drivers: ad559x: add i2c bus support

Rename ad5592 files in dts, driver and include to ad559x and add support
for I2C bus which is required for AD5593.

Signed-off-by: Jeppe Odgaard <jeppe.odgaard@prevas.dk>
This commit is contained in:
Jeppe Odgaard 2024-01-24 09:05:09 +01:00 committed by Maureen Helm
parent 2a5dc2a0df
commit 17b1912bc3
39 changed files with 1226 additions and 936 deletions

View file

@ -167,7 +167,7 @@
/drivers/adc/*ads114s0x* @benediktibk
/drivers/adc/*max11102_17* @benediktibk
/drivers/adc/*kb1200* @ene-steven
/drivers/adc/adc_ad5592.c @bbilas
/drivers/adc/adc_ad559x.c @bbilas
/drivers/audio/*nrfx* @anangl
/drivers/auxdisplay/*pt6314* @xingrz
/drivers/auxdisplay/* @thedjnK
@ -192,7 +192,7 @@
/drivers/display/*rm68200* @mmahadevan108
/drivers/display/display_ili9342c.* @extremegtx
/drivers/dac/*ad56xx* @benediktibk
/drivers/dac/dac_ad5592.c @bbilas
/drivers/dac/dac_ad559x.c @bbilas
/drivers/dai/ @kv2019i @marcinszkudlinski @abonislawski
/drivers/dai/intel/ @kv2019i @marcinszkudlinski @abonislawski
/drivers/dai/intel/ssp/ @kv2019i @marcinszkudlinski @abonislawski
@ -244,7 +244,7 @@
/drivers/gpio/*pcal64xxa* @benediktibk
/drivers/gpio/*kb1200* @ene-steven
/drivers/gpio/gpio_altera_pio.c @shilinte
/drivers/gpio/gpio_ad5592.c @bbilas
/drivers/gpio/gpio_ad559x.c @bbilas
/drivers/i2c/i2c_common.c @sjg20
/drivers/i2c/i2c_emul.c @sjg20
/drivers/i2c/i2c_ite_enhance.c @GTLin08
@ -284,7 +284,7 @@
/drivers/kscan/*ft5336* @MaureenHelm
/drivers/kscan/*ht16k33* @henrikbrixandersen
/drivers/led_strip/ @mbolivar-ampere
/drivers/mfd/mfd_ad5592.c @bbilas
/drivers/mfd/mfd_ad559x.c @bbilas
/drivers/mfd/mfd_max20335.c @bbilas
/drivers/misc/ft8xx/ @hubertmis
/drivers/modem/hl7800.c @rerickson1

View file

@ -46,7 +46,7 @@ zephyr_library_sources_ifdef(CONFIG_ADC_TLA2021 adc_tla2021.c)
zephyr_library_sources_ifdef(CONFIG_ADC_NXP_S32_ADC_SAR adc_nxp_s32_adc_sar.c)
zephyr_library_sources_ifdef(CONFIG_ADC_MAX1125X adc_max1125x.c)
zephyr_library_sources_ifdef(CONFIG_ADC_MAX11102_17 adc_max11102_17.c)
zephyr_library_sources_ifdef(CONFIG_ADC_AD5592 adc_ad5592.c)
zephyr_library_sources_ifdef(CONFIG_ADC_AD559X adc_ad559x.c)
zephyr_library_sources_ifdef(CONFIG_ADC_LTC2451 adc_ltc2451.c)
zephyr_library_sources_ifdef(CONFIG_ADC_NUMAKER adc_numaker.c)
zephyr_library_sources_ifdef(CONFIG_ADC_ENE_KB1200 adc_ene_kb1200.c)

View file

@ -120,7 +120,7 @@ source "drivers/adc/Kconfig.max1125x"
source "drivers/adc/Kconfig.max11102_17"
source "drivers/adc/Kconfig.ad5592"
source "drivers/adc/Kconfig.ad559x"
source "drivers/adc/Kconfig.ltc2451"

View file

@ -1,25 +1,25 @@
# Copyright (c) 2023 Grinn
# SPDX -License-Identifier: Apache-2.0
config ADC_AD5592
bool "AD5592 ADC driver"
config ADC_AD559X
bool "AD559x ADC driver"
default y
depends on DT_HAS_ADI_AD5592_ADC_ENABLED
depends on DT_HAS_ADI_AD559X_ADC_ENABLED
select MFD
help
Enable the AD5592 ADC driver.
Enable the AD559x ADC driver.
config ADC_AD5592_ACQUISITION_THREAD_STACK_SIZE
config ADC_AD559X_ACQUISITION_THREAD_STACK_SIZE
int "Stack size for the ADC data acquisition thread"
depends on ADC_AD5592
depends on ADC_AD559X
default 384
help
Size of the stack used for the internal data acquisition
thread.
config ADC_AD5592_ACQUISITION_THREAD_PRIO
config ADC_AD559X_ACQUISITION_THREAD_PRIO
int "Priority for the ADC data acquisition thread"
depends on ADC_AD5592
depends on ADC_AD559X
default 0
help
Priority level for the internal ADC data acquisition thread.

View file

@ -1,255 +0,0 @@
/*
* Copyright (c) 2023 Grinn
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT adi_ad5592_adc
#include <zephyr/drivers/adc.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/drivers/mfd/ad5592.h>
#define ADC_CONTEXT_USES_KERNEL_TIMER
#include "adc_context.h"
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(adc_ad5592, CONFIG_ADC_LOG_LEVEL);
#define AD5592_ADC_RESOLUTION 12U
#define AD5592_ADC_MAX_VAL 4096
struct adc_ad5592_config {
const struct device *mfd_dev;
};
struct adc_ad5592_data {
struct adc_context ctx;
const struct device *dev;
uint8_t adc_conf;
uint16_t *buffer;
uint16_t *repeat_buffer;
uint8_t channels;
struct k_thread thread;
struct k_sem sem;
K_KERNEL_STACK_MEMBER(stack, CONFIG_ADC_AD5592_ACQUISITION_THREAD_STACK_SIZE);
};
static int adc_ad5592_channel_setup(const struct device *dev,
const struct adc_channel_cfg *channel_cfg)
{
const struct adc_ad5592_config *config = dev->config;
struct adc_ad5592_data *data = dev->data;
if (channel_cfg->channel_id >= AD5592_PIN_MAX) {
LOG_ERR("invalid channel id %d", channel_cfg->channel_id);
return -EINVAL;
}
data->adc_conf |= BIT(channel_cfg->channel_id);
return mfd_ad5592_write_reg(config->mfd_dev, AD5592_REG_ADC_CONFIG, data->adc_conf);
}
static int adc_ad5592_validate_buffer_size(const struct device *dev,
const struct adc_sequence *sequence)
{
uint8_t channels;
size_t needed;
channels = POPCOUNT(sequence->channels);
needed = channels * sizeof(uint16_t);
if (sequence->buffer_size < needed) {
return -ENOMEM;
}
return 0;
}
static int adc_ad5592_start_read(const struct device *dev, const struct adc_sequence *sequence)
{
struct adc_ad5592_data *data = dev->data;
int ret;
if (sequence->resolution != AD5592_ADC_RESOLUTION) {
LOG_ERR("invalid resolution %d", sequence->resolution);
return -EINVAL;
}
if (find_msb_set(sequence->channels) > AD5592_PIN_MAX) {
LOG_ERR("invalid channels in mask: 0x%08x", sequence->channels);
return -EINVAL;
}
ret = adc_ad5592_validate_buffer_size(dev, sequence);
if (ret < 0) {
LOG_ERR("insufficient buffer size");
return ret;
}
data->buffer = sequence->buffer;
adc_context_start_read(&data->ctx, sequence);
return adc_context_wait_for_completion(&data->ctx);
}
static int adc_ad5592_read_channel(const struct device *dev, uint8_t channel, uint16_t *result)
{
const struct adc_ad5592_config *config = dev->config;
uint16_t val;
int ret;
ret = mfd_ad5592_write_reg(config->mfd_dev, AD5592_REG_SEQ_ADC, BIT(channel));
if (ret < 0) {
return ret;
}
/*
* Invalid data:
* See Figure 46. Single-Channel ADC Conversion Sequence.
* The first conversion result always returns invalid data.
*/
(void) mfd_ad5592_read_raw(config->mfd_dev, &val);
ret = mfd_ad5592_read_raw(config->mfd_dev, &val);
if (ret < 0) {
return ret;
}
val = sys_be16_to_cpu(val);
if (channel >= 1) {
val -= channel * AD5592_ADC_MAX_VAL;
}
*result = val;
return 0;
}
static void adc_context_start_sampling(struct adc_context *ctx)
{
struct adc_ad5592_data *data = CONTAINER_OF(ctx, struct adc_ad5592_data, ctx);
data->channels = ctx->sequence.channels;
data->repeat_buffer = data->buffer;
k_sem_give(&data->sem);
}
static void adc_context_update_buffer_pointer(struct adc_context *ctx,
bool repeat_sampling)
{
struct adc_ad5592_data *data = CONTAINER_OF(ctx, struct adc_ad5592_data, ctx);
if (repeat_sampling) {
data->buffer = data->repeat_buffer;
}
}
static void adc_ad5592_acquisition_thread(struct adc_ad5592_data *data)
{
uint16_t result;
uint8_t channel;
int ret;
while (true) {
k_sem_take(&data->sem, K_FOREVER);
while (data->channels != 0) {
channel = find_lsb_set(data->channels) - 1;
ret = adc_ad5592_read_channel(data->dev, channel, &result);
if (ret < 0) {
LOG_ERR("failed to read channel %d (ret %d)", channel, ret);
adc_context_complete(&data->ctx, ret);
break;
}
*data->buffer++ = result;
WRITE_BIT(data->channels, channel, 0);
}
adc_context_on_sampling_done(&data->ctx, data->dev);
}
}
static int adc_ad5592_read_async(const struct device *dev,
const struct adc_sequence *sequence,
struct k_poll_signal *async)
{
struct adc_ad5592_data *data = dev->data;
int ret;
adc_context_lock(&data->ctx, async ? true : false, async);
ret = adc_ad5592_start_read(dev, sequence);
adc_context_release(&data->ctx, ret);
return ret;
}
static int adc_ad5592_read(const struct device *dev,
const struct adc_sequence *sequence)
{
return adc_ad5592_read_async(dev, sequence, NULL);
}
static int adc_ad5592_init(const struct device *dev)
{
const struct adc_ad5592_config *config = dev->config;
struct adc_ad5592_data *data = dev->data;
k_tid_t tid;
int ret;
if (!device_is_ready(config->mfd_dev)) {
return -ENODEV;
}
ret = mfd_ad5592_write_reg(config->mfd_dev, AD5592_REG_PD_REF_CTRL, AD5592_EN_REF);
if (ret < 0) {
return ret;
}
data->dev = dev;
k_sem_init(&data->sem, 0, 1);
adc_context_init(&data->ctx);
tid = k_thread_create(&data->thread, data->stack,
K_KERNEL_STACK_SIZEOF(data->stack),
(k_thread_entry_t)adc_ad5592_acquisition_thread, data, NULL, NULL,
CONFIG_ADC_AD5592_ACQUISITION_THREAD_PRIO, 0, K_NO_WAIT);
ret = k_thread_name_set(tid, "adc_ad5592");
if (ret < 0) {
return ret;
}
adc_context_unlock_unconditionally(&data->ctx);
return 0;
}
static const struct adc_driver_api adc_ad5592_api = {
.channel_setup = adc_ad5592_channel_setup,
.read = adc_ad5592_read,
#ifdef CONFIG_ADC_ASYNC
.read_async = adc_ad5592_read_async,
#endif
};
#define ADC_AD5592_DEFINE(inst) \
static const struct adc_ad5592_config adc_ad5592_config##inst = { \
.mfd_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
}; \
\
static struct adc_ad5592_data adc_ad5592_data##inst; \
\
DEVICE_DT_INST_DEFINE(inst, adc_ad5592_init, NULL, \
&adc_ad5592_data##inst, &adc_ad5592_config##inst, \
POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, \
&adc_ad5592_api);
DT_INST_FOREACH_STATUS_OKAY(ADC_AD5592_DEFINE)

