gpio: nct38xx: Remove reg access wrappers

Remove the register access wrappers used to read/write the NCT38xx
register space.

Signed-off-by: Keith Short <keithshort@google.com>
This commit is contained in:
Keith Short 2023-08-11 13:50:26 -06:00 committed by Fabio Baltieri
parent ea40f3af24
commit c9f822df27
5 changed files with 161 additions and 280 deletions

View file

@ -35,6 +35,8 @@ struct gpio_nct38xx_data {
const struct device *dev;
/* lock NCT38xx register access */
struct k_sem *lock;
/* I2C device for the MFD parent */
const struct i2c_dt_spec *i2c_dev;
};
void nct38xx_gpio_alert_handler(const struct device *dev)
@ -55,8 +57,8 @@ static int nct38xx_init_interrupt(const struct device *dev)
k_sem_take(data->lock, K_FOREVER);
/* Disable all interrupt */
if (nct38xx_reg_burst_write(dev, NCT38XX_REG_ALERT_MASK, (uint8_t *)&alert_mask,
sizeof(alert_mask))) {
if (i2c_burst_write_dt(data->i2c_dev, NCT38XX_REG_ALERT_MASK, (uint8_t *)&alert_mask,
sizeof(alert_mask))) {
ret = -EIO;
goto unlock;
}
@ -65,21 +67,21 @@ static int nct38xx_init_interrupt(const struct device *dev)
alert_mask |= BIT(NCT38XX_REG_ALERT_MASK_VENDOR_DEFINDED_ALERT);
/* Clear alert */
if (nct38xx_reg_burst_read(dev, NCT38XX_REG_ALERT, (uint8_t *)&alert, sizeof(alert))) {
if (i2c_burst_read_dt(data->i2c_dev, NCT38XX_REG_ALERT, (uint8_t *)&alert, sizeof(alert))) {
ret = -EIO;
goto unlock;
}
alert &= alert_mask;
if (alert) {
if (nct38xx_reg_burst_write(dev, NCT38XX_REG_ALERT, (uint8_t *)&alert,
sizeof(alert))) {
if (i2c_burst_write_dt(data->i2c_dev, NCT38XX_REG_ALERT, (uint8_t *)&alert,
sizeof(alert))) {
ret = -EIO;
goto unlock;
}
}
if (nct38xx_reg_burst_write(dev, NCT38XX_REG_ALERT_MASK, (uint8_t *)&alert_mask,
sizeof(alert_mask))) {
if (i2c_burst_write_dt(data->i2c_dev, NCT38XX_REG_ALERT_MASK, (uint8_t *)&alert_mask,
sizeof(alert_mask))) {
ret = -EIO;
goto unlock;
}
@ -101,6 +103,7 @@ static int nct38xx_gpio_init(const struct device *dev)
}
data->lock = mfd_nct38xx_get_lock_reference(config->mfd);
data->i2c_dev = mfd_nct38xx_get_i2c_dt_spec(config->mfd);
if (IS_ENABLED(CONFIG_GPIO_NCT38XX_ALERT)) {
nct38xx_init_interrupt(dev);

View file

@ -18,6 +18,13 @@
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(gpio_ntc38xx, CONFIG_GPIO_LOG_LEVEL);
struct nct38xx_mfd {
/* Lock for NCT38xx register access */
struct k_sem *lock;
/* I2C device used for register access */
const struct i2c_dt_spec *i2c_dev;
};
/* Driver config */
struct nct38xx_alert_config {
/* Alert GPIO pin */
@ -36,6 +43,8 @@ struct nct38xx_alert_data {
struct gpio_callback gpio_cb;
/* Alert worker */
struct k_work alert_worker;
/* Lock for NCT38xx register access */
struct nct38xx_mfd *mfd;
};
static void nct38xx_alert_callback(const struct device *dev, struct gpio_callback *cb,
@ -47,39 +56,58 @@ static void nct38xx_alert_callback(const struct device *dev, struct gpio_callbac
k_work_submit(&data->alert_worker);
}
static bool nct38xx_alert_is_active(struct nct38xx_mfd *mfd)
{
int ret;
uint16_t alert, mask;
k_sem_take(mfd->lock, K_FOREVER);
/* Clear alert */
ret = i2c_burst_read_dt(mfd->i2c_dev, NCT38XX_REG_ALERT, (uint8_t *)&alert,
sizeof(alert));
if (ret < 0) {
goto release_lock;
}
ret = i2c_burst_read_dt(mfd->i2c_dev, NCT38XX_REG_ALERT_MASK,
(uint8_t *)&mask, sizeof(mask));
if (ret < 0) {
goto release_lock;
}
alert &= mask;
if (alert) {
ret = i2c_burst_write_dt(mfd->i2c_dev, NCT38XX_REG_ALERT,
(uint8_t *)&alert, sizeof(alert));
}
release_lock:
k_sem_give(mfd->lock);
if (ret < 0) {
LOG_ERR("i2c access failed");
return false;
}
if (alert & BIT(NCT38XX_REG_ALERT_VENDOR_DEFINDED_ALERT)) {
return true;
}
return false;
}
static void nct38xx_alert_worker(struct k_work *work)
{
struct nct38xx_alert_data *const data =
CONTAINER_OF(work, struct nct38xx_alert_data, alert_worker);
const struct nct38xx_alert_config *const config = data->alert_dev->config;
uint16_t alert, mask;
do {
/* NCT38XX device handler */
for (int i = 0; i < config->nct38xx_num; i++) {
/* Clear alert */
if (nct38xx_reg_burst_read(config->nct38xx_dev[i], NCT38XX_REG_ALERT,
(uint8_t *)&alert, sizeof(alert))) {
LOG_ERR("i2c access failed");
return;
}
if (nct38xx_reg_burst_read(config->nct38xx_dev[i], NCT38XX_REG_ALERT_MASK,
(uint8_t *)&mask, sizeof(mask))) {
LOG_ERR("i2c access failed");
return;
}
struct nct38xx_mfd *mfd = &data->mfd[i];
alert &= mask;
if (alert) {
if (nct38xx_reg_burst_write(config->nct38xx_dev[i],
NCT38XX_REG_ALERT, (uint8_t *)&alert,
sizeof(alert))) {
LOG_ERR("i2c access failed");
return;
}
}
if (alert & BIT(NCT38XX_REG_ALERT_VENDOR_DEFINDED_ALERT)) {
if (nct38xx_alert_is_active(mfd)) {
nct38xx_gpio_alert_handler(config->nct38xx_dev[i]);
}
}
@ -99,6 +127,9 @@ static int nct38xx_alert_init(const struct device *dev)
LOG_ERR("%s device not ready", config->nct38xx_dev[i]->name);
return -ENODEV;
}
data->mfd[i].lock = mfd_nct38xx_get_lock_reference(config->nct38xx_dev[i]);
data->mfd[i].i2c_dev = mfd_nct38xx_get_i2c_dt_spec(config->nct38xx_dev[i]);
}
/* Set the alert pin for handling the interrupt */
@ -130,8 +161,9 @@ BUILD_ASSERT(CONFIG_GPIO_NCT38XX_ALERT_INIT_PRIORITY > CONFIG_GPIO_NCT38XX_INIT_
DEVICE_DT_GET(DT_PHANDLE_BY_IDX(node_id, prop, idx)),
#define NCT38XX_ALERT_DEVICE_INSTANCE(inst) \
const struct device *nct38xx_dev_##inst[] = { DT_INST_FOREACH_PROP_ELEM( \
inst, nct38xx_dev, NCT38XX_DEV_AND_COMMA) }; \
const struct device *nct38xx_dev_##inst[] = { \
DT_INST_FOREACH_PROP_ELEM(inst, nct38xx_dev, NCT38XX_DEV_AND_COMMA)}; \
static struct nct38xx_mfd nct38xx_mfd_##inst[DT_INST_PROP_LEN(inst, nct38xx_dev)]; \
static const struct nct38xx_alert_config nct38xx_alert_cfg_##inst = { \
.irq_gpio = GPIO_DT_SPEC_INST_GET(inst, irq_gpios), \
.nct38xx_dev = &nct38xx_dev_##inst[0], \
@ -139,6 +171,7 @@ BUILD_ASSERT(CONFIG_GPIO_NCT38XX_ALERT_INIT_PRIORITY > CONFIG_GPIO_NCT38XX_INIT_
}; \
static struct nct38xx_alert_data nct38xx_alert_data_##inst = { \
.alert_dev = DEVICE_DT_INST_GET(inst), \
.mfd = nct38xx_mfd_##inst, \
}; \
DEVICE_DT_INST_DEFINE(inst, nct38xx_alert_init, NULL, &nct38xx_alert_data_##inst, \
&nct38xx_alert_cfg_##inst, POST_KERNEL, \

View file

@ -33,6 +33,8 @@ struct gpio_nct38xx_port_data {
sys_slist_t cb_list_gpio;
/* lock NCT38xx register access */
struct k_sem *lock;
/* I2C device for the MFD parent */
const struct i2c_dt_spec *i2c_dev;
};
/* GPIO api functions */
@ -40,8 +42,8 @@ static int gpio_nct38xx_pin_config(const struct device *dev, gpio_pin_t pin, gpi
{
const struct gpio_nct38xx_port_config *const config = dev->config;
struct gpio_nct38xx_port_data *const data = dev->data;
uint32_t mask = BIT(pin);
uint8_t reg, new_reg;
uint32_t mask;
uint8_t new_reg;
int ret;
/* Don't support simultaneous in/out mode */
@ -63,16 +65,14 @@ static int gpio_nct38xx_pin_config(const struct device *dev, gpio_pin_t pin, gpi
/* Pin multiplexing */
if (config->gpio_port == 0) {
ret = nct38xx_reg_read_byte(config->mfd, NCT38XX_REG_MUX_CONTROL, &reg);
if (ret < 0) {
goto done;
}
/* Set the mux control bit, but ensure the reserved fields
* are cleared. Note that pinmux_mask contains the set
* of non-reserved bits.
*/
new_reg = BIT(pin) & config->pinmux_mask;
mask = BIT(pin) | ~config->pinmux_mask;
new_reg = reg | mask;
/* NCT3807 bit3 must be set to 0 */
new_reg &= config->pinmux_mask;
ret = nct38xx_reg_update(config->mfd, NCT38XX_REG_MUX_CONTROL, reg, new_reg);
ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_MUX_CONTROL, mask, new_reg);
if (ret < 0) {
goto done;
}
@ -80,63 +80,45 @@ static int gpio_nct38xx_pin_config(const struct device *dev, gpio_pin_t pin, gpi
/* Configure pin as input. */
if (flags & GPIO_INPUT) {
ret = nct38xx_reg_read_byte(config->mfd,
NCT38XX_REG_GPIO_DIR(config->gpio_port), &reg);
if (ret < 0) {
goto done;
}
new_reg = reg & ~mask;
ret = nct38xx_reg_update(config->mfd,
NCT38XX_REG_GPIO_DIR(config->gpio_port), reg, new_reg);
/* Clear the direction bit to set as an input */
new_reg = 0;
mask = BIT(pin);
ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DIR(config->gpio_port),
mask, new_reg);
goto done;
}
/* Select open drain 0:push-pull 1:open-drain */
ret = nct38xx_reg_read_byte(config->mfd, NCT38XX_REG_GPIO_OD_SEL(config->gpio_port),
&reg);
if (ret < 0) {
goto done;
}
mask = BIT(pin);
if (flags & GPIO_OPEN_DRAIN) {
new_reg = reg | mask;
new_reg = mask;
} else {
new_reg = reg & ~mask;
new_reg = 0;
}
ret = nct38xx_reg_update(config->mfd, NCT38XX_REG_GPIO_OD_SEL(config->gpio_port),
reg, new_reg);
ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_OD_SEL(config->gpio_port),
mask, new_reg);
if (ret < 0) {
goto done;
}
/* Set level 0:low 1:high */
ret = nct38xx_reg_read_byte(config->mfd,
NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
&reg);
if (ret < 0) {
goto done;
}
if (flags & GPIO_OUTPUT_INIT_HIGH) {
new_reg = reg | mask;
new_reg = mask;
} else if (flags & GPIO_OUTPUT_INIT_LOW) {
new_reg = reg & ~mask;
new_reg = 0;
}
ret = nct38xx_reg_update(config->mfd, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
reg, new_reg);
ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
mask, new_reg);
if (ret < 0) {
goto done;
}
/* Configure pin as output, if requested 0:input 1:output */
if (flags & GPIO_OUTPUT) {
ret = nct38xx_reg_read_byte(config->mfd,
NCT38XX_REG_GPIO_DIR(config->gpio_port), &reg);
if (ret < 0) {
goto done;
}
new_reg = reg | mask;
ret = nct38xx_reg_update(config->mfd,
NCT38XX_REG_GPIO_DIR(config->gpio_port), reg, new_reg);
new_reg = BIT(pin);
ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DIR(config->gpio_port),
mask, new_reg);
}
done:
@ -161,7 +143,7 @@ int gpio_nct38xx_pin_get_config(const struct device *dev, gpio_pin_t pin, gpio_f
goto done;
}
ret = nct38xx_reg_read_byte(config->mfd, NCT38XX_REG_MUX_CONTROL, &reg);
ret = i2c_reg_read_byte_dt(data->i2c_dev, NCT38XX_REG_MUX_CONTROL, &reg);
if (ret < 0) {
goto done;
}
@ -172,8 +154,7 @@ int gpio_nct38xx_pin_get_config(const struct device *dev, gpio_pin_t pin, gpio_f
}
}
ret = nct38xx_reg_read_byte(config->mfd, NCT38XX_REG_GPIO_DIR(config->gpio_port),
&reg);
ret = i2c_reg_read_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DIR(config->gpio_port), &reg);
if (ret < 0) {
goto done;
}
@ -183,8 +164,8 @@ int gpio_nct38xx_pin_get_config(const struct device *dev, gpio_pin_t pin, gpio_f
*flags = GPIO_OUTPUT;
/* 0 - push-pull, 1 - open-drain */
ret = nct38xx_reg_read_byte(config->mfd,
NCT38XX_REG_GPIO_OD_SEL(config->gpio_port), &reg);
ret = i2c_reg_read_byte_dt(data->i2c_dev,
NCT38XX_REG_GPIO_OD_SEL(config->gpio_port), &reg);
if (ret < 0) {
goto done;
}
@ -194,8 +175,8 @@ int gpio_nct38xx_pin_get_config(const struct device *dev, gpio_pin_t pin, gpio_f
}
/* Output value */
ret = nct38xx_reg_read_byte(config->mfd,
NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), &reg);
ret = i2c_reg_read_byte_dt(data->i2c_dev,
NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), &reg);
if (ret < 0) {
goto done;
}
@ -224,8 +205,8 @@ static int gpio_nct38xx_port_get_raw(const struct device *dev, gpio_port_value_t
k_sem_take(data->lock, K_FOREVER);
ret = nct38xx_reg_read_byte(config->mfd,
NCT38XX_REG_GPIO_DATA_IN(config->gpio_port), (uint8_t *)value);
ret = i2c_reg_read_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DATA_IN(config->gpio_port),
(uint8_t *)value);
k_sem_give(data->lock);
return ret;
@ -236,21 +217,13 @@ static int gpio_nct38xx_port_set_masked_raw(const struct device *dev, gpio_port_
{
const struct gpio_nct38xx_port_config *const config = dev->config;
struct gpio_nct38xx_port_data *const data = dev->data;
uint8_t reg, new_reg;
int ret;
k_sem_take(data->lock, K_FOREVER);
ret = nct38xx_reg_read_byte(config->mfd,
NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), &reg);
if (ret < 0) {
goto done;
}
new_reg = ((reg & ~mask) | (value & mask));
ret = nct38xx_reg_update(config->mfd, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
reg, new_reg);
ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
mask, value);
done:
k_sem_give(data->lock);
return ret;
@ -260,21 +233,13 @@ static int gpio_nct38xx_port_set_bits_raw(const struct device *dev, gpio_port_pi
{
const struct gpio_nct38xx_port_config *const config = dev->config;
struct gpio_nct38xx_port_data *const data = dev->data;
uint8_t reg, new_reg;
int ret;
k_sem_take(data->lock, K_FOREVER);
ret = nct38xx_reg_read_byte(config->mfd,
NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), &reg);
if (ret < 0) {
goto done;
}
new_reg = reg | mask;
ret = nct38xx_reg_update(config->mfd, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
reg, new_reg);
ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
mask, mask);
done:
k_sem_give(data->lock);
return ret;
@ -284,21 +249,13 @@ static int gpio_nct38xx_port_clear_bits_raw(const struct device *dev, gpio_port_
{
const struct gpio_nct38xx_port_config *const config = dev->config;
struct gpio_nct38xx_port_data *const data = dev->data;
uint8_t reg, new_reg;
int ret;
k_sem_take(data->lock, K_FOREVER);
ret = nct38xx_reg_read_byte(config->mfd,
NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), &reg);
if (ret < 0) {
goto done;
}
new_reg = reg & ~mask;
ret = nct38xx_reg_update(config->mfd, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
reg, new_reg);
ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
mask, 0);
done:
k_sem_give(data->lock);
return ret;
@ -313,14 +270,16 @@ static int gpio_nct38xx_port_toggle_bits(const struct device *dev, gpio_port_pin
k_sem_take(data->lock, K_FOREVER);
ret = nct38xx_reg_read_byte(config->mfd, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
&reg);
ret = i2c_reg_read_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
&reg);
if (ret < 0) {
goto done;
}
new_reg = reg ^ mask;
ret = nct38xx_reg_update(config->mfd, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
reg, new_reg);
if (new_reg != reg) {
ret = i2c_reg_write_byte_dt(data->i2c_dev,
NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), new_reg);
}
done:
k_sem_give(data->lock);
@ -333,24 +292,16 @@ static int gpio_nct38xx_pin_interrupt_configure(const struct device *dev, gpio_p
{
const struct gpio_nct38xx_port_config *const config = dev->config;
struct gpio_nct38xx_port_data *const data = dev->data;
uint8_t reg, new_reg, rise, new_rise, fall, new_fall;
uint8_t new_reg, new_rise, new_fall;
int ret;
uint32_t mask = BIT(pin);
k_sem_take(data->lock, K_FOREVER);
/* Disable irq before configuring them */
ret = nct38xx_reg_read_byte(config->mfd,
NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), &reg);
if (ret < 0) {
goto done;
}
new_reg = reg & ~mask;
ret = nct38xx_reg_update(config->mfd,
NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), reg, new_reg);
if (ret < 0) {
goto done;
}
new_reg = 0;
ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port),
mask, new_reg);
/* Configure and enable interrupt? */
if (mode == GPIO_INT_MODE_DISABLED) {
@ -358,69 +309,52 @@ static int gpio_nct38xx_pin_interrupt_configure(const struct device *dev, gpio_p
}
/* set edge register */
ret = nct38xx_reg_read_byte(config->mfd,
NCT38XX_REG_GPIO_ALERT_RISE(config->gpio_port), &rise);
if (ret < 0) {
goto done;
}
ret = nct38xx_reg_read_byte(config->mfd,
NCT38XX_REG_GPIO_ALERT_FALL(config->gpio_port), &fall);
if (ret < 0) {
goto done;
}
if (mode == GPIO_INT_MODE_EDGE) {
if (trig == GPIO_INT_TRIG_LOW) {
new_rise = rise & ~mask;
new_fall = fall | mask;
new_rise = 0;
new_fall = mask;
} else if (trig == GPIO_INT_TRIG_HIGH) {
new_rise = rise | mask;
new_fall = fall & ~mask;
new_rise = mask;
new_fall = 0;
} else if (trig == GPIO_INT_TRIG_BOTH) {
new_rise = rise | mask;
new_fall = fall | mask;
new_rise = mask;
new_fall = mask;
} else {
LOG_ERR("Invalid interrupt trigger type %d", trig);
return -EINVAL;
}
} else {
/* level mode */
new_rise = rise & ~mask;
new_fall = fall & ~mask;
new_rise = 0;
new_fall = 0;
}
ret = nct38xx_reg_update(config->mfd,
NCT38XX_REG_GPIO_ALERT_RISE(config->gpio_port), rise, new_rise);
ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_ALERT_RISE(config->gpio_port),
mask, new_rise);
if (ret < 0) {
goto done;
}
ret = nct38xx_reg_update(config->mfd,
NCT38XX_REG_GPIO_ALERT_FALL(config->gpio_port), fall, new_fall);
ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_ALERT_FALL(config->gpio_port),
mask, new_fall);
if (ret < 0) {
goto done;
}
if (mode == GPIO_INT_MODE_LEVEL) {
/* set active high/low */
ret = nct38xx_reg_read_byte(config->mfd,
NCT38XX_REG_GPIO_ALERT_LEVEL(config->gpio_port), &reg);
if (ret < 0) {
goto done;
}
if (trig == GPIO_INT_TRIG_LOW) {
new_reg = reg & ~mask;
new_reg = 0;
} else if (trig == GPIO_INT_TRIG_HIGH) {
new_reg = reg | mask;
new_reg = mask;
} else {
LOG_ERR("Invalid interrupt trigger type %d", trig);
ret = -EINVAL;
goto done;
}
ret = nct38xx_reg_update(config->mfd,
NCT38XX_REG_GPIO_ALERT_LEVEL(config->gpio_port), reg,
new_reg);
ret = i2c_reg_update_byte_dt(data->i2c_dev,
NCT38XX_REG_GPIO_ALERT_LEVEL(config->gpio_port), mask,
new_reg);
if (ret < 0) {
goto done;
@ -428,21 +362,16 @@ static int gpio_nct38xx_pin_interrupt_configure(const struct device *dev, gpio_p
}
/* Clear pending bit */
ret = nct38xx_reg_write_byte(config->mfd,
NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port), mask);
ret = i2c_reg_write_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port),
mask);
if (ret < 0) {
goto done;
}
/* Enable it after configuration is completed */
ret = nct38xx_reg_read_byte(config->mfd,
NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), &reg);
if (ret < 0) {
goto done;
}
new_reg = reg | mask;
ret = nct38xx_reg_update(config->mfd,
NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), reg, new_reg);
new_reg = mask;
ret = i2c_reg_update_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port),
mask, new_reg);
done:
k_sem_give(data->lock);
@ -472,8 +401,7 @@ static int gpio_nct38xx_port_get_direction(const struct device *dev, gpio_port_p
if (config->gpio_port == 0) {
uint8_t enabled_gpios;
/* Remove the disabled GPIOs from the mask */
ret = nct38xx_reg_read_byte(config->mfd, NCT38XX_REG_MUX_CONTROL,
&enabled_gpios);
ret = i2c_reg_read_byte_dt(data->i2c_dev, NCT38XX_REG_MUX_CONTROL, &enabled_gpios);
mask &= (enabled_gpios & config->common.port_pin_mask);
if (ret < 0) {
@ -482,8 +410,8 @@ static int gpio_nct38xx_port_get_direction(const struct device *dev, gpio_port_p
}
/* Read direction register, 0 - input, 1 - output */
ret = nct38xx_reg_read_byte(config->mfd, NCT38XX_REG_GPIO_DIR(config->gpio_port),
&dir_reg);
ret = i2c_reg_read_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DIR(config->gpio_port),
&dir_reg);
if (ret < 0) {
goto done;
}
@ -511,25 +439,24 @@ int gpio_nct38xx_dispatch_port_isr(const struct device *dev)
do {
k_sem_take(data->lock, K_FOREVER);
ret = nct38xx_reg_read_byte(config->mfd,
NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port),
&alert_pins);
ret = i2c_reg_read_byte_dt(
data->i2c_dev, NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port), &alert_pins);
if (ret < 0) {
k_sem_give(data->lock);
return ret;
}
ret = nct38xx_reg_read_byte(config->mfd,
NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), &mask);
ret = i2c_reg_read_byte_dt(data->i2c_dev,
NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), &mask);
if (ret < 0) {
k_sem_give(data->lock);
return ret;
}
alert_pins &= mask;
if (alert_pins) {
ret = nct38xx_reg_write_byte(config->mfd,
NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port),
alert_pins);
ret = i2c_reg_write_byte_dt(data->i2c_dev,
NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port),
alert_pins);
if (ret < 0) {
k_sem_give(data->lock);
return ret;
@ -577,6 +504,7 @@ static int gpio_nct38xx_port_init(const struct device *dev)
}
data->lock = mfd_nct38xx_get_lock_reference(config->mfd);
data->i2c_dev = mfd_nct38xx_get_i2c_dt_spec(config->mfd);
return 0;
}

