diff --git a/drivers/gpio/gpio_nct38xx.c b/drivers/gpio/gpio_nct38xx.c index eb5412fce5c..a4949f1f9bb 100644 --- a/drivers/gpio/gpio_nct38xx.c +++ b/drivers/gpio/gpio_nct38xx.c @@ -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); diff --git a/drivers/gpio/gpio_nct38xx_alert.c b/drivers/gpio/gpio_nct38xx_alert.c index 7b5a14b722d..eb52339364a 100644 --- a/drivers/gpio/gpio_nct38xx_alert.c +++ b/drivers/gpio/gpio_nct38xx_alert.c @@ -18,6 +18,13 @@ #include 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, \ diff --git a/drivers/gpio/gpio_nct38xx_port.c b/drivers/gpio/gpio_nct38xx_port.c index d21d66734d6..32d70808fcd 100644 --- a/drivers/gpio/gpio_nct38xx_port.c +++ b/drivers/gpio/gpio_nct38xx_port.c @@ -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, ®); - 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), ®); - 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), - ®); - 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), - ®); - 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), ®); - 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, ®); + ret = i2c_reg_read_byte_dt(data->i2c_dev, NCT38XX_REG_MUX_CONTROL, ®); 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), - ®); + ret = i2c_reg_read_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DIR(config->gpio_port), ®); 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), ®); + ret = i2c_reg_read_byte_dt(data->i2c_dev, + NCT38XX_REG_GPIO_OD_SEL(config->gpio_port), ®); 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), ®); + ret = i2c_reg_read_byte_dt(data->i2c_dev, + NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), ®); 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), ®); - 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), ®); - 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), ®); - 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), - ®); + ret = i2c_reg_read_byte_dt(data->i2c_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), + ®); 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), ®); - 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), ®); - 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), ®); - 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; } diff --git a/drivers/mfd/mfd_nct38xx.c b/drivers/mfd/mfd_nct38xx.c index ac5885fd46c..81b6ece4d1a 100644 --- a/drivers/mfd/mfd_nct38xx.c +++ b/drivers/mfd/mfd_nct38xx.c @@ -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) \ diff --git a/include/zephyr/drivers/mfd/nct38xx.h b/include/zephyr/drivers/mfd/nct38xx.h index 2ea4513c281..40e1a87fc26 100644 --- a/include/zephyr/drivers/mfd/nct38xx.h +++ b/include/zephyr/drivers/mfd/nct38xx.h @@ -7,6 +7,7 @@ #define ZEPHYR_INCLUDE_DRIVERS_MFD_NCT38XX_H_ #include +#include #include #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 }