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:
parent
2a5dc2a0df
commit
17b1912bc3
|
@ -167,7 +167,7 @@
|
||||||
/drivers/adc/*ads114s0x* @benediktibk
|
/drivers/adc/*ads114s0x* @benediktibk
|
||||||
/drivers/adc/*max11102_17* @benediktibk
|
/drivers/adc/*max11102_17* @benediktibk
|
||||||
/drivers/adc/*kb1200* @ene-steven
|
/drivers/adc/*kb1200* @ene-steven
|
||||||
/drivers/adc/adc_ad5592.c @bbilas
|
/drivers/adc/adc_ad559x.c @bbilas
|
||||||
/drivers/audio/*nrfx* @anangl
|
/drivers/audio/*nrfx* @anangl
|
||||||
/drivers/auxdisplay/*pt6314* @xingrz
|
/drivers/auxdisplay/*pt6314* @xingrz
|
||||||
/drivers/auxdisplay/* @thedjnK
|
/drivers/auxdisplay/* @thedjnK
|
||||||
|
@ -192,7 +192,7 @@
|
||||||
/drivers/display/*rm68200* @mmahadevan108
|
/drivers/display/*rm68200* @mmahadevan108
|
||||||
/drivers/display/display_ili9342c.* @extremegtx
|
/drivers/display/display_ili9342c.* @extremegtx
|
||||||
/drivers/dac/*ad56xx* @benediktibk
|
/drivers/dac/*ad56xx* @benediktibk
|
||||||
/drivers/dac/dac_ad5592.c @bbilas
|
/drivers/dac/dac_ad559x.c @bbilas
|
||||||
/drivers/dai/ @kv2019i @marcinszkudlinski @abonislawski
|
/drivers/dai/ @kv2019i @marcinszkudlinski @abonislawski
|
||||||
/drivers/dai/intel/ @kv2019i @marcinszkudlinski @abonislawski
|
/drivers/dai/intel/ @kv2019i @marcinszkudlinski @abonislawski
|
||||||
/drivers/dai/intel/ssp/ @kv2019i @marcinszkudlinski @abonislawski
|
/drivers/dai/intel/ssp/ @kv2019i @marcinszkudlinski @abonislawski
|
||||||
|
@ -244,7 +244,7 @@
|
||||||
/drivers/gpio/*pcal64xxa* @benediktibk
|
/drivers/gpio/*pcal64xxa* @benediktibk
|
||||||
/drivers/gpio/*kb1200* @ene-steven
|
/drivers/gpio/*kb1200* @ene-steven
|
||||||
/drivers/gpio/gpio_altera_pio.c @shilinte
|
/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_common.c @sjg20
|
||||||
/drivers/i2c/i2c_emul.c @sjg20
|
/drivers/i2c/i2c_emul.c @sjg20
|
||||||
/drivers/i2c/i2c_ite_enhance.c @GTLin08
|
/drivers/i2c/i2c_ite_enhance.c @GTLin08
|
||||||
|
@ -284,7 +284,7 @@
|
||||||
/drivers/kscan/*ft5336* @MaureenHelm
|
/drivers/kscan/*ft5336* @MaureenHelm
|
||||||
/drivers/kscan/*ht16k33* @henrikbrixandersen
|
/drivers/kscan/*ht16k33* @henrikbrixandersen
|
||||||
/drivers/led_strip/ @mbolivar-ampere
|
/drivers/led_strip/ @mbolivar-ampere
|
||||||
/drivers/mfd/mfd_ad5592.c @bbilas
|
/drivers/mfd/mfd_ad559x.c @bbilas
|
||||||
/drivers/mfd/mfd_max20335.c @bbilas
|
/drivers/mfd/mfd_max20335.c @bbilas
|
||||||
/drivers/misc/ft8xx/ @hubertmis
|
/drivers/misc/ft8xx/ @hubertmis
|
||||||
/drivers/modem/hl7800.c @rerickson1
|
/drivers/modem/hl7800.c @rerickson1
|
||||||
|
|
|
@ -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_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_MAX1125X adc_max1125x.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_ADC_MAX11102_17 adc_max11102_17.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_LTC2451 adc_ltc2451.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_ADC_NUMAKER adc_numaker.c)
|
zephyr_library_sources_ifdef(CONFIG_ADC_NUMAKER adc_numaker.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_ADC_ENE_KB1200 adc_ene_kb1200.c)
|
zephyr_library_sources_ifdef(CONFIG_ADC_ENE_KB1200 adc_ene_kb1200.c)
|
||||||
|
|
|
@ -120,7 +120,7 @@ source "drivers/adc/Kconfig.max1125x"
|
||||||
|
|
||||||
source "drivers/adc/Kconfig.max11102_17"
|
source "drivers/adc/Kconfig.max11102_17"
|
||||||
|
|
||||||
source "drivers/adc/Kconfig.ad5592"
|
source "drivers/adc/Kconfig.ad559x"
|
||||||
|
|
||||||
source "drivers/adc/Kconfig.ltc2451"
|
source "drivers/adc/Kconfig.ltc2451"
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
# Copyright (c) 2023 Grinn
|
# Copyright (c) 2023 Grinn
|
||||||
# SPDX -License-Identifier: Apache-2.0
|
# SPDX -License-Identifier: Apache-2.0
|
||||||
|
|
||||||
config ADC_AD5592
|
config ADC_AD559X
|
||||||
bool "AD5592 ADC driver"
|
bool "AD559x ADC driver"
|
||||||
default y
|
default y
|
||||||
depends on DT_HAS_ADI_AD5592_ADC_ENABLED
|
depends on DT_HAS_ADI_AD559X_ADC_ENABLED
|
||||||
select MFD
|
select MFD
|
||||||
help
|
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"
|
int "Stack size for the ADC data acquisition thread"
|
||||||
depends on ADC_AD5592
|
depends on ADC_AD559X
|
||||||
default 384
|
default 384
|
||||||
help
|
help
|
||||||
Size of the stack used for the internal data acquisition
|
Size of the stack used for the internal data acquisition
|
||||||
thread.
|
thread.
|
||||||
|
|
||||||
config ADC_AD5592_ACQUISITION_THREAD_PRIO
|
config ADC_AD559X_ACQUISITION_THREAD_PRIO
|
||||||
int "Priority for the ADC data acquisition thread"
|
int "Priority for the ADC data acquisition thread"
|
||||||
depends on ADC_AD5592
|
depends on ADC_AD559X
|
||||||
default 0
|
default 0
|
||||||
help
|
help
|
||||||
Priority level for the internal ADC data acquisition thread.
|
Priority level for the internal ADC data acquisition thread.
|
|
@ -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
273
drivers/adc/adc_ad559x.c
Normal 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)
|
|
@ -75,7 +75,7 @@ static struct adc_hdl {
|
||||||
uint8_t resolution;
|
uint8_t resolution;
|
||||||
} adc_list[] = {
|
} adc_list[] = {
|
||||||
/* zephyr-keep-sorted-start */
|
/* 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_sam0_adc, ADC_HDL_LIST_ENTRY)
|
||||||
DT_FOREACH_STATUS_OKAY(atmel_sam_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)
|
DT_FOREACH_STATUS_OKAY(atmel_sam_afec, ADC_HDL_LIST_ENTRY)
|
||||||
|
|
|
@ -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_MCP4728 dac_mcp4728.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_DAC_GD32 dac_gd32.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_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_DAC_AD56XX dac_ad56xx.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE dac_handlers.c)
|
zephyr_library_sources_ifdef(CONFIG_USERSPACE dac_handlers.c)
|
||||||
|
|
|
@ -53,6 +53,6 @@ source "drivers/dac/Kconfig.esp32"
|
||||||
|
|
||||||
source "drivers/dac/Kconfig.ad56xx"
|
source "drivers/dac/Kconfig.ad56xx"
|
||||||
|
|
||||||
source "drivers/dac/Kconfig.ad5592"
|
source "drivers/dac/Kconfig.ad559x"
|
||||||
|
|
||||||
endif # DAC
|
endif # DAC
|
||||||
|
|
|
@ -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.
|
|
10
drivers/dac/Kconfig.ad559x
Normal file
10
drivers/dac/Kconfig.ad559x
Normal 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.
|
|
@ -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
110
drivers/dac/dac_ad559x.c
Normal 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)
|
|
@ -4,7 +4,7 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/gpio.h)
|
||||||
|
|
||||||
zephyr_library()
|
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_AXP192 gpio_axp192.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_GPIO_TELINK_B91 gpio_b91.c)
|
zephyr_library_sources_ifdef(CONFIG_GPIO_TELINK_B91 gpio_b91.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_GPIO_INFINEON_CAT1 gpio_ifx_cat1.c)
|
zephyr_library_sources_ifdef(CONFIG_GPIO_INFINEON_CAT1 gpio_ifx_cat1.c)
|
||||||
|
|
|
@ -87,7 +87,7 @@ config GPIO_ENABLE_DISABLE_INTERRUPT
|
||||||
pending register, etc. The driver must implement it to work.
|
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"
|
source "drivers/gpio/Kconfig.axp192"
|
||||||
|
|
||||||
|
|
|
@ -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.
|
|
10
drivers/gpio/Kconfig.ad559x
Normal file
10
drivers/gpio/Kconfig.ad559x
Normal 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.
|
|
@ -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
236
drivers/gpio/gpio_ad559x.c
Normal 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)
|
|
@ -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_NPM1300 mfd_npm1300.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_MFD_NPM6001 mfd_npm6001.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_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_MFD_MAX31790 mfd_max31790.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_NXP_LP_FLEXCOMM mfd_nxp_lp_flexcomm.c)
|
zephyr_library_sources_ifdef(CONFIG_NXP_LP_FLEXCOMM mfd_nxp_lp_flexcomm.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_MFD_BD8LB600FS mfd_bd8lb600fs.c)
|
zephyr_library_sources_ifdef(CONFIG_MFD_BD8LB600FS mfd_bd8lb600fs.c)
|
||||||
|
|
|
@ -18,7 +18,7 @@ config MFD_INIT_PRIORITY
|
||||||
help
|
help
|
||||||
Multi-function devices initialization priority.
|
Multi-function devices initialization priority.
|
||||||
|
|
||||||
source "drivers/mfd/Kconfig.ad5592"
|
source "drivers/mfd/Kconfig.ad559x"
|
||||||
source "drivers/mfd/Kconfig.axp192"
|
source "drivers/mfd/Kconfig.axp192"
|
||||||
source "drivers/mfd/Kconfig.bd8lb600fs"
|
source "drivers/mfd/Kconfig.bd8lb600fs"
|
||||||
source "drivers/mfd/Kconfig.max20335"
|
source "drivers/mfd/Kconfig.max20335"
|
||||||
|
|
|
@ -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.
|
|
25
drivers/mfd/Kconfig.ad559x
Normal file
25
drivers/mfd/Kconfig.ad559x
Normal 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
|
|
@ -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
110
drivers/mfd/mfd_ad559x.c
Normal 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
65
drivers/mfd/mfd_ad559x.h
Normal 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_*/
|
79
drivers/mfd/mfd_ad559x_i2c.c
Normal file
79
drivers/mfd/mfd_ad559x_i2c.c
Normal 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, ®, 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;
|
||||||
|
}
|
114
drivers/mfd/mfd_ad559x_spi.c
Normal file
114
drivers/mfd/mfd_ad559x_spi.c
Normal 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;
|
||||||
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
# Copyright (c) 2023 Grinn
|
# Copyright (c) 2023 Grinn
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# 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
|
include: adc-controller.yaml
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
# Copyright (c) 2023 Grinn
|
# Copyright (c) 2023 Grinn
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# 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
|
include: dac-controller.yaml
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
# Copyright (c) 2023 Grinn
|
# Copyright (c) 2023 Grinn
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# 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
|
include: gpio-controller.yaml
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
# Copyright (C) 2023 Grinn
|
# Copyright (C) 2023 Grinn
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
description: Analog AD5592 ADC/DAC/GPIO chip
|
description: Analog AD559x ADC/DAC/GPIO chip common properties
|
||||||
|
|
||||||
compatible: "adi,ad5592"
|
|
||||||
|
|
||||||
include: spi-device.yaml
|
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
reset-gpios:
|
reset-gpios:
|
8
dts/bindings/mfd/adi,ad559x-i2c.yaml
Normal file
8
dts/bindings/mfd/adi,ad559x-i2c.yaml
Normal 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"]
|
8
dts/bindings/mfd/adi,ad559x-spi.yaml
Normal file
8
dts/bindings/mfd/adi,ad559x-spi.yaml
Normal 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"]
|
|
@ -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_ */
|
|
136
include/zephyr/drivers/mfd/ad559x.h
Normal file
136
include/zephyr/drivers/mfd/ad559x.h
Normal 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_ */
|
|
@ -315,15 +315,15 @@
|
||||||
#io-channel-cells = <1>;
|
#io-channel-cells = <1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
test_spi_ad5592: ad5592@16 {
|
test_spi_ad559x: ad559x@16 {
|
||||||
compatible = "adi,ad5592";
|
compatible = "adi,ad559x";
|
||||||
status = "okay";
|
status = "okay";
|
||||||
reg = <0x16>;
|
reg = <0x16>;
|
||||||
spi-max-frequency = <0>;
|
spi-max-frequency = <0>;
|
||||||
reset-gpios = <&test_gpio 0 0>;
|
reset-gpios = <&test_gpio 0 0>;
|
||||||
|
|
||||||
ad5592_adc: adc-controller {
|
ad559x_adc: adc-controller {
|
||||||
compatible = "adi,ad5592-adc";
|
compatible = "adi,ad559x-adc";
|
||||||
#io-channel-cells = <1>;
|
#io-channel-cells = <1>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -235,15 +235,15 @@
|
||||||
reset-gpios = <&test_gpio 0 0>;
|
reset-gpios = <&test_gpio 0 0>;
|
||||||
};
|
};
|
||||||
|
|
||||||
test_spi_ad5592: ad5592@10 {
|
test_spi_ad559x: ad559x@10 {
|
||||||
compatible = "adi,ad5592";
|
compatible = "adi,ad559x";
|
||||||
status = "okay";
|
status = "okay";
|
||||||
reg = <0x10>;
|
reg = <0x10>;
|
||||||
spi-max-frequency = <0>;
|
spi-max-frequency = <0>;
|
||||||
reset-gpios = <&test_gpio 0 0>;
|
reset-gpios = <&test_gpio 0 0>;
|
||||||
|
|
||||||
ad5592_dac: dac-controller {
|
ad559x_dac: dac-controller {
|
||||||
compatible = "adi,ad5592-dac";
|
compatible = "adi,ad559x-dac";
|
||||||
#io-channel-cells = <1>;
|
#io-channel-cells = <1>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -268,15 +268,15 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
test_spi_ad5592: ad5592@3 {
|
test_spi_ad559x: ad559x@3 {
|
||||||
compatible = "adi,ad5592";
|
compatible = "adi,ad559x";
|
||||||
status = "okay";
|
status = "okay";
|
||||||
reg = <0x03>;
|
reg = <0x03>;
|
||||||
spi-max-frequency = <0>;
|
spi-max-frequency = <0>;
|
||||||
reset-gpios = <&test_gpio 0 0>;
|
reset-gpios = <&test_gpio 0 0>;
|
||||||
|
|
||||||
ad5592_gpio: gpio-controller {
|
ad559x_gpio: gpio-controller {
|
||||||
compatible = "adi,ad5592-gpio";
|
compatible = "adi,ad559x-gpio";
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
#gpio-cells = <2>;
|
#gpio-cells = <2>;
|
||||||
ngpios = <8>;
|
ngpios = <8>;
|
||||||
|
|
Loading…
Reference in a new issue