273
drivers/adc/adc_ad559x.c Normal file
View file

@ -0,0 +1,273 @@
/*
* Copyright (c) 2023 Grinn
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT adi_ad559x_adc
#include <zephyr/drivers/adc.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/drivers/mfd/ad559x.h>
#define ADC_CONTEXT_USES_KERNEL_TIMER
#include "adc_context.h"
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(adc_ad559x, CONFIG_ADC_LOG_LEVEL);
#define AD559X_ADC_RD_POINTER_SIZE 1
#define AD559X_ADC_RD_POINTER 0x40
#define AD559X_ADC_RESOLUTION 12U
struct adc_ad559x_config {
const struct device *mfd_dev;
};
struct adc_ad559x_data {
struct adc_context ctx;
const struct device *dev;
uint8_t adc_conf;
uint16_t *buffer;
uint16_t *repeat_buffer;
uint8_t channels;
struct k_thread thread;
struct k_sem sem;
K_KERNEL_STACK_MEMBER(stack, CONFIG_ADC_AD559X_ACQUISITION_THREAD_STACK_SIZE);
};
static int adc_ad559x_channel_setup(const struct device *dev,
const struct adc_channel_cfg *channel_cfg)
{
const struct adc_ad559x_config *config = dev->config;
struct adc_ad559x_data *data = dev->data;
if (channel_cfg->channel_id >= AD559X_PIN_MAX) {
LOG_ERR("invalid channel id %d", channel_cfg->channel_id);
return -EINVAL;
}
data->adc_conf |= BIT(channel_cfg->channel_id);
return mfd_ad559x_write_reg(config->mfd_dev, AD559X_REG_ADC_CONFIG, data->adc_conf);
}
static int adc_ad559x_validate_buffer_size(const struct device *dev,
const struct adc_sequence *sequence)
{
uint8_t channels;
size_t needed;
channels = POPCOUNT(sequence->channels);
needed = channels * sizeof(uint16_t);
if (sequence->buffer_size < needed) {
return -ENOMEM;
}
return 0;
}
static int adc_ad559x_start_read(const struct device *dev, const struct adc_sequence *sequence)
{
struct adc_ad559x_data *data = dev->data;
int ret;
if (sequence->resolution != AD559X_ADC_RESOLUTION) {
LOG_ERR("invalid resolution %d", sequence->resolution);
return -EINVAL;
}
if (find_msb_set(sequence->channels) > AD559X_PIN_MAX) {
LOG_ERR("invalid channels in mask: 0x%08x", sequence->channels);
return -EINVAL;
}
ret = adc_ad559x_validate_buffer_size(dev, sequence);
if (ret < 0) {
LOG_ERR("insufficient buffer size");
return ret;
}
data->buffer = sequence->buffer;
adc_context_start_read(&data->ctx, sequence);
return adc_context_wait_for_completion(&data->ctx);
}
static int adc_ad559x_read_channel(const struct device *dev, uint8_t channel, uint16_t *result)
{
const struct adc_ad559x_config *config = dev->config;
uint16_t val;
int ret;
/* Select channel */
ret = mfd_ad559x_write_reg(config->mfd_dev, AD559X_REG_SEQ_ADC, BIT(channel));
if (ret < 0) {
return ret;
}
if (mfd_ad559x_has_pointer_byte_map(config->mfd_dev)) {
/* Start readback */
val = AD559X_ADC_RD_POINTER;
ret = mfd_ad559x_write_raw(config->mfd_dev, (uint8_t *)&val,
AD559X_ADC_RD_POINTER_SIZE);
if (ret < 0) {
return ret;
}
/* Read channel */
ret = mfd_ad559x_read_raw(config->mfd_dev, (uint8_t *)&val, sizeof(val));
if (ret < 0) {
return ret;
}
*result = sys_get_be16((uint8_t *)&val);
} else {
/*
* Invalid data:
* See Figure 46. Single-Channel ADC Conversion Sequence.
* The first conversion result always returns invalid data.
*/
(void)mfd_ad559x_read_raw(config->mfd_dev, (uint8_t *)&val, sizeof(val));
ret = mfd_ad559x_read_raw(config->mfd_dev, (uint8_t *)&val, sizeof(val));
if (ret < 0) {
return ret;
}
val = sys_be16_to_cpu(val);
if (channel >= 1) {
val -= channel * BIT(AD559X_ADC_RESOLUTION);
}
*result = val;
}
return 0;
}
static void adc_context_start_sampling(struct adc_context *ctx)
{
struct adc_ad559x_data *data = CONTAINER_OF(ctx, struct adc_ad559x_data, ctx);
data->channels = ctx->sequence.channels;
data->repeat_buffer = data->buffer;
k_sem_give(&data->sem);
}
static void adc_context_update_buffer_pointer(struct adc_context *ctx, bool repeat_sampling)
{
struct adc_ad559x_data *data = CONTAINER_OF(ctx, struct adc_ad559x_data, ctx);
if (repeat_sampling) {
data->buffer = data->repeat_buffer;
}
}
static void adc_ad559x_acquisition_thread(struct adc_ad559x_data *data)
{
uint16_t result;
uint8_t channel;
int ret;
while (true) {
k_sem_take(&data->sem, K_FOREVER);
while (data->channels != 0) {
channel = find_lsb_set(data->channels) - 1;
ret = adc_ad559x_read_channel(data->dev, channel, &result);
if (ret < 0) {
LOG_ERR("failed to read channel %d (ret %d)", channel, ret);
adc_context_complete(&data->ctx, ret);
break;
}
*data->buffer++ = result;
WRITE_BIT(data->channels, channel, 0);
}
adc_context_on_sampling_done(&data->ctx, data->dev);
}
}
static int adc_ad559x_read_async(const struct device *dev, const struct adc_sequence *sequence,
struct k_poll_signal *async)
{
struct adc_ad559x_data *data = dev->data;
int ret;
adc_context_lock(&data->ctx, async ? true : false, async);
ret = adc_ad559x_start_read(dev, sequence);
adc_context_release(&data->ctx, ret);
return ret;
}
static int adc_ad559x_read(const struct device *dev, const struct adc_sequence *sequence)
{
return adc_ad559x_read_async(dev, sequence, NULL);
}
static int adc_ad559x_init(const struct device *dev)
{
const struct adc_ad559x_config *config = dev->config;
struct adc_ad559x_data *data = dev->data;
k_tid_t tid;
int ret;
if (!device_is_ready(config->mfd_dev)) {
return -ENODEV;
}
ret = mfd_ad559x_write_reg(config->mfd_dev, AD559X_REG_PD_REF_CTRL, AD559X_EN_REF);
if (ret < 0) {
return ret;
}
data->dev = dev;
k_sem_init(&data->sem, 0, 1);
adc_context_init(&data->ctx);
tid = k_thread_create(&data->thread, data->stack,
K_KERNEL_STACK_SIZEOF(data->stack),
(k_thread_entry_t)adc_ad559x_acquisition_thread, data, NULL, NULL,
CONFIG_ADC_AD559X_ACQUISITION_THREAD_PRIO, 0, K_NO_WAIT);
ret = k_thread_name_set(tid, "adc_ad559x");
if (ret < 0) {
return ret;
}
adc_context_unlock_unconditionally(&data->ctx);
return 0;
}
static const struct adc_driver_api adc_ad559x_api = {
.channel_setup = adc_ad559x_channel_setup,
.read = adc_ad559x_read,
#ifdef CONFIG_ADC_ASYNC
.read_async = adc_ad559x_read_async,
#endif
};
#define ADC_AD559X_DEFINE(inst) \
static const struct adc_ad559x_config adc_ad559x_config##inst = { \
.mfd_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
}; \
\
static struct adc_ad559x_data adc_ad559x_data##inst; \
\
DEVICE_DT_INST_DEFINE(inst, adc_ad559x_init, NULL, &adc_ad559x_data##inst, \
&adc_ad559x_config##inst, POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, \
&adc_ad559x_api);
DT_INST_FOREACH_STATUS_OKAY(ADC_AD559X_DEFINE)