View file

@ -37,43 +37,11 @@ struct k_sem *mfd_nct38xx_get_lock_reference(const struct device *dev)
return &data->lock;
}
int nct38xx_reg_read_byte(const struct device *dev, uint8_t reg_addr, uint8_t *val)
const struct i2c_dt_spec *mfd_nct38xx_get_i2c_dt_spec(const struct device *dev)
{
const struct mfd_nct38xx_config *const config = dev->config;
const struct mfd_nct38xx_config *config = dev->config;
return i2c_reg_read_byte_dt(&config->i2c_dev, reg_addr, val);
}
int nct38xx_reg_burst_read(const struct device *dev, uint8_t start_addr, uint8_t *buf,
uint32_t num_bytes)
{
const struct mfd_nct38xx_config *const config = dev->config;
return i2c_burst_read_dt(&config->i2c_dev, start_addr, buf, num_bytes);
}
int nct38xx_reg_write_byte(const struct device *dev, uint8_t reg_addr, uint8_t val)
{
const struct mfd_nct38xx_config *const config = dev->config;
return i2c_reg_write_byte_dt(&config->i2c_dev, reg_addr, val);
}
int nct38xx_reg_burst_write(const struct device *dev, uint8_t start_addr, uint8_t *buf,
uint32_t num_bytes)
{
const struct mfd_nct38xx_config *const config = dev->config;
return i2c_burst_write_dt(&config->i2c_dev, start_addr, buf, num_bytes);
}
int nct38xx_reg_update(const struct device *dev, uint8_t reg_addr, uint8_t reg_val, uint8_t new_val)
{
if (reg_val == new_val) {
return 0;
}
return nct38xx_reg_write_byte(dev, reg_addr, new_val);
return &config->i2c_dev;
}
#define MFD_NCT38XX_DEFINE(inst) \

