blob: 32b6e05bb2713eb5484f380518e0841242b02878 [file] [edit]
/*
* Copyright (c) 2025 Analog Devices Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT adi_max2221x
#include <zephyr/drivers/mfd/max2221x.h>
#include <zephyr/device.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/spi.h>
#include <zephyr/sys/util.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/__assert.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(MFD_MAX2221X, CONFIG_MFD_LOG_LEVEL);
struct mfd_max2221x_config {
struct spi_dt_spec spi;
};
int max2221x_reg_read(const struct device *dev, uint8_t addr, uint16_t *value)
{
int ret;
const struct mfd_max2221x_config *config = dev->config;
uint8_t rxbuffer[3] = {0};
size_t rx_len = 3;
*value = 0;
addr = FIELD_PREP(MAX2221X_SPI_TRANS_ADDR, addr) | FIELD_PREP(MAX2221X_SPI_TRANS_DIR, 0);
const struct spi_buf txb[] = {
{
.buf = &addr,
.len = 1,
},
};
const struct spi_buf rxb[] = {
{
.buf = rxbuffer,
.len = rx_len,
},
};
struct spi_buf_set tx = {
.buffers = txb,
.count = ARRAY_SIZE(txb),
};
struct spi_buf_set rx = {
.buffers = rxb,
.count = ARRAY_SIZE(rxb),
};
ret = spi_transceive_dt(&config->spi, &tx, &rx);
if (ret) {
return ret;
}
memset(rxbuffer, 0, sizeof(rxbuffer));
ret = spi_transceive_dt(&config->spi, &tx, &rx);
if (ret) {
return ret;
}
*value = sys_be16_to_cpu(*(uint16_t *)&rxbuffer[1]);
return 0;
}
int max2221x_reg_write(const struct device *dev, uint8_t addr, uint16_t value)
{
const struct mfd_max2221x_config *config = dev->config;
addr = FIELD_PREP(MAX2221X_SPI_TRANS_ADDR, addr) | FIELD_PREP(MAX2221X_SPI_TRANS_DIR, 1);
value = sys_cpu_to_be16(value);
const struct spi_buf buf[] = {
{
.buf = &addr,
.len = 1,
},
{
.buf = &value,
.len = 2,
},
};
struct spi_buf_set tx = {
.buffers = buf,
.count = ARRAY_SIZE(buf),
};
return spi_write_dt(&config->spi, &tx);
}
int max2221x_reg_update(const struct device *dev, uint8_t addr, uint16_t mask, uint16_t val)
{
uint16_t tmp;
int ret;
ret = max2221x_reg_read(dev, addr, &tmp);
if (ret) {
return ret;
}
tmp = (tmp & ~mask) | FIELD_PREP(mask, val);
return max2221x_reg_write(dev, addr, tmp);
}
static int max2221x_init(const struct device *dev)
{
const struct mfd_max2221x_config *config = dev->config;
if (!spi_is_ready_dt(&config->spi)) {
LOG_ERR("SPI device %s not ready", config->spi.bus->name);
return -ENODEV;
}
return 0;
}
#define MAX2221X_DEFINE(inst) \
static const struct mfd_max2221x_config mfd_max2221x_config_##inst = { \
.spi = SPI_DT_SPEC_INST_GET(inst, SPI_WORD_SET(8) | SPI_TRANSFER_MSB, 0), \
}; \
\
DEVICE_DT_INST_DEFINE(inst, max2221x_init, NULL, NULL, &mfd_max2221x_config_##inst, \
POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, NULL);
DT_INST_FOREACH_STATUS_OKAY(MAX2221X_DEFINE)