View file

@ -75,7 +75,7 @@ static struct adc_hdl {
uint8_t resolution;
} adc_list[] = {
/* zephyr-keep-sorted-start */
DT_FOREACH_STATUS_OKAY(adi_ad5592_adc, ADC_HDL_LIST_ENTRY)
DT_FOREACH_STATUS_OKAY(adi_ad559x_adc, ADC_HDL_LIST_ENTRY)
DT_FOREACH_STATUS_OKAY(atmel_sam0_adc, ADC_HDL_LIST_ENTRY)
DT_FOREACH_STATUS_OKAY(atmel_sam_adc, ADC_HDL_LIST_ENTRY)
DT_FOREACH_STATUS_OKAY(atmel_sam_afec, ADC_HDL_LIST_ENTRY)

View file

@ -18,6 +18,6 @@ zephyr_library_sources_ifdef(CONFIG_DAC_MCP4725 dac_mcp4725.c)
zephyr_library_sources_ifdef(CONFIG_DAC_MCP4728 dac_mcp4728.c)
zephyr_library_sources_ifdef(CONFIG_DAC_GD32 dac_gd32.c)
zephyr_library_sources_ifdef(CONFIG_DAC_ESP32 dac_esp32.c)
zephyr_library_sources_ifdef(CONFIG_DAC_AD5592 dac_ad5592.c)
zephyr_library_sources_ifdef(CONFIG_DAC_AD559X dac_ad559x.c)
zephyr_library_sources_ifdef(CONFIG_DAC_AD56XX dac_ad56xx.c)
zephyr_library_sources_ifdef(CONFIG_USERSPACE dac_handlers.c)

View file

@ -53,6 +53,6 @@ source "drivers/dac/Kconfig.esp32"
source "drivers/dac/Kconfig.ad56xx"
source "drivers/dac/Kconfig.ad5592"
source "drivers/dac/Kconfig.ad559x"
endif # DAC

View file

@ -1,10 +0,0 @@
# Copyright (c) 2023 Grinn
# SPDX -License-Identifier: Apache-2.0
config DAC_AD5592
bool "AD5592 DAC driver"
default y
depends on DT_HAS_ADI_AD5592_DAC_ENABLED
select MFD
help
Enable the AD5592 DAC driver.

View file

@ -0,0 +1,10 @@
# Copyright (c) 2023 Grinn
# SPDX -License-Identifier: Apache-2.0
config DAC_AD559X
bool "AD559x DAC driver"
default y
depends on DT_HAS_ADI_AD559X_DAC_ENABLED
select MFD
help
Enable the AD559x DAC driver.

View file

@ -1,107 +0,0 @@
/*
* Copyright (c) 2023 Grinn
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT adi_ad5592_dac
#include <zephyr/drivers/dac.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/drivers/mfd/ad5592.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(dac_ad5592, CONFIG_DAC_LOG_LEVEL);
#define AD5592_DAC_RESOLUTION 12
#define AD5592_DAC_WR_MSB_BIT BIT(15)
#define AD5592_DAC_CHANNEL_SHIFT_VAL 12
struct dac_ad5592_config {
const struct device *mfd_dev;
};
struct dac_ad5592_data {
uint8_t dac_conf;
};
static int dac_ad5592_channel_setup(const struct device *dev,
const struct dac_channel_cfg *channel_cfg)
{
const struct dac_ad5592_config *config = dev->config;
struct dac_ad5592_data *data = dev->data;
if (channel_cfg->channel_id >= AD5592_PIN_MAX) {
LOG_ERR("Invalid channel number %d", channel_cfg->channel_id);
return -EINVAL;
}
if (channel_cfg->resolution != AD5592_DAC_RESOLUTION) {
LOG_ERR("Invalid resolution %d", channel_cfg->resolution);
return -EINVAL;
}
data->dac_conf |= BIT(channel_cfg->channel_id);
return mfd_ad5592_write_reg(config->mfd_dev, AD5592_REG_LDAC_EN, data->dac_conf);
}
static int dac_ad5592_write_value(const struct device *dev, uint8_t channel,
uint32_t value)
{
const struct dac_ad5592_config *config = dev->config;
uint16_t msg;
if (channel >= AD5592_PIN_MAX) {
LOG_ERR("Invalid channel number %d", channel);
return -EINVAL;
}
if (value >= (1 << AD5592_DAC_RESOLUTION)) {
LOG_ERR("Value %d out of range", value);
return -EINVAL;
}
msg = sys_cpu_to_be16(AD5592_DAC_WR_MSB_BIT |
channel << AD5592_DAC_CHANNEL_SHIFT_VAL |
value);
return mfd_ad5592_write_raw(config->mfd_dev, msg);
}
static const struct dac_driver_api dac_ad5592_api = {
.channel_setup = dac_ad5592_channel_setup,
.write_value = dac_ad5592_write_value,
};
static int dac_ad5592_init(const struct device *dev)
{
const struct dac_ad5592_config *config = dev->config;
int ret;
if (!device_is_ready(config->mfd_dev)) {
return -ENODEV;
}
ret = mfd_ad5592_write_reg(config->mfd_dev, AD5592_REG_PD_REF_CTRL, AD5592_EN_REF);
if (ret < 0) {
return ret;
}
return 0;
}
#define DAC_AD5592_DEFINE(inst) \
static const struct dac_ad5592_config dac_ad5592_config##inst = { \
.mfd_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
}; \
\
struct dac_ad5592_data dac_ad5592_data##inst; \
\
DEVICE_DT_INST_DEFINE(inst, dac_ad5592_init, NULL, \
&dac_ad5592_data##inst, &dac_ad5592_config##inst, \
POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, \
&dac_ad5592_api);
DT_INST_FOREACH_STATUS_OKAY(DAC_AD5592_DEFINE)

110
drivers/dac/dac_ad559x.c Normal file
View file

@ -0,0 +1,110 @@
/*
* Copyright (c) 2023 Grinn
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT adi_ad559x_dac
#include <zephyr/drivers/dac.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/drivers/mfd/ad559x.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(dac_ad559x, CONFIG_DAC_LOG_LEVEL);
#define AD559X_DAC_RESOLUTION 12
#define AD559X_DAC_WR_POINTER 0x10
#define AD559X_DAC_WR_MSB_BIT BIT(15)
#define AD559X_DAC_CHANNEL_SHIFT_VAL 12
struct dac_ad559x_config {
const struct device *mfd_dev;
};
struct dac_ad559x_data {
uint8_t dac_conf;
};
static int dac_ad559x_channel_setup(const struct device *dev,
const struct dac_channel_cfg *channel_cfg)
{
const struct dac_ad559x_config *config = dev->config;
struct dac_ad559x_data *data = dev->data;
if (channel_cfg->channel_id >= AD559X_PIN_MAX) {
LOG_ERR("Invalid channel number %d", channel_cfg->channel_id);
return -EINVAL;
}
if (channel_cfg->resolution != AD559X_DAC_RESOLUTION) {
LOG_ERR("Invalid resolution %d", channel_cfg->resolution);
return -EINVAL;
}
data->dac_conf |= BIT(channel_cfg->channel_id);
return mfd_ad559x_write_reg(config->mfd_dev, AD559X_REG_LDAC_EN, data->dac_conf);
}
static int dac_ad559x_write_value(const struct device *dev, uint8_t channel, uint32_t value)
{
const struct dac_ad559x_config *config = dev->config;
uint16_t msg;
if (channel >= AD559X_PIN_MAX) {
LOG_ERR("Invalid channel number %d", channel);
return -EINVAL;
}
if (value >= (1 << AD559X_DAC_RESOLUTION)) {
LOG_ERR("Value %d out of range", value);
return -EINVAL;
}
if (mfd_ad559x_has_pointer_byte_map(config->mfd_dev)) {
return mfd_ad559x_write_reg(config->mfd_dev, AD559X_DAC_WR_POINTER | channel,
value);
} else {
msg = sys_cpu_to_be16(AD559X_DAC_WR_MSB_BIT |
channel << AD559X_DAC_CHANNEL_SHIFT_VAL | value);
return mfd_ad559x_write_raw(config->mfd_dev, (uint8_t *)&msg, sizeof(msg));
}
}
static const struct dac_driver_api dac_ad559x_api = {
.channel_setup = dac_ad559x_channel_setup,
.write_value = dac_ad559x_write_value,
};
static int dac_ad559x_init(const struct device *dev)
{
const struct dac_ad559x_config *config = dev->config;
int ret;
if (!device_is_ready(config->mfd_dev)) {
return -ENODEV;
}
ret = mfd_ad559x_write_reg(config->mfd_dev, AD559X_REG_PD_REF_CTRL, AD559X_EN_REF);
if (ret < 0) {
return ret;
}
return 0;
}
#define DAC_AD559X_DEFINE(inst) \
static const struct dac_ad559x_config dac_ad559x_config##inst = { \
.mfd_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
}; \
\
struct dac_ad559x_data dac_ad559x_data##inst; \
\
DEVICE_DT_INST_DEFINE(inst, dac_ad559x_init, NULL, &dac_ad559x_data##inst, \
&dac_ad559x_config##inst, POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, \
&dac_ad559x_api);
DT_INST_FOREACH_STATUS_OKAY(DAC_AD559X_DEFINE)

View file

@ -4,7 +4,7 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/gpio.h)
zephyr_library()
zephyr_library_sources_ifdef(CONFIG_GPIO_AD5592 gpio_ad5592.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_AD559X gpio_ad559x.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_AXP192 gpio_axp192.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_TELINK_B91 gpio_b91.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_INFINEON_CAT1 gpio_ifx_cat1.c)

View file

@ -87,7 +87,7 @@ config GPIO_ENABLE_DISABLE_INTERRUPT
pending register, etc. The driver must implement it to work.
source "drivers/gpio/Kconfig.ad5592"
source "drivers/gpio/Kconfig.ad559x"
source "drivers/gpio/Kconfig.axp192"

View file

@ -1,10 +0,0 @@
# Copyright (c) 2023 Grinn
# SPDX-License-Identifier: Apache-2.0
config GPIO_AD5592
bool "AD5592 GPIO driver"
default y
depends on DT_HAS_ADI_AD5592_GPIO_ENABLED
select MFD
help
Enable the AD5592 GPIO driver.

View file

@ -0,0 +1,10 @@
# Copyright (c) 2023 Grinn
# SPDX-License-Identifier: Apache-2.0
config GPIO_AD559X
bool "AD559x GPIO driver"
default y
depends on DT_HAS_ADI_AD559X_GPIO_ENABLED
select MFD
help
Enable the AD559x GPIO driver.

View file

@ -1,227 +0,0 @@
/*
* Copyright (c) 2023 Grinn
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT adi_ad5592_gpio
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/gpio/gpio_utils.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/drivers/mfd/ad5592.h>
struct gpio_ad5592_config {
/* gpio_driver_config needs to be first */
struct gpio_driver_config common;
const struct device *mfd_dev;
};
struct gpio_ad5592_data {
/* gpio_driver_data needs to be first */
struct gpio_driver_data common;
uint8_t gpio_val;
uint8_t gpio_out;
uint8_t gpio_in;
uint8_t gpio_pull_down;
};
static int gpio_ad5592_port_get_raw(const struct device *dev, uint32_t *value)
{
const struct gpio_ad5592_config *config = dev->config;
struct gpio_ad5592_data *drv_data = dev->data;
uint16_t data;
int ret;
if (k_is_in_isr()) {
return -EWOULDBLOCK;
}
ret = mfd_ad5592_read_reg(config->mfd_dev,
AD5592_REG_GPIO_INPUT_EN, drv_data->gpio_in, &data);
if (ret < 0) {
return ret;
}
*value = (uint32_t)data;
return 0;
}
static int gpio_ad5592_port_set_bits_raw(const struct device *dev,
gpio_port_pins_t pins)
{
struct gpio_ad5592_data *data = dev->data;
const struct gpio_ad5592_config *config = dev->config;
if (k_is_in_isr()) {
return -EWOULDBLOCK;
}
data->gpio_val |= (uint8_t)pins;
return mfd_ad5592_write_reg(config->mfd_dev, AD5592_REG_GPIO_SET, data->gpio_val);
}
static int gpio_ad5592_port_clear_bits_raw(const struct device *dev,
gpio_port_pins_t pins)
{
struct gpio_ad5592_data *data = dev->data;
const struct gpio_ad5592_config *config = dev->config;
if (k_is_in_isr()) {
return -EWOULDBLOCK;
}
data->gpio_val &= ~(uint8_t)pins;
return mfd_ad5592_write_reg(config->mfd_dev, AD5592_REG_GPIO_SET, data->gpio_val);
}
static inline int gpio_ad5592_configure(const struct device *dev,
gpio_pin_t pin, gpio_flags_t flags)
{
struct gpio_ad5592_data *data = dev->data;
const struct gpio_ad5592_config *config = dev->config;
uint8_t val;
int ret;
if (k_is_in_isr()) {
return -EWOULDBLOCK;
}
if (pin >= AD5592_PIN_MAX) {
return -EINVAL;
}
val = BIT(pin);
if ((flags & GPIO_OUTPUT) != 0U) {
data->gpio_in &= ~val;
data->gpio_out |= val;
if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) {
ret = gpio_ad5592_port_set_bits_raw(
dev, (gpio_port_pins_t)BIT(pin));
if (ret < 0) {
return ret;
}
} else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0U) {
ret = gpio_ad5592_port_clear_bits_raw(
dev, (gpio_port_pins_t)BIT(pin));
if (ret < 0) {
return ret;
}
}
ret = mfd_ad5592_write_reg(config->mfd_dev,
AD5592_REG_GPIO_OUTPUT_EN, data->gpio_out);
if (ret < 0) {
return ret;
}
ret = mfd_ad5592_write_reg(config->mfd_dev,
AD5592_REG_GPIO_INPUT_EN, data->gpio_in);
} else if ((flags & GPIO_INPUT) != 0U) {
data->gpio_in |= val;
data->gpio_out &= ~val;
if ((flags & GPIO_PULL_DOWN) != 0U) {
data->gpio_pull_down |= val;
ret = mfd_ad5592_write_reg(config->mfd_dev,
AD5592_REG_GPIO_PULLDOWN,
data->gpio_pull_down);
if (ret < 0) {
return ret;
}
} else if ((flags & GPIO_PULL_UP) != 0U) {
return -ENOTSUP;
}
ret = mfd_ad5592_write_reg(config->mfd_dev,
AD5592_REG_GPIO_OUTPUT_EN, data->gpio_out);
if (ret < 0) {
return ret;
}
ret = mfd_ad5592_write_reg(config->mfd_dev,
AD5592_REG_GPIO_INPUT_EN, data->gpio_in);
} else {
return -ENOTSUP;
}
return ret;
}
static int gpio_ad5592_port_set_masked_raw(const struct device *dev,
gpio_port_pins_t mask,
gpio_port_value_t value)
{
ARG_UNUSED(dev);
ARG_UNUSED(mask);
ARG_UNUSED(value);
return -ENOTSUP;
}
static int gpio_ad5592_port_toggle_bits(const struct device *dev,
gpio_port_pins_t pins)
{
ARG_UNUSED(dev);
ARG_UNUSED(pins);
return -ENOTSUP;
}
static int gpio_ad5592_pin_interrupt_configure(const struct device *dev,
gpio_pin_t pin,
enum gpio_int_mode mode,
enum gpio_int_trig trig)
{
ARG_UNUSED(dev);
ARG_UNUSED(pin);
ARG_UNUSED(mode);
ARG_UNUSED(trig);
return -ENOTSUP;
}
static const struct gpio_driver_api gpio_ad5592_api = {
.pin_configure = gpio_ad5592_configure,
.port_get_raw = gpio_ad5592_port_get_raw,
.port_set_masked_raw = gpio_ad5592_port_set_masked_raw,
.port_set_bits_raw = gpio_ad5592_port_set_bits_raw,
.port_clear_bits_raw = gpio_ad5592_port_clear_bits_raw,
.port_toggle_bits = gpio_ad5592_port_toggle_bits,
.pin_interrupt_configure = gpio_ad5592_pin_interrupt_configure,
};
static int gpio_ad5592_init(const struct device *dev)
{
const struct gpio_ad5592_config *config = dev->config;
if (!device_is_ready(config->mfd_dev)) {
return -ENODEV;
}
return 0;
}
#define GPIO_AD5592_DEFINE(inst) \
static const struct gpio_ad5592_config gpio_ad5592_config##inst = { \
.common = { \
.port_pin_mask = \
GPIO_PORT_PIN_MASK_FROM_DT_INST(inst), \
}, \
.mfd_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
}; \
\
static struct gpio_ad5592_data gpio_ad5592_data##inst; \
\
DEVICE_DT_INST_DEFINE(inst, gpio_ad5592_init, NULL, \
&gpio_ad5592_data##inst, &gpio_ad5592_config##inst, \
POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, \
&gpio_ad5592_api);
DT_INST_FOREACH_STATUS_OKAY(GPIO_AD5592_DEFINE)