View file

@ -7,6 +7,7 @@
#define ZEPHYR_INCLUDE_DRIVERS_MFD_NCT38XX_H_
#include <zephyr/device.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/kernel.h>
#ifdef __cplusplus
@ -24,65 +25,13 @@ extern "C" {
struct k_sem *mfd_nct38xx_get_lock_reference(const struct device *dev);
/**
* @brief Read a NCT38XX register
* @brief Get the I2C DT spec reference for a NCT38xx instance.
*
* @param dev NCT38XX multi-function device
* @param reg_addr Register address
* @param val A pointer to a buffer for the data to return
* @param[in] dev Pointer to device struct of the driver instance
*
* @return 0 if successful, otherwise failed.
* @return Address of the I2C DT spec
*/
int nct38xx_reg_read_byte(const struct device *dev, uint8_t reg_addr, uint8_t *val);
/**
* @brief Read a sequence of NCT38XX registers
*
* @param dev NCT38XX multi-function device
* @param start_addr The register start address
* @param buf A pointer to a buffer for the data to return
* @param num_bytes Number of data to read
*
* @return 0 if successful, otherwise failed.
*/
int nct38xx_reg_burst_read(const struct device *dev, uint8_t start_addr, uint8_t *buf,
uint32_t num_bytes);
/**
* @brief Write a NCT38XX register
*
* @param dev NCT38XX device
* @param reg_addr Register address
* @param val Data to write
*
* @return 0 if successful, otherwise failed.
*/
int nct38xx_reg_write_byte(const struct device *dev, uint8_t reg_addr, uint8_t val);
/**
* @brief Write a sequence of NCT38XX registers
*
* @param dev NCT38XX device
* @param start_addr The register start address
* @param buf A pointer to a buffer for the data to write
* @param num_bytes Number of data to write
*
* @return 0 if successful, otherwise failed.
*/
int nct38xx_reg_burst_write(const struct device *dev, uint8_t start_addr, uint8_t *buf,
uint32_t num_bytes);
/**
* @brief Compare data & write a NCT38XX register
*
* @param dev NCT38XX device
* @param reg_addr Register address
* @param reg_val Old register data
* @param new_val New register data
*
* @return 0 if successful, otherwise failed.
*/
int nct38xx_reg_update(const struct device *dev, uint8_t reg_addr, uint8_t reg_val,
uint8_t new_val);
const struct i2c_dt_spec *mfd_nct38xx_get_i2c_dt_spec(const struct device *dev);
#ifdef __cplusplus
}