diff --git a/CODEOWNERS b/CODEOWNERS index d7aadd6623a7a4e..ecc3fc4adf815d9 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -275,6 +275,7 @@ /drivers/display/display_ili9342c.* @extremegtx /drivers/dac/ @martinjaeger /drivers/dac/*ad56xx* @benediktibk +/drivers/dac/dac_ad5592.c @bbilas /drivers/dai/ @kv2019i @marcinszkudlinski @abonislawski /drivers/dai/intel/ @kv2019i @marcinszkudlinski @abonislawski /drivers/dai/intel/ssp/ @kv2019i @marcinszkudlinski @abonislawski diff --git a/drivers/dac/CMakeLists.txt b/drivers/dac/CMakeLists.txt index d2164f92d7ebda1..c84b0d9d78e5662 100644 --- a/drivers/dac/CMakeLists.txt +++ b/drivers/dac/CMakeLists.txt @@ -18,5 +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_AD56XX dac_ad56xx.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE dac_handlers.c) diff --git a/drivers/dac/Kconfig b/drivers/dac/Kconfig index 6449032fa4822e9..553d9f05355d9d9 100644 --- a/drivers/dac/Kconfig +++ b/drivers/dac/Kconfig @@ -54,4 +54,6 @@ source "drivers/dac/Kconfig.esp32" source "drivers/dac/Kconfig.ad56xx" +source "drivers/dac/Kconfig.ad5592" + endif # DAC diff --git a/drivers/dac/Kconfig.ad5592 b/drivers/dac/Kconfig.ad5592 new file mode 100644 index 000000000000000..3bb87df2a1eb606 --- /dev/null +++ b/drivers/dac/Kconfig.ad5592 @@ -0,0 +1,17 @@ +# 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. + +config DAC_AD5592_INIT_PRIORITY + int "AD5592 DAC driver initialization priority" + depends on DAC_AD5592 + default 85 + help + Initialization priority for the AD5592 DAC driver. diff --git a/drivers/dac/dac_ad5592.c b/drivers/dac/dac_ad5592.c new file mode 100644 index 000000000000000..12efcd54552c031 --- /dev/null +++ b/drivers/dac/dac_ad5592.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2023 Grinn + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT adi_ad5592_dac + +#include +#include +#include + +#include + +#include +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 (k_is_in_isr()) { + return -EWOULDBLOCK; + } + + 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) +{ + uint16_t msg; + + if (k_is_in_isr()) { + return -EWOULDBLOCK; + } + + 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(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_DAC_AD5592_INIT_PRIORITY, \ + &dac_ad5592_api); + +DT_INST_FOREACH_STATUS_OKAY(DAC_AD5592_DEFINE) diff --git a/dts/bindings/dac/adi,ad5592-dac.yaml b/dts/bindings/dac/adi,ad5592-dac.yaml new file mode 100644 index 000000000000000..3ac8087b91da562 --- /dev/null +++ b/dts/bindings/dac/adi,ad5592-dac.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2023 Grinn +# SPDX-License-Identifier: Apache-2.0 + +description: AD5592 DAC Controller + +compatible: "adi,ad5592-dac" + +include: dac-controller.yaml + +properties: + "#io-channel-cells": + const: 1 + +io-channel-cells: + - output diff --git a/tests/drivers/build_all/dac/app.overlay b/tests/drivers/build_all/dac/app.overlay index 40218f7949df03b..ee82a5e8b86bf07 100644 --- a/tests/drivers/build_all/dac/app.overlay +++ b/tests/drivers/build_all/dac/app.overlay @@ -82,6 +82,7 @@ <&test_gpio 0 0>, <&test_gpio 0 0>, <&test_gpio 0 0>, + <&test_gpio 0 0>, <&test_gpio 0 0>; test_spi_dac60508: dac60508@0 { @@ -233,6 +234,19 @@ #io-channel-cells = <1>; reset-gpios = <&test_gpio 0 0>; }; + + test_spi_ad5592: ad5592@10 { + compatible = "adi,ad5592"; + status = "okay"; + reg = <0x10>; + spi-max-frequency = <0>; + reset-gpios = <&test_gpio 0 0>; + + ad5592_dac: dac-controller { + compatible = "adi,ad5592-dac"; + #io-channel-cells = <1>; + }; + }; }; }; };