236
drivers/gpio/gpio_ad559x.c Normal file
View file

@ -0,0 +1,236 @@
/*
* Copyright (c) 2023 Grinn
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT adi_ad559x_gpio
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/gpio/gpio_utils.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/drivers/mfd/ad559x.h>
#define AD559X_GPIO_RD_POINTER 0x60
struct gpio_ad559x_config {
/* gpio_driver_config needs to be first */
struct gpio_driver_config common;
const struct device *mfd_dev;
};
struct gpio_ad559x_data {
/* gpio_driver_data needs to be first */
struct gpio_driver_data common;
uint8_t gpio_val;
uint8_t gpio_out;
uint8_t gpio_in;
uint8_t gpio_pull_down;
};
static int gpio_ad559x_port_get_raw(const struct device *dev, uint32_t *value)
{
const struct gpio_ad559x_config *config = dev->config;
struct gpio_ad559x_data *drv_data = dev->data;
uint16_t data;
int ret;
if (k_is_in_isr()) {
return -EWOULDBLOCK;
}
if (mfd_ad559x_has_pointer_byte_map(config->mfd_dev)) {
ret = mfd_ad559x_read_reg(config->mfd_dev, AD559X_GPIO_RD_POINTER, 0, &data);
/* LSB contains port information. Clear the MSB. */
data &= BIT_MASK(AD559X_PIN_MAX);
} else {
ret = mfd_ad559x_read_reg(config->mfd_dev, AD559X_REG_GPIO_INPUT_EN,
drv_data->gpio_in, &data);
}
if (ret < 0) {
return ret;
}
*value = (uint32_t)data;
return 0;
}
static int gpio_ad559x_port_set_bits_raw(const struct device *dev,
gpio_port_pins_t pins)
{
struct gpio_ad559x_data *data = dev->data;
const struct gpio_ad559x_config *config = dev->config;
if (k_is_in_isr()) {
return -EWOULDBLOCK;
}
data->gpio_val |= (uint8_t)pins;
return mfd_ad559x_write_reg(config->mfd_dev, AD559X_REG_GPIO_SET, data->gpio_val);
}
static int gpio_ad559x_port_clear_bits_raw(const struct device *dev,
gpio_port_pins_t pins)
{
struct gpio_ad559x_data *data = dev->data;
const struct gpio_ad559x_config *config = dev->config;
if (k_is_in_isr()) {
return -EWOULDBLOCK;
}
data->gpio_val &= ~(uint8_t)pins;
return mfd_ad559x_write_reg(config->mfd_dev, AD559X_REG_GPIO_SET, data->gpio_val);
}
static inline int gpio_ad559x_configure(const struct device *dev,
gpio_pin_t pin, gpio_flags_t flags)
{
struct gpio_ad559x_data *data = dev->data;
const struct gpio_ad559x_config *config = dev->config;
uint8_t val;
int ret;
if (k_is_in_isr()) {
return -EWOULDBLOCK;
}
if (pin >= AD559X_PIN_MAX) {
return -EINVAL;
}
val = BIT(pin);
if ((flags & GPIO_OUTPUT) != 0U) {
data->gpio_in &= ~val;
data->gpio_out |= val;
if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) {
ret = gpio_ad559x_port_set_bits_raw(
dev, (gpio_port_pins_t)BIT(pin));
if (ret < 0) {
return ret;
}
} else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0U) {
ret = gpio_ad559x_port_clear_bits_raw(
dev, (gpio_port_pins_t)BIT(pin));
if (ret < 0) {
return ret;
}
}
ret = mfd_ad559x_write_reg(config->mfd_dev,
AD559X_REG_GPIO_OUTPUT_EN, data->gpio_out);
if (ret < 0) {
return ret;
}
ret = mfd_ad559x_write_reg(config->mfd_dev,
AD559X_REG_GPIO_INPUT_EN, data->gpio_in);
} else if ((flags & GPIO_INPUT) != 0U) {
data->gpio_in |= val;
data->gpio_out &= ~val;
if ((flags & GPIO_PULL_DOWN) != 0U) {
data->gpio_pull_down |= val;
ret = mfd_ad559x_write_reg(config->mfd_dev,
AD559X_REG_GPIO_PULLDOWN,
data->gpio_pull_down);
if (ret < 0) {
return ret;
}
} else if ((flags & GPIO_PULL_UP) != 0U) {
return -ENOTSUP;
}
ret = mfd_ad559x_write_reg(config->mfd_dev,
AD559X_REG_GPIO_OUTPUT_EN, data->gpio_out);
if (ret < 0) {
return ret;
}
ret = mfd_ad559x_write_reg(config->mfd_dev,
AD559X_REG_GPIO_INPUT_EN, data->gpio_in);
} else {
return -ENOTSUP;
}
return ret;
}
static int gpio_ad559x_port_set_masked_raw(const struct device *dev,
gpio_port_pins_t mask,
gpio_port_value_t value)
{
ARG_UNUSED(dev);
ARG_UNUSED(mask);
ARG_UNUSED(value);
return -ENOTSUP;
}
static int gpio_ad559x_port_toggle_bits(const struct device *dev,
gpio_port_pins_t pins)
{
ARG_UNUSED(dev);
ARG_UNUSED(pins);
return -ENOTSUP;
}
static int gpio_ad559x_pin_interrupt_configure(const struct device *dev,
gpio_pin_t pin,
enum gpio_int_mode mode,
enum gpio_int_trig trig)
{
ARG_UNUSED(dev);
ARG_UNUSED(pin);
ARG_UNUSED(mode);
ARG_UNUSED(trig);
return -ENOTSUP;
}
static const struct gpio_driver_api gpio_ad559x_api = {
.pin_configure = gpio_ad559x_configure,
.port_get_raw = gpio_ad559x_port_get_raw,
.port_set_masked_raw = gpio_ad559x_port_set_masked_raw,
.port_set_bits_raw = gpio_ad559x_port_set_bits_raw,
.port_clear_bits_raw = gpio_ad559x_port_clear_bits_raw,
.port_toggle_bits = gpio_ad559x_port_toggle_bits,
.pin_interrupt_configure = gpio_ad559x_pin_interrupt_configure,
};
static int gpio_ad559x_init(const struct device *dev)
{
const struct gpio_ad559x_config *config = dev->config;
if (!device_is_ready(config->mfd_dev)) {
return -ENODEV;
}
return 0;
}
#define GPIO_AD559X_DEFINE(inst) \
static const struct gpio_ad559x_config gpio_ad559x_config##inst = { \
.common = { \
.port_pin_mask = \
GPIO_PORT_PIN_MASK_FROM_DT_INST(inst), \
}, \
.mfd_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
}; \
\
static struct gpio_ad559x_data gpio_ad559x_data##inst; \
\
DEVICE_DT_INST_DEFINE(inst, gpio_ad559x_init, NULL, \
&gpio_ad559x_data##inst, &gpio_ad559x_config##inst, \
POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, \
&gpio_ad559x_api);
DT_INST_FOREACH_STATUS_OKAY(GPIO_AD559X_DEFINE)

View file

@ -8,7 +8,9 @@ zephyr_library_sources_ifdef(CONFIG_MFD_NCT38XX mfd_nct38xx.c)
zephyr_library_sources_ifdef(CONFIG_MFD_NPM1300 mfd_npm1300.c)
zephyr_library_sources_ifdef(CONFIG_MFD_NPM6001 mfd_npm6001.c)
zephyr_library_sources_ifdef(CONFIG_MFD_AXP192 mfd_axp192.c)
zephyr_library_sources_ifdef(CONFIG_MFD_AD5592 mfd_ad5592.c)
zephyr_library_sources_ifdef(CONFIG_MFD_AD559X mfd_ad559x.c)
zephyr_library_sources_ifdef(CONFIG_MFD_AD559X_BUS_I2C mfd_ad559x_i2c.c)
zephyr_library_sources_ifdef(CONFIG_MFD_AD559X_BUS_SPI mfd_ad559x_spi.c)
zephyr_library_sources_ifdef(CONFIG_MFD_MAX31790 mfd_max31790.c)
zephyr_library_sources_ifdef(CONFIG_NXP_LP_FLEXCOMM mfd_nxp_lp_flexcomm.c)
zephyr_library_sources_ifdef(CONFIG_MFD_BD8LB600FS mfd_bd8lb600fs.c)

View file

@ -18,7 +18,7 @@ config MFD_INIT_PRIORITY
help
Multi-function devices initialization priority.
source "drivers/mfd/Kconfig.ad5592"
source "drivers/mfd/Kconfig.ad559x"
source "drivers/mfd/Kconfig.axp192"
source "drivers/mfd/Kconfig.bd8lb600fs"
source "drivers/mfd/Kconfig.max20335"

View file

@ -1,10 +0,0 @@
# Copyright (c) 2023 Grinn
# SPDX -License-Identifier: Apache-2.0
config MFD_AD5592
bool "Analog AD5592 SPI configurable ADC/DAC/GPIO chip"
default y
depends on DT_HAS_ADI_AD5592_ENABLED
depends on SPI
help
Enable driver for Analog AD5592.

View file

@ -0,0 +1,25 @@
# Copyright (c) 2023 Grinn
# SPDX -License-Identifier: Apache-2.0
menuconfig MFD_AD559X
bool "Analog AD559x I2C/SPI configurable ADC/DAC/GPIO chip"
default y
depends on DT_HAS_ADI_AD559X_ENABLED
help
Enable driver for Analog AD5592 or Analog AD5593.
if MFD_AD559X
config MFD_AD559X_BUS_I2C
bool "Analog AD559x I2C bus support"
default y
depends on $(dt_compat_on_bus,$(DT_COMPAT_ADI_AD559X),i2c)
depends on I2C
config MFD_AD559X_BUS_SPI
bool "Analog AD559x SPI bus support"
default y
depends on $(dt_compat_on_bus,$(DT_COMPAT_ADI_AD559X),spi)
depends on SPI
endif # MFD_AD559X

View file

@ -1,182 +0,0 @@
/*
* Copyright (c) 2023 Grinn
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT adi_ad5592
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/spi.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/drivers/mfd/ad5592.h>
#define AD5592_GPIO_READBACK_EN BIT(10)
#define AD5592_LDAC_READBACK_EN BIT(6)
#define AD5592_REG_SOFTWARE_RESET 0x0FU
#define AD5592_SOFTWARE_RESET_MAGIC_VAL 0x5AC
#define AD5592_REG_VAL_MASK 0x3FF
#define AD5592_REG_RESET_VAL_MASK 0x7FF
#define AD5592_REG_SHIFT_VAL 11
#define AD5592_REG_READBACK_SHIFT_VAL 2
#define AD5592_SPI_SPEC_CONF (SPI_WORD_SET(8) | SPI_TRANSFER_MSB | \
SPI_OP_MODE_MASTER | SPI_MODE_CPOL)
struct mfd_ad5592_config {
struct gpio_dt_spec reset_gpio;
struct spi_dt_spec bus;
};
int mfd_ad5592_read_raw(const struct device *dev, uint16_t *val)
{
const struct mfd_ad5592_config *config = dev->config;
uint16_t nop_msg = 0;
struct spi_buf tx_buf[] = {
{
.buf = &nop_msg,
.len = sizeof(nop_msg)
}
};
const struct spi_buf_set tx = {
.buffers = tx_buf,
.count = 1
};
struct spi_buf rx_buf[] = {
{
.buf = val,
.len = sizeof(uint16_t)
}
};
const struct spi_buf_set rx = {
.buffers = rx_buf,
.count = 1
};
return spi_transceive_dt(&config->bus, &tx, &rx);
}
int mfd_ad5592_write_raw(const struct device *dev, uint16_t val)
{
const struct mfd_ad5592_config *config = dev->config;
struct spi_buf tx_buf[] = {
{
.buf = &val,
.len = sizeof(val)
}
};
const struct spi_buf_set tx = {
.buffers = tx_buf,
.count = 1
};
return spi_write_dt(&config->bus, &tx);
}
int mfd_ad5592_read_reg(const struct device *dev, uint8_t reg, uint8_t reg_data, uint16_t *val)
{
uint16_t data;
uint16_t msg;
int ret;
switch (reg) {
case AD5592_REG_GPIO_INPUT_EN:
msg = sys_cpu_to_be16(AD5592_GPIO_READBACK_EN |
(AD5592_REG_GPIO_INPUT_EN << AD5592_REG_SHIFT_VAL) |
reg_data);
break;
default:
msg = sys_cpu_to_be16(AD5592_LDAC_READBACK_EN |
(AD5592_REG_READ_AND_LDAC << AD5592_REG_SHIFT_VAL) |
reg << AD5592_REG_READBACK_SHIFT_VAL);
break;
}
ret = mfd_ad5592_write_raw(dev, msg);
if (ret < 0) {
return ret;
}
ret = mfd_ad5592_read_raw(dev, &data);
if (ret < 0) {
return ret;
}
*val = sys_be16_to_cpu(data);
return 0;
}
int mfd_ad5592_write_reg(const struct device *dev, uint8_t reg, uint16_t val)
{
uint16_t write_mask;
uint16_t msg;
switch (reg) {
case AD5592_REG_SOFTWARE_RESET:
write_mask = AD5592_REG_RESET_VAL_MASK;
break;
default:
write_mask = AD5592_REG_VAL_MASK;
break;
}
msg = sys_cpu_to_be16((reg << AD5592_REG_SHIFT_VAL) | (val & write_mask));
return mfd_ad5592_write_raw(dev, msg);
}
static int mfd_add592_software_reset(const struct device *dev)
{
return mfd_ad5592_write_reg(dev,
AD5592_REG_SOFTWARE_RESET,
AD5592_SOFTWARE_RESET_MAGIC_VAL);
}
static int mfd_ad5592_init(const struct device *dev)
{
const struct mfd_ad5592_config *config = dev->config;
int ret;
if (!spi_is_ready_dt(&config->bus)) {
return -ENODEV;
}
if (!gpio_is_ready_dt(&config->reset_gpio)) {
return -ENODEV;
}
ret = gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_INACTIVE);
if (ret < 0) {
return ret;
}
ret = mfd_add592_software_reset(dev);
if (ret < 0) {
return ret;
}
return 0;
}
#define MFD_AD5592_DEFINE(inst) \
static const struct mfd_ad5592_config mfd_ad5592_config_##inst = { \
.reset_gpio = GPIO_DT_SPEC_INST_GET(inst, reset_gpios), \
.bus = SPI_DT_SPEC_INST_GET(inst, AD5592_SPI_SPEC_CONF, 0), \
}; \
\
DEVICE_DT_INST_DEFINE(inst, mfd_ad5592_init, NULL, \
NULL, \
&mfd_ad5592_config_##inst, \
POST_KERNEL, \
CONFIG_MFD_INIT_PRIORITY, \
NULL);
DT_INST_FOREACH_STATUS_OKAY(MFD_AD5592_DEFINE);

110
drivers/mfd/mfd_ad559x.c Normal file
View file

@ -0,0 +1,110 @@
/*
* Copyright (c) 2023 Grinn
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT adi_ad559x
#include <zephyr/drivers/gpio.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/drivers/mfd/ad559x.h>
#include "mfd_ad559x.h"
bool mfd_ad559x_has_pointer_byte_map(const struct device *dev)
{
const struct mfd_ad559x_config *config = dev->config;
return config->has_pointer_byte_map;
}
int mfd_ad559x_read_raw(const struct device *dev, uint8_t *val, size_t len)
{
struct mfd_ad559x_data *data = dev->data;
return data->transfer_function->read_raw(dev, val, len);
}
int mfd_ad559x_write_raw(const struct device *dev, uint8_t *val, size_t len)
{
struct mfd_ad559x_data *data = dev->data;
return data->transfer_function->write_raw(dev, val, len);
}
int mfd_ad559x_read_reg(const struct device *dev, uint8_t reg, uint8_t reg_data, uint16_t *val)
{
struct mfd_ad559x_data *data = dev->data;
return data->transfer_function->read_reg(dev, reg, reg_data, val);
}
int mfd_ad559x_write_reg(const struct device *dev, uint8_t reg, uint16_t val)
{
struct mfd_ad559x_data *data = dev->data;
return data->transfer_function->write_reg(dev, reg, val);
}
static int mfd_add559x_software_reset(const struct device *dev)
{
return mfd_ad559x_write_reg(dev, AD559X_REG_SOFTWARE_RESET,
AD559X_SOFTWARE_RESET_MAGIC_VAL);
}
static int mfd_ad559x_init(const struct device *dev)
{
const struct mfd_ad559x_config *config = dev->config;
int ret;
ret = config->bus_init(dev);
if (ret < 0) {
return ret;
}
if (!gpio_is_ready_dt(&config->reset_gpio)) {
return -ENODEV;
}
ret = gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_INACTIVE);
if (ret < 0) {
return ret;
}
ret = mfd_add559x_software_reset(dev);
if (ret < 0) {
return ret;
}
return 0;
}
#define MDF_AD559X_DEFINE_I2C_BUS(inst) \
.i2c = I2C_DT_SPEC_INST_GET(inst), .bus_init = mfd_ad559x_i2c_init, \
.has_pointer_byte_map = true
#define MDF_AD559X_DEFINE_SPI_BUS_FLAGS \
(SPI_WORD_SET(8) | SPI_TRANSFER_MSB | SPI_OP_MODE_MASTER | SPI_MODE_CPOL)
#define MDF_AD559X_DEFINE_SPI_BUS(inst) \
.spi = SPI_DT_SPEC_INST_GET(inst, MDF_AD559X_DEFINE_SPI_BUS_FLAGS, 0), \
.bus_init = mfd_ad559x_spi_init, .has_pointer_byte_map = false
#define MFD_AD559X_DEFINE_BUS(inst) \
COND_CODE_1(DT_INST_ON_BUS(inst, i2c), (MDF_AD559X_DEFINE_I2C_BUS(inst)), \
(MDF_AD559X_DEFINE_SPI_BUS(inst)))
#define MFD_AD559X_DEFINE(inst) \
static struct mfd_ad559x_data mfd_ad559x_data_##inst; \
static const struct mfd_ad559x_config mfd_ad559x_config_##inst = { \
.reset_gpio = GPIO_DT_SPEC_INST_GET(inst, reset_gpios), \
MFD_AD559X_DEFINE_BUS(inst), \
}; \
\
DEVICE_DT_INST_DEFINE(inst, mfd_ad559x_init, NULL, &mfd_ad559x_data_##inst, \
&mfd_ad559x_config_##inst, POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, \
NULL);
DT_INST_FOREACH_STATUS_OKAY(MFD_AD559X_DEFINE);

65
drivers/mfd/mfd_ad559x.h Normal file
View file

@ -0,0 +1,65 @@
/*
* Copyright (c) 2024 Vitrolife A/S
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_DRIVERS_MFD_AD559X_H_
#define ZEPHYR_DRIVERS_MFD_AD559X_H_
#ifdef __cplusplus
extern "C" {
#endif
#define DT_DRV_COMPAT adi_ad559x
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
#include <zephyr/drivers/i2c.h>
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
#include <zephyr/drivers/spi.h>
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) */
#define AD559X_GPIO_READBACK_EN BIT(10)
#define AD559X_LDAC_READBACK_EN BIT(6)
#define AD559X_REG_SOFTWARE_RESET 0x0FU
#define AD559X_SOFTWARE_RESET_MAGIC_VAL 0x5AC
#define AD559X_REG_VAL_MASK 0x3FF
#define AD559X_REG_RESET_VAL_MASK 0x7FF
#define AD559X_REG_SHIFT_VAL 11
#define AD559X_REG_READBACK_SHIFT_VAL 2
struct mfd_ad559x_transfer_function {
int (*read_raw)(const struct device *dev, uint8_t *val, size_t len);
int (*write_raw)(const struct device *dev, uint8_t *val, size_t len);
int (*read_reg)(const struct device *dev, uint8_t reg, uint8_t reg_data, uint16_t *val);
int (*write_reg)(const struct device *dev, uint8_t reg, uint16_t val);
};
struct mfd_ad559x_config {
struct gpio_dt_spec reset_gpio;
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
struct i2c_dt_spec i2c;
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
struct spi_dt_spec spi;
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) */
int (*bus_init)(const struct device *dev);
bool has_pointer_byte_map;
};
struct mfd_ad559x_data {
const struct mfd_ad559x_transfer_function *transfer_function;
};
int mfd_ad559x_i2c_init(const struct device *dev);
int mfd_ad559x_spi_init(const struct device *dev);
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_DRIVERS_MFD_AD559X_H_*/

View file

@ -0,0 +1,79 @@
/*
* Copyright (c) 2024, Vitrolife A/S
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/device.h>
#include <zephyr/drivers/mfd/ad559x.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/util_macro.h>
#include "mfd_ad559x.h"
static int mfd_ad559x_i2c_read_raw(const struct device *dev, uint8_t *val, size_t len)
{
const struct mfd_ad559x_config *config = dev->config;
return i2c_read_dt(&config->i2c, val, len);
}
static int mfd_ad559x_i2c_write_raw(const struct device *dev, uint8_t *val, size_t len)
{
const struct mfd_ad559x_config *config = dev->config;
return i2c_write_dt(&config->i2c, val, len);
}
static int mfd_ad559x_i2c_read_reg(const struct device *dev, uint8_t reg, uint8_t reg_data,
uint16_t *val)
{
const struct mfd_ad559x_config *config = dev->config;
uint8_t buf[sizeof(*val)];
int ret;
ARG_UNUSED(reg_data);
__ASSERT((reg & 0xf0) == 0, "reg bits [7:4] should be 0: 0x%x", reg);
ret = i2c_write_read_dt(&config->i2c, &reg, sizeof(reg), buf, sizeof(buf));
if (ret < 0) {
return ret;
}
*val = sys_get_be16(buf);
return 0;
}
static int mfd_ad559x_i2c_write_reg(const struct device *dev, uint8_t reg, uint16_t val)
{
uint8_t buf[sizeof(reg) + sizeof(val)];
buf[0] = reg;
sys_put_be16(val, &buf[1]);
return mfd_ad559x_i2c_write_raw(dev, buf, sizeof(buf));
}
static const struct mfd_ad559x_transfer_function mfd_ad559x_i2c_transfer_function = {
.read_raw = mfd_ad559x_i2c_read_raw,
.write_raw = mfd_ad559x_i2c_write_raw,
.read_reg = mfd_ad559x_i2c_read_reg,
.write_reg = mfd_ad559x_i2c_write_reg,
};
int mfd_ad559x_i2c_init(const struct device *dev)
{
const struct mfd_ad559x_config *config = dev->config;
struct mfd_ad559x_data *data = dev->data;
data->transfer_function = &mfd_ad559x_i2c_transfer_function;
if (!i2c_is_ready_dt(&config->i2c)) {
return -ENODEV;
}
return 0;
}

View file

@ -0,0 +1,114 @@
/*
* Copyright (c) 2023 Grinn
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/device.h>
#include <zephyr/drivers/mfd/ad559x.h>
#include <zephyr/drivers/spi.h>
#include <zephyr/sys/byteorder.h>
#include "mfd_ad559x.h"
static int mfd_ad559x_spi_read_raw(const struct device *dev, uint8_t *val, size_t len)
{
const struct mfd_ad559x_config *config = dev->config;
uint16_t nop_msg = 0;
struct spi_buf tx_buf[] = {{.buf = &nop_msg, .len = sizeof(nop_msg)}};
const struct spi_buf_set tx = {.buffers = tx_buf, .count = 1};
struct spi_buf rx_buf[] = {{.buf = val, .len = len}};
const struct spi_buf_set rx = {.buffers = rx_buf, .count = 1};
return spi_transceive_dt(&config->spi, &tx, &rx);
}
static int mfd_ad559x_spi_write_raw(const struct device *dev, uint8_t *val, size_t len)
{
const struct mfd_ad559x_config *config = dev->config;
struct spi_buf tx_buf[] = {{.buf = val, .len = len}};
const struct spi_buf_set tx = {.buffers = tx_buf, .count = 1};
return spi_write_dt(&config->spi, &tx);
}
static int mfd_ad559x_spi_read_reg(const struct device *dev, uint8_t reg, uint8_t reg_data,
uint16_t *val)
{
uint16_t data;
uint16_t msg;
int ret;
switch (reg) {
case AD559X_REG_GPIO_INPUT_EN:
msg = sys_cpu_to_be16(AD559X_GPIO_READBACK_EN |
(AD559X_REG_GPIO_INPUT_EN << AD559X_REG_SHIFT_VAL) |
reg_data);
break;
default:
msg = sys_cpu_to_be16(AD559X_LDAC_READBACK_EN |
(AD559X_REG_READ_AND_LDAC << AD559X_REG_SHIFT_VAL) |
reg << AD559X_REG_READBACK_SHIFT_VAL);
break;
}
ret = mfd_ad559x_spi_write_raw(dev, (uint8_t *)&msg, sizeof(msg));
if (ret < 0) {
return ret;
}
ret = mfd_ad559x_spi_read_raw(dev, (uint8_t *)&data, sizeof(data));
if (ret < 0) {
return ret;
}
*val = sys_be16_to_cpu(data);
return 0;
}
static int mfd_ad559x_spi_write_reg(const struct device *dev, uint8_t reg, uint16_t val)
{
uint16_t write_mask;
uint16_t msg;
switch (reg) {
case AD559X_REG_SOFTWARE_RESET:
write_mask = AD559X_REG_RESET_VAL_MASK;
break;
default:
write_mask = AD559X_REG_VAL_MASK;
break;
}
msg = sys_cpu_to_be16((reg << AD559X_REG_SHIFT_VAL) | (val & write_mask));
return mfd_ad559x_spi_write_raw(dev, (uint8_t *)&msg, sizeof(msg));
}
static const struct mfd_ad559x_transfer_function mfd_ad559x_spi_transfer_function = {
.read_raw = mfd_ad559x_spi_read_raw,
.write_raw = mfd_ad559x_spi_write_raw,
.read_reg = mfd_ad559x_spi_read_reg,
.write_reg = mfd_ad559x_spi_write_reg,
};
int mfd_ad559x_spi_init(const struct device *dev)
{
const struct mfd_ad559x_config *config = dev->config;
struct mfd_ad559x_data *data = dev->data;
data->transfer_function = &mfd_ad559x_spi_transfer_function;
if (!spi_is_ready_dt(&config->spi)) {
return -ENODEV;
}
return 0;
}

View file

@ -1,9 +1,9 @@
# Copyright (c) 2023 Grinn
# SPDX-License-Identifier: Apache-2.0
description: AD5592 ADC Controller
description: AD559x ADC Controller
compatible: "adi,ad5592-adc"
compatible: "adi,ad559x-adc"
include: adc-controller.yaml

View file

@ -1,9 +1,9 @@
# Copyright (c) 2023 Grinn
# SPDX-License-Identifier: Apache-2.0
description: AD5592 DAC Controller
description: AD559x DAC Controller
compatible: "adi,ad5592-dac"
compatible: "adi,ad559x-dac"
include: dac-controller.yaml

View file

@ -1,9 +1,9 @@
# Copyright (c) 2023 Grinn
# SPDX-License-Identifier: Apache-2.0
description: AD5592 GPIO Controller
description: AD559x GPIO Controller
compatible: "adi,ad5592-gpio"
compatible: "adi,ad559x-gpio"
include: gpio-controller.yaml

View file

@ -1,11 +1,7 @@
# Copyright (C) 2023 Grinn
# SPDX-License-Identifier: Apache-2.0
description: Analog AD5592 ADC/DAC/GPIO chip
compatible: "adi,ad5592"
include: spi-device.yaml
description: Analog AD559x ADC/DAC/GPIO chip common properties
properties:
reset-gpios:

View file

@ -0,0 +1,8 @@
# Copyright (C) 2024, Vitrolife A/S
# SPDX-License-Identifier: Apache-2.0
description: Analog AD559X ADC/DAC/GPIO chip via I2C bus
compatible: "adi,ad559x"
include: [i2c-device.yaml, "adi,ad559x-common.yaml"]

View file

@ -0,0 +1,8 @@
# Copyright (c) 2024, Vitrolife A/S
# SPDX-License-Identifier: Apache-2.0
description: Analog AD559X ADC/DAC/GPIO chip via SPI bus
compatible: "adi,ad559x"
include: [spi-device.yaml, "adi,ad559x-common.yaml"]

View file

@ -1,91 +0,0 @@
/*
* Copyright (c) 2023 Grinn
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_MFD_AD5592_H_
#define ZEPHYR_INCLUDE_DRIVERS_MFD_AD5592_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <zephyr/device.h>
#define AD5592_REG_SEQ_ADC 0x02U
#define AD5592_REG_ADC_CONFIG 0x04U
#define AD5592_REG_LDAC_EN 0x05U
#define AD5592_REG_GPIO_PULLDOWN 0x06U
#define AD5592_REG_READ_AND_LDAC 0x07U
#define AD5592_REG_GPIO_OUTPUT_EN 0x08U
#define AD5592_REG_GPIO_SET 0x09U
#define AD5592_REG_GPIO_INPUT_EN 0x0AU
#define AD5592_REG_PD_REF_CTRL 0x0BU
#define AD5592_EN_REF BIT(9)
#define AD5592_PIN_MAX 8U
/**
* @defgroup mdf_interface_ad5592 MFD AD5592 interface
* @ingroup mfd_interfaces
* @{
*/
/**
* @brief Read raw data from the chip
*
* @param[in] dev Pointer to MFD device
* @param[in] val Pointer to data buffer
*
* @retval 0 if success
* @retval negative errno if failure
*/
int mfd_ad5592_read_raw(const struct device *dev, uint16_t *val);
/**
* @brief Write raw data to chip
*
* @param[in] dev Pointer to MFD device
* @param[in] val Data to be written
*
*
* @retval 0 if success
* @retval negative errno if failure
*/
int mfd_ad5592_write_raw(const struct device *dev, uint16_t val);
/**
* @brief Read data from provided register
*
* @param[in] dev Pointer to MFD device
* @param[in] reg Register to be read
* @param[in] reg_data Additional data passed to selected register
* @param[in] val Pointer to data buffer
*
* @retval 0 if success
* @retval negative errno if failure
*/
int mfd_ad5592_read_reg(const struct device *dev, uint8_t reg, uint8_t reg_data, uint16_t *val);
/**
* @brief Write data to provided register
*
* @param[in] dev Pointer to MFD device
* @param[in] reg Register to be written
* @param[in] val Data to be written
*
* @retval 0 if success
* @retval negative errno if failure
*/
int mfd_ad5592_write_reg(const struct device *dev, uint8_t reg, uint16_t val);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_INCLUDE_DRIVERS_MFD_AD5952_H_ */

View file

@ -0,0 +1,136 @@
/*
* Copyright (c) 2023 Grinn
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_DRIVERS_MFD_AD559X_H_
#define ZEPHYR_INCLUDE_DRIVERS_MFD_AD559X_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <zephyr/device.h>
#define AD559X_REG_SEQ_ADC 0x02U
#define AD559X_REG_ADC_CONFIG 0x04U
#define AD559X_REG_LDAC_EN 0x05U
#define AD559X_REG_GPIO_PULLDOWN 0x06U
#define AD559X_REG_READ_AND_LDAC 0x07U
#define AD559X_REG_GPIO_OUTPUT_EN 0x08U
#define AD559X_REG_GPIO_SET 0x09U
#define AD559X_REG_GPIO_INPUT_EN 0x0AU
#define AD559X_REG_PD_REF_CTRL 0x0BU
#define AD559X_EN_REF BIT(9)
#define AD559X_PIN_MAX 8U
/**
* @defgroup mdf_interface_ad559x MFD AD559X interface
* @ingroup mfd_interfaces
* @{
*/
/**
* @brief Check if the chip has a pointer byte map
*
* @param[in] dev Pointer to MFD device
*
* @retval true if chip has a pointer byte map, false if it has normal register map
*/
bool mfd_ad559x_has_pointer_byte_map(const struct device *dev);
/**
* @brief Read raw data from the chip
*
* @param[in] dev Pointer to MFD device
* @param[in] val Pointer to data buffer
* @param[in] len Number of bytes to be read
*
* @retval 0 if success
* @retval negative errno if failure
*/
int mfd_ad559x_read_raw(const struct device *dev, uint8_t *val, size_t len);
/**
* @brief Write raw data to chip
*
* @param[in] dev Pointer to MFD device
* @param[in] val Data to be written
* @param[in] len Number of bytes to be written
*
* @retval 0 if success
* @retval negative errno if failure
*/
int mfd_ad559x_write_raw(const struct device *dev, uint8_t *val, size_t len);
/**
* @brief Read data from provided register
*
* @param[in] dev Pointer to MFD device
* @param[in] reg Register to be read
* @param[in] reg_data Additional data passed to selected register
* @param[in] val Pointer to data buffer
*
* @retval 0 if success
* @retval negative errno if failure
*/
int mfd_ad559x_read_reg(const struct device *dev, uint8_t reg, uint8_t reg_data, uint16_t *val);
/**
* @brief Write data to provided register
*
* @param[in] dev Pointer to MFD device
* @param[in] reg Register to be written
* @param[in] val Data to be written
*
* @retval 0 if success
* @retval negative errno if failure
*/
int mfd_ad559x_write_reg(const struct device *dev, uint8_t reg, uint16_t val);
/**
* @brief Read ADC channel data from the chip
*
* @param[in] dev Pointer to MFD device
* @param[in] channel Channel to read
* @param[out] result ADC channel value read
*
* @retval 0 if success
* @retval negative errno if failure
*/
int mfd_ad559x_read_adc_chan(const struct device *dev, uint8_t channel, uint16_t *result);
/**
* @brief Write ADC channel data to the chip
*
* @param[in] dev Pointer to MFD device
* @param[in] channel Channel to write to
* @param[in] value DAC channel value
*
* @retval 0 if success
* @retval negative errno if failure
*/
int mfd_ad559x_write_dac_chan(const struct device *dev, uint8_t channel, uint16_t value);
/**
* @brief Read GPIO port from the chip
*
* @param[in] dev Pointer to MFD device
* @param[in] gpio GPIO to read
* @param[in] value DAC channel value
*
* @retval 0 if success
* @retval negative errno if failure
*/
int mfd_ad559x_gpio_port_get_raw(const struct device *dev, uint8_t gpio, uint16_t *value);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_INCLUDE_DRIVERS_MFD_AD559X_H_ */

View file

@ -315,15 +315,15 @@
#io-channel-cells = <1>;
};
test_spi_ad5592: ad5592@16 {
compatible = "adi,ad5592";
test_spi_ad559x: ad559x@16 {
compatible = "adi,ad559x";
status = "okay";
reg = <0x16>;
spi-max-frequency = <0>;
reset-gpios = <&test_gpio 0 0>;
ad5592_adc: adc-controller {
compatible = "adi,ad5592-adc";
ad559x_adc: adc-controller {
compatible = "adi,ad559x-adc";
#io-channel-cells = <1>;
};
};

View file

@ -235,15 +235,15 @@
reset-gpios = <&test_gpio 0 0>;
};
test_spi_ad5592: ad5592@10 {
compatible = "adi,ad5592";
test_spi_ad559x: ad559x@10 {
compatible = "adi,ad559x";
status = "okay";
reg = <0x10>;
spi-max-frequency = <0>;
reset-gpios = <&test_gpio 0 0>;
ad5592_dac: dac-controller {
compatible = "adi,ad5592-dac";
ad559x_dac: dac-controller {
compatible = "adi,ad559x-dac";
#io-channel-cells = <1>;
};
};

View file

@ -268,15 +268,15 @@
};
};
test_spi_ad5592: ad5592@3 {
compatible = "adi,ad5592";
test_spi_ad559x: ad559x@3 {
compatible = "adi,ad559x";
status = "okay";
reg = <0x03>;
spi-max-frequency = <0>;
reset-gpios = <&test_gpio 0 0>;
ad5592_gpio: gpio-controller {
compatible = "adi,ad5592-gpio";
ad559x_gpio: gpio-controller {
compatible = "adi,ad559x-gpio";
gpio-controller;
#gpio-cells = <2>;
ngpios = <8>;