mfd: Add NCT38xx multi-function driver
The Nuvoton NCT38xx is a multi-function device providing a TCPC controller and a I/O expander (GPIO driver). Add a multi-function driver to manage exclusive access to the device. Tested with "twister -T tests/drivers/build_all/gpio". Signed-off-by: Keith Short <keithshort@google.com>
This commit is contained in:
parent
617c7cb337
commit
ea40f3af24
14 changed files with 442 additions and 281 deletions
|
@ -7,7 +7,8 @@ config GPIO_NCT38XX
|
||||||
bool "NCT38XX I2C-based GPIO chip"
|
bool "NCT38XX I2C-based GPIO chip"
|
||||||
default y
|
default y
|
||||||
depends on DT_HAS_NUVOTON_NCT38XX_GPIO_PORT_ENABLED
|
depends on DT_HAS_NUVOTON_NCT38XX_GPIO_PORT_ENABLED
|
||||||
depends on I2C
|
select I2C
|
||||||
|
select MFD
|
||||||
help
|
help
|
||||||
Enable driver for NCT38XX I2C-based GPIO chip.
|
Enable driver for NCT38XX I2C-based GPIO chip.
|
||||||
|
|
||||||
|
@ -15,17 +16,17 @@ if GPIO_NCT38XX
|
||||||
|
|
||||||
config GPIO_NCT38XX_INIT_PRIORITY
|
config GPIO_NCT38XX_INIT_PRIORITY
|
||||||
int "NCT38XX GPIO init priority"
|
int "NCT38XX GPIO init priority"
|
||||||
default 51
|
default 62
|
||||||
help
|
help
|
||||||
Device driver initialization priority. The priority should be lower
|
NCT38xx GPIO driver initialization priority. The priority must be lower
|
||||||
than I2C device.
|
than MFD_INIT_PRIORITY.
|
||||||
|
|
||||||
config GPIO_NCT38XX_PORT_INIT_PRIORITY
|
config GPIO_NCT38XX_PORT_INIT_PRIORITY
|
||||||
int "NCT38XX GPIO port init priority"
|
int "NCT38XX GPIO port init priority"
|
||||||
default 52
|
default 64
|
||||||
help
|
help
|
||||||
Device driver initialization priority. The priority should be lower
|
NCT38xx GPIO port device driver initialization priority. The priority
|
||||||
than I2C & GPIO_NCT38XX_INIT_PRIORITY device.
|
must be lower than GPIO_NCT38XX_INIT_PRIORITY device.
|
||||||
|
|
||||||
config GPIO_NCT38XX_ALERT
|
config GPIO_NCT38XX_ALERT
|
||||||
bool "NCT38XX GPIO interrupt"
|
bool "NCT38XX GPIO interrupt"
|
||||||
|
@ -36,7 +37,7 @@ config GPIO_NCT38XX_ALERT
|
||||||
|
|
||||||
config GPIO_NCT38XX_ALERT_INIT_PRIORITY
|
config GPIO_NCT38XX_ALERT_INIT_PRIORITY
|
||||||
int "NCT38XX GPIO alert handler init priority"
|
int "NCT38XX GPIO alert handler init priority"
|
||||||
default 52
|
default 64
|
||||||
depends on GPIO_NCT38XX_ALERT
|
depends on GPIO_NCT38XX_ALERT
|
||||||
help
|
help
|
||||||
NCT38XX alert handler initialization priority. This initialization
|
NCT38XX alert handler initialization priority. This initialization
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <zephyr/device.h>
|
#include <zephyr/device.h>
|
||||||
#include <zephyr/drivers/gpio.h>
|
#include <zephyr/drivers/gpio.h>
|
||||||
#include <zephyr/drivers/gpio/gpio_nct38xx.h>
|
#include <zephyr/drivers/gpio/gpio_nct38xx.h>
|
||||||
|
#include <zephyr/drivers/mfd/nct38xx.h>
|
||||||
#include <zephyr/kernel.h>
|
#include <zephyr/kernel.h>
|
||||||
#include <zephyr/sys/util_macro.h>
|
#include <zephyr/sys/util_macro.h>
|
||||||
|
|
||||||
|
@ -17,6 +18,25 @@
|
||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
LOG_MODULE_REGISTER(gpio_ntc38xx, CONFIG_GPIO_LOG_LEVEL);
|
LOG_MODULE_REGISTER(gpio_ntc38xx, CONFIG_GPIO_LOG_LEVEL);
|
||||||
|
|
||||||
|
/* Driver config */
|
||||||
|
struct gpio_nct38xx_config {
|
||||||
|
/* Multi-function device, parent to the NCT38xx GPIO controller */
|
||||||
|
const struct device *mfd;
|
||||||
|
/* GPIO ports */
|
||||||
|
const struct device **sub_gpio_dev;
|
||||||
|
uint8_t sub_gpio_port_num;
|
||||||
|
/* Alert handler */
|
||||||
|
const struct device *alert_dev;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Driver data */
|
||||||
|
struct gpio_nct38xx_data {
|
||||||
|
/* NCT38XX device */
|
||||||
|
const struct device *dev;
|
||||||
|
/* lock NCT38xx register access */
|
||||||
|
struct k_sem *lock;
|
||||||
|
};
|
||||||
|
|
||||||
void nct38xx_gpio_alert_handler(const struct device *dev)
|
void nct38xx_gpio_alert_handler(const struct device *dev)
|
||||||
{
|
{
|
||||||
const struct gpio_nct38xx_config *const config = dev->config;
|
const struct gpio_nct38xx_config *const config = dev->config;
|
||||||
|
@ -29,11 +49,16 @@ void nct38xx_gpio_alert_handler(const struct device *dev)
|
||||||
static int nct38xx_init_interrupt(const struct device *dev)
|
static int nct38xx_init_interrupt(const struct device *dev)
|
||||||
{
|
{
|
||||||
uint16_t alert, alert_mask = 0;
|
uint16_t alert, alert_mask = 0;
|
||||||
|
int ret = 0;
|
||||||
|
struct gpio_nct38xx_data *data = dev->data;
|
||||||
|
|
||||||
|
k_sem_take(data->lock, K_FOREVER);
|
||||||
|
|
||||||
/* Disable all interrupt */
|
/* Disable all interrupt */
|
||||||
if (nct38xx_reg_burst_write(dev, NCT38XX_REG_ALERT_MASK, (uint8_t *)&alert_mask,
|
if (nct38xx_reg_burst_write(dev, NCT38XX_REG_ALERT_MASK, (uint8_t *)&alert_mask,
|
||||||
sizeof(alert_mask))) {
|
sizeof(alert_mask))) {
|
||||||
return -EIO;
|
ret = -EIO;
|
||||||
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable vendor-defined alert for GPIO. */
|
/* Enable vendor-defined alert for GPIO. */
|
||||||
|
@ -41,34 +66,42 @@ static int nct38xx_init_interrupt(const struct device *dev)
|
||||||
|
|
||||||
/* Clear alert */
|
/* Clear alert */
|
||||||
if (nct38xx_reg_burst_read(dev, NCT38XX_REG_ALERT, (uint8_t *)&alert, sizeof(alert))) {
|
if (nct38xx_reg_burst_read(dev, NCT38XX_REG_ALERT, (uint8_t *)&alert, sizeof(alert))) {
|
||||||
return -EIO;
|
ret = -EIO;
|
||||||
|
goto unlock;
|
||||||
}
|
}
|
||||||
alert &= alert_mask;
|
alert &= alert_mask;
|
||||||
if (alert) {
|
if (alert) {
|
||||||
if (nct38xx_reg_burst_write(dev, NCT38XX_REG_ALERT, (uint8_t *)&alert,
|
if (nct38xx_reg_burst_write(dev, NCT38XX_REG_ALERT, (uint8_t *)&alert,
|
||||||
sizeof(alert))) {
|
sizeof(alert))) {
|
||||||
return -EIO;
|
ret = -EIO;
|
||||||
|
goto unlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nct38xx_reg_burst_write(dev, NCT38XX_REG_ALERT_MASK, (uint8_t *)&alert_mask,
|
if (nct38xx_reg_burst_write(dev, NCT38XX_REG_ALERT_MASK, (uint8_t *)&alert_mask,
|
||||||
sizeof(alert_mask))) {
|
sizeof(alert_mask))) {
|
||||||
return -EIO;
|
ret = -EIO;
|
||||||
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
unlock:
|
||||||
|
k_sem_give(data->lock);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nct38xx_gpio_init(const struct device *dev)
|
static int nct38xx_gpio_init(const struct device *dev)
|
||||||
{
|
{
|
||||||
const struct gpio_nct38xx_config *const config = dev->config;
|
const struct gpio_nct38xx_config *const config = dev->config;
|
||||||
|
struct gpio_nct38xx_data *data = dev->data;
|
||||||
|
|
||||||
/* Check I2C is ready */
|
/* Verify multi-function parent is ready */
|
||||||
if (!device_is_ready(config->i2c_dev.bus)) {
|
if (!device_is_ready(config->mfd)) {
|
||||||
LOG_ERR("%s device not ready", config->i2c_dev.bus->name);
|
LOG_ERR("%s device not ready", config->mfd->name);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data->lock = mfd_nct38xx_get_lock_reference(config->mfd);
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_GPIO_NCT38XX_ALERT)) {
|
if (IS_ENABLED(CONFIG_GPIO_NCT38XX_ALERT)) {
|
||||||
nct38xx_init_interrupt(dev);
|
nct38xx_init_interrupt(dev);
|
||||||
}
|
}
|
||||||
|
@ -81,7 +114,7 @@ static int nct38xx_gpio_init(const struct device *dev)
|
||||||
DT_INST_FOREACH_CHILD_STATUS_OKAY_SEP(inst, DEVICE_DT_GET, (,)) \
|
DT_INST_FOREACH_CHILD_STATUS_OKAY_SEP(inst, DEVICE_DT_GET, (,)) \
|
||||||
}; \
|
}; \
|
||||||
static const struct gpio_nct38xx_config gpio_nct38xx_cfg_##inst = { \
|
static const struct gpio_nct38xx_config gpio_nct38xx_cfg_##inst = { \
|
||||||
.i2c_dev = I2C_DT_SPEC_INST_GET(inst), \
|
.mfd = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
|
||||||
.sub_gpio_dev = sub_gpio_dev_##inst, \
|
.sub_gpio_dev = sub_gpio_dev_##inst, \
|
||||||
.sub_gpio_port_num = ARRAY_SIZE(sub_gpio_dev_##inst), \
|
.sub_gpio_port_num = ARRAY_SIZE(sub_gpio_dev_##inst), \
|
||||||
}; \
|
}; \
|
||||||
|
@ -93,3 +126,6 @@ static int nct38xx_gpio_init(const struct device *dev)
|
||||||
CONFIG_GPIO_NCT38XX_INIT_PRIORITY, NULL);
|
CONFIG_GPIO_NCT38XX_INIT_PRIORITY, NULL);
|
||||||
|
|
||||||
DT_INST_FOREACH_STATUS_OKAY(GPIO_NCT38XX_DEVICE_INSTANCE)
|
DT_INST_FOREACH_STATUS_OKAY(GPIO_NCT38XX_DEVICE_INSTANCE)
|
||||||
|
|
||||||
|
/* The nct38xx MFD parent must be initialized before this driver */
|
||||||
|
BUILD_ASSERT(CONFIG_GPIO_NCT38XX_INIT_PRIORITY > CONFIG_MFD_INIT_PRIORITY);
|
||||||
|
|
|
@ -31,110 +31,6 @@
|
||||||
#define NCT38XX_REG_ALERT_VENDOR_DEFINDED_ALERT 15
|
#define NCT38XX_REG_ALERT_VENDOR_DEFINDED_ALERT 15
|
||||||
#define NCT38XX_REG_ALERT_MASK_VENDOR_DEFINDED_ALERT 15
|
#define NCT38XX_REG_ALERT_MASK_VENDOR_DEFINDED_ALERT 15
|
||||||
|
|
||||||
/* Driver config */
|
|
||||||
struct gpio_nct38xx_config {
|
|
||||||
/* I2C device */
|
|
||||||
const struct i2c_dt_spec i2c_dev;
|
|
||||||
/* GPIO ports */
|
|
||||||
const struct device **sub_gpio_dev;
|
|
||||||
uint8_t sub_gpio_port_num;
|
|
||||||
/* Alert handler */
|
|
||||||
const struct device *alert_dev;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Driver data */
|
|
||||||
struct gpio_nct38xx_data {
|
|
||||||
/* NCT38XX device */
|
|
||||||
const struct device *dev;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read a NCT38XX register
|
|
||||||
*
|
|
||||||
* @param dev NCT38XX device
|
|
||||||
* @param reg_addr Register address
|
|
||||||
* @param val A pointer to a buffer for the data to return
|
|
||||||
*
|
|
||||||
* @return 0 if successful, otherwise failed.
|
|
||||||
*/
|
|
||||||
static inline int nct38xx_reg_read_byte(const struct device *dev, uint8_t reg_addr, uint8_t *val)
|
|
||||||
{
|
|
||||||
const struct gpio_nct38xx_config *const config =
|
|
||||||
(const struct gpio_nct38xx_config *)dev->config;
|
|
||||||
return i2c_reg_read_byte_dt(&config->i2c_dev, reg_addr, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read 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 return
|
|
||||||
* @param num_bytes Number of data to read
|
|
||||||
*
|
|
||||||
* @return 0 if successful, otherwise failed.
|
|
||||||
*/
|
|
||||||
static inline int nct38xx_reg_burst_read(const struct device *dev, uint8_t start_addr, uint8_t *buf,
|
|
||||||
uint32_t num_bytes)
|
|
||||||
{
|
|
||||||
const struct gpio_nct38xx_config *const config =
|
|
||||||
(const struct gpio_nct38xx_config *)dev->config;
|
|
||||||
return i2c_burst_read_dt(&config->i2c_dev, start_addr, buf, 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.
|
|
||||||
*/
|
|
||||||
static inline int nct38xx_reg_write_byte(const struct device *dev, uint8_t reg_addr, uint8_t val)
|
|
||||||
{
|
|
||||||
const struct gpio_nct38xx_config *const config =
|
|
||||||
(const struct gpio_nct38xx_config *)dev->config;
|
|
||||||
return i2c_reg_write_byte_dt(&config->i2c_dev, reg_addr, 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.
|
|
||||||
*/
|
|
||||||
static inline int nct38xx_reg_burst_write(const struct device *dev, uint8_t start_addr,
|
|
||||||
uint8_t *buf, uint32_t num_bytes)
|
|
||||||
{
|
|
||||||
const struct gpio_nct38xx_config *const config =
|
|
||||||
(const struct gpio_nct38xx_config *)dev->config;
|
|
||||||
return i2c_burst_write_dt(&config->i2c_dev, start_addr, buf, 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.
|
|
||||||
*/
|
|
||||||
static inline 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Dispatch GPIO port ISR
|
* @brief Dispatch GPIO port ISR
|
||||||
*
|
*
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <zephyr/device.h>
|
#include <zephyr/device.h>
|
||||||
#include <zephyr/drivers/gpio.h>
|
#include <zephyr/drivers/gpio.h>
|
||||||
#include <zephyr/drivers/gpio/gpio_nct38xx.h>
|
#include <zephyr/drivers/gpio/gpio_nct38xx.h>
|
||||||
|
#include <zephyr/drivers/mfd/nct38xx.h>
|
||||||
#include <zephyr/kernel.h>
|
#include <zephyr/kernel.h>
|
||||||
#include <zephyr/sys/util_macro.h>
|
#include <zephyr/sys/util_macro.h>
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
|
|
||||||
#include "gpio_nct38xx.h"
|
#include "gpio_nct38xx.h"
|
||||||
#include <zephyr/drivers/gpio/gpio_utils.h>
|
#include <zephyr/drivers/gpio/gpio_utils.h>
|
||||||
|
|
||||||
#include <zephyr/drivers/gpio.h>
|
#include <zephyr/drivers/gpio.h>
|
||||||
|
#include <zephyr/drivers/mfd/nct38xx.h>
|
||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
LOG_MODULE_DECLARE(gpio_ntc38xx, CONFIG_GPIO_LOG_LEVEL);
|
LOG_MODULE_DECLARE(gpio_ntc38xx, CONFIG_GPIO_LOG_LEVEL);
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ struct gpio_nct38xx_port_config {
|
||||||
/* gpio_driver_config needs to be first */
|
/* gpio_driver_config needs to be first */
|
||||||
struct gpio_driver_config common;
|
struct gpio_driver_config common;
|
||||||
/* NCT38XX controller dev */
|
/* NCT38XX controller dev */
|
||||||
const struct device *nct38xx_dev;
|
const struct device *mfd;
|
||||||
/* GPIO port index */
|
/* GPIO port index */
|
||||||
uint8_t gpio_port;
|
uint8_t gpio_port;
|
||||||
/* GPIO port 0 pinmux mask */
|
/* GPIO port 0 pinmux mask */
|
||||||
|
@ -31,8 +31,8 @@ struct gpio_nct38xx_port_data {
|
||||||
struct gpio_driver_data common;
|
struct gpio_driver_data common;
|
||||||
/* GPIO callback list */
|
/* GPIO callback list */
|
||||||
sys_slist_t cb_list_gpio;
|
sys_slist_t cb_list_gpio;
|
||||||
/* lock GPIO register access */
|
/* lock NCT38xx register access */
|
||||||
struct k_sem lock;
|
struct k_sem *lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* GPIO api functions */
|
/* GPIO api functions */
|
||||||
|
@ -59,11 +59,11 @@ static int gpio_nct38xx_pin_config(const struct device *dev, gpio_pin_t pin, gpi
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
k_sem_take(&data->lock, K_FOREVER);
|
k_sem_take(data->lock, K_FOREVER);
|
||||||
|
|
||||||
/* Pin multiplexing */
|
/* Pin multiplexing */
|
||||||
if (config->gpio_port == 0) {
|
if (config->gpio_port == 0) {
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev, NCT38XX_REG_MUX_CONTROL, ®);
|
ret = nct38xx_reg_read_byte(config->mfd, NCT38XX_REG_MUX_CONTROL, ®);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -72,8 +72,7 @@ static int gpio_nct38xx_pin_config(const struct device *dev, gpio_pin_t pin, gpi
|
||||||
/* NCT3807 bit3 must be set to 0 */
|
/* NCT3807 bit3 must be set to 0 */
|
||||||
new_reg &= config->pinmux_mask;
|
new_reg &= config->pinmux_mask;
|
||||||
|
|
||||||
ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_MUX_CONTROL, reg,
|
ret = nct38xx_reg_update(config->mfd, NCT38XX_REG_MUX_CONTROL, reg, new_reg);
|
||||||
new_reg);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -81,20 +80,20 @@ static int gpio_nct38xx_pin_config(const struct device *dev, gpio_pin_t pin, gpi
|
||||||
|
|
||||||
/* Configure pin as input. */
|
/* Configure pin as input. */
|
||||||
if (flags & GPIO_INPUT) {
|
if (flags & GPIO_INPUT) {
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev,
|
ret = nct38xx_reg_read_byte(config->mfd,
|
||||||
NCT38XX_REG_GPIO_DIR(config->gpio_port), ®);
|
NCT38XX_REG_GPIO_DIR(config->gpio_port), ®);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
new_reg = reg & ~mask;
|
new_reg = reg & ~mask;
|
||||||
ret = nct38xx_reg_update(config->nct38xx_dev,
|
ret = nct38xx_reg_update(config->mfd,
|
||||||
NCT38XX_REG_GPIO_DIR(config->gpio_port), reg, new_reg);
|
NCT38XX_REG_GPIO_DIR(config->gpio_port), reg, new_reg);
|
||||||
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Select open drain 0:push-pull 1:open-drain */
|
/* Select open drain 0:push-pull 1:open-drain */
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev, NCT38XX_REG_GPIO_OD_SEL(config->gpio_port),
|
ret = nct38xx_reg_read_byte(config->mfd, NCT38XX_REG_GPIO_OD_SEL(config->gpio_port),
|
||||||
®);
|
®);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -104,14 +103,14 @@ static int gpio_nct38xx_pin_config(const struct device *dev, gpio_pin_t pin, gpi
|
||||||
} else {
|
} else {
|
||||||
new_reg = reg & ~mask;
|
new_reg = reg & ~mask;
|
||||||
}
|
}
|
||||||
ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_GPIO_OD_SEL(config->gpio_port),
|
ret = nct38xx_reg_update(config->mfd, NCT38XX_REG_GPIO_OD_SEL(config->gpio_port),
|
||||||
reg, new_reg);
|
reg, new_reg);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set level 0:low 1:high */
|
/* Set level 0:low 1:high */
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev,
|
ret = nct38xx_reg_read_byte(config->mfd,
|
||||||
NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
|
NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
|
||||||
®);
|
®);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -122,7 +121,7 @@ static int gpio_nct38xx_pin_config(const struct device *dev, gpio_pin_t pin, gpi
|
||||||
} else if (flags & GPIO_OUTPUT_INIT_LOW) {
|
} else if (flags & GPIO_OUTPUT_INIT_LOW) {
|
||||||
new_reg = reg & ~mask;
|
new_reg = reg & ~mask;
|
||||||
}
|
}
|
||||||
ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
|
ret = nct38xx_reg_update(config->mfd, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
|
||||||
reg, new_reg);
|
reg, new_reg);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -130,18 +129,18 @@ static int gpio_nct38xx_pin_config(const struct device *dev, gpio_pin_t pin, gpi
|
||||||
|
|
||||||
/* Configure pin as output, if requested 0:input 1:output */
|
/* Configure pin as output, if requested 0:input 1:output */
|
||||||
if (flags & GPIO_OUTPUT) {
|
if (flags & GPIO_OUTPUT) {
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev,
|
ret = nct38xx_reg_read_byte(config->mfd,
|
||||||
NCT38XX_REG_GPIO_DIR(config->gpio_port), ®);
|
NCT38XX_REG_GPIO_DIR(config->gpio_port), ®);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
new_reg = reg | mask;
|
new_reg = reg | mask;
|
||||||
ret = nct38xx_reg_update(config->nct38xx_dev,
|
ret = nct38xx_reg_update(config->mfd,
|
||||||
NCT38XX_REG_GPIO_DIR(config->gpio_port), reg, new_reg);
|
NCT38XX_REG_GPIO_DIR(config->gpio_port), reg, new_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
k_sem_give(&data->lock);
|
k_sem_give(data->lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +153,7 @@ int gpio_nct38xx_pin_get_config(const struct device *dev, gpio_pin_t pin, gpio_f
|
||||||
uint8_t reg;
|
uint8_t reg;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
k_sem_take(&data->lock, K_FOREVER);
|
k_sem_take(data->lock, K_FOREVER);
|
||||||
|
|
||||||
if (config->gpio_port == 0) {
|
if (config->gpio_port == 0) {
|
||||||
if (mask & (~config->common.port_pin_mask)) {
|
if (mask & (~config->common.port_pin_mask)) {
|
||||||
|
@ -162,7 +161,7 @@ int gpio_nct38xx_pin_get_config(const struct device *dev, gpio_pin_t pin, gpio_f
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev, NCT38XX_REG_MUX_CONTROL, ®);
|
ret = nct38xx_reg_read_byte(config->mfd, NCT38XX_REG_MUX_CONTROL, ®);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -173,7 +172,7 @@ int gpio_nct38xx_pin_get_config(const struct device *dev, gpio_pin_t pin, gpio_f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev, NCT38XX_REG_GPIO_DIR(config->gpio_port),
|
ret = nct38xx_reg_read_byte(config->mfd, NCT38XX_REG_GPIO_DIR(config->gpio_port),
|
||||||
®);
|
®);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -184,7 +183,7 @@ int gpio_nct38xx_pin_get_config(const struct device *dev, gpio_pin_t pin, gpio_f
|
||||||
*flags = GPIO_OUTPUT;
|
*flags = GPIO_OUTPUT;
|
||||||
|
|
||||||
/* 0 - push-pull, 1 - open-drain */
|
/* 0 - push-pull, 1 - open-drain */
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev,
|
ret = nct38xx_reg_read_byte(config->mfd,
|
||||||
NCT38XX_REG_GPIO_OD_SEL(config->gpio_port), ®);
|
NCT38XX_REG_GPIO_OD_SEL(config->gpio_port), ®);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -195,7 +194,7 @@ int gpio_nct38xx_pin_get_config(const struct device *dev, gpio_pin_t pin, gpio_f
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Output value */
|
/* Output value */
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev,
|
ret = nct38xx_reg_read_byte(config->mfd,
|
||||||
NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), ®);
|
NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), ®);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -212,7 +211,7 @@ int gpio_nct38xx_pin_get_config(const struct device *dev, gpio_pin_t pin, gpio_f
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
k_sem_give(&data->lock);
|
k_sem_give(data->lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_GPIO_GET_CONFIG */
|
#endif /* CONFIG_GPIO_GET_CONFIG */
|
||||||
|
@ -223,12 +222,12 @@ static int gpio_nct38xx_port_get_raw(const struct device *dev, gpio_port_value_t
|
||||||
const struct gpio_nct38xx_port_config *const config = dev->config;
|
const struct gpio_nct38xx_port_config *const config = dev->config;
|
||||||
struct gpio_nct38xx_port_data *const data = dev->data;
|
struct gpio_nct38xx_port_data *const data = dev->data;
|
||||||
|
|
||||||
k_sem_take(&data->lock, K_FOREVER);
|
k_sem_take(data->lock, K_FOREVER);
|
||||||
|
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev,
|
ret = nct38xx_reg_read_byte(config->mfd,
|
||||||
NCT38XX_REG_GPIO_DATA_IN(config->gpio_port), (uint8_t *)value);
|
NCT38XX_REG_GPIO_DATA_IN(config->gpio_port), (uint8_t *)value);
|
||||||
|
|
||||||
k_sem_give(&data->lock);
|
k_sem_give(data->lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,19 +239,19 @@ static int gpio_nct38xx_port_set_masked_raw(const struct device *dev, gpio_port_
|
||||||
uint8_t reg, new_reg;
|
uint8_t reg, new_reg;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
k_sem_take(&data->lock, K_FOREVER);
|
k_sem_take(data->lock, K_FOREVER);
|
||||||
|
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev,
|
ret = nct38xx_reg_read_byte(config->mfd,
|
||||||
NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), ®);
|
NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), ®);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
new_reg = ((reg & ~mask) | (value & mask));
|
new_reg = ((reg & ~mask) | (value & mask));
|
||||||
ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
|
ret = nct38xx_reg_update(config->mfd, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
|
||||||
reg, new_reg);
|
reg, new_reg);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
k_sem_give(&data->lock);
|
k_sem_give(data->lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -264,19 +263,19 @@ static int gpio_nct38xx_port_set_bits_raw(const struct device *dev, gpio_port_pi
|
||||||
uint8_t reg, new_reg;
|
uint8_t reg, new_reg;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
k_sem_take(&data->lock, K_FOREVER);
|
k_sem_take(data->lock, K_FOREVER);
|
||||||
|
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev,
|
ret = nct38xx_reg_read_byte(config->mfd,
|
||||||
NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), ®);
|
NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), ®);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
new_reg = reg | mask;
|
new_reg = reg | mask;
|
||||||
ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
|
ret = nct38xx_reg_update(config->mfd, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
|
||||||
reg, new_reg);
|
reg, new_reg);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
k_sem_give(&data->lock);
|
k_sem_give(data->lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -288,19 +287,19 @@ static int gpio_nct38xx_port_clear_bits_raw(const struct device *dev, gpio_port_
|
||||||
uint8_t reg, new_reg;
|
uint8_t reg, new_reg;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
k_sem_take(&data->lock, K_FOREVER);
|
k_sem_take(data->lock, K_FOREVER);
|
||||||
|
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev,
|
ret = nct38xx_reg_read_byte(config->mfd,
|
||||||
NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), ®);
|
NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), ®);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
new_reg = reg & ~mask;
|
new_reg = reg & ~mask;
|
||||||
ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
|
ret = nct38xx_reg_update(config->mfd, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
|
||||||
reg, new_reg);
|
reg, new_reg);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
k_sem_give(&data->lock);
|
k_sem_give(data->lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -312,19 +311,19 @@ static int gpio_nct38xx_port_toggle_bits(const struct device *dev, gpio_port_pin
|
||||||
uint8_t reg, new_reg;
|
uint8_t reg, new_reg;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
k_sem_take(&data->lock, K_FOREVER);
|
k_sem_take(data->lock, K_FOREVER);
|
||||||
|
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev,
|
ret = nct38xx_reg_read_byte(config->mfd, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
|
||||||
NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port), ®);
|
®);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
new_reg = reg ^ mask;
|
new_reg = reg ^ mask;
|
||||||
ret = nct38xx_reg_update(config->nct38xx_dev, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
|
ret = nct38xx_reg_update(config->mfd, NCT38XX_REG_GPIO_DATA_OUT(config->gpio_port),
|
||||||
reg, new_reg);
|
reg, new_reg);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
k_sem_give(&data->lock);
|
k_sem_give(data->lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -338,16 +337,16 @@ static int gpio_nct38xx_pin_interrupt_configure(const struct device *dev, gpio_p
|
||||||
int ret;
|
int ret;
|
||||||
uint32_t mask = BIT(pin);
|
uint32_t mask = BIT(pin);
|
||||||
|
|
||||||
k_sem_take(&data->lock, K_FOREVER);
|
k_sem_take(data->lock, K_FOREVER);
|
||||||
|
|
||||||
/* Disable irq before configuring them */
|
/* Disable irq before configuring them */
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev,
|
ret = nct38xx_reg_read_byte(config->mfd,
|
||||||
NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), ®);
|
NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), ®);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
new_reg = reg & ~mask;
|
new_reg = reg & ~mask;
|
||||||
ret = nct38xx_reg_update(config->nct38xx_dev,
|
ret = nct38xx_reg_update(config->mfd,
|
||||||
NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), reg, new_reg);
|
NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), reg, new_reg);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -359,12 +358,12 @@ static int gpio_nct38xx_pin_interrupt_configure(const struct device *dev, gpio_p
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set edge register */
|
/* set edge register */
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev,
|
ret = nct38xx_reg_read_byte(config->mfd,
|
||||||
NCT38XX_REG_GPIO_ALERT_RISE(config->gpio_port), &rise);
|
NCT38XX_REG_GPIO_ALERT_RISE(config->gpio_port), &rise);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev,
|
ret = nct38xx_reg_read_byte(config->mfd,
|
||||||
NCT38XX_REG_GPIO_ALERT_FALL(config->gpio_port), &fall);
|
NCT38XX_REG_GPIO_ALERT_FALL(config->gpio_port), &fall);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -390,13 +389,13 @@ static int gpio_nct38xx_pin_interrupt_configure(const struct device *dev, gpio_p
|
||||||
new_fall = fall & ~mask;
|
new_fall = fall & ~mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = nct38xx_reg_update(config->nct38xx_dev,
|
ret = nct38xx_reg_update(config->mfd,
|
||||||
NCT38XX_REG_GPIO_ALERT_RISE(config->gpio_port), rise, new_rise);
|
NCT38XX_REG_GPIO_ALERT_RISE(config->gpio_port), rise, new_rise);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = nct38xx_reg_update(config->nct38xx_dev,
|
ret = nct38xx_reg_update(config->mfd,
|
||||||
NCT38XX_REG_GPIO_ALERT_FALL(config->gpio_port), fall, new_fall);
|
NCT38XX_REG_GPIO_ALERT_FALL(config->gpio_port), fall, new_fall);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -404,7 +403,7 @@ static int gpio_nct38xx_pin_interrupt_configure(const struct device *dev, gpio_p
|
||||||
|
|
||||||
if (mode == GPIO_INT_MODE_LEVEL) {
|
if (mode == GPIO_INT_MODE_LEVEL) {
|
||||||
/* set active high/low */
|
/* set active high/low */
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev,
|
ret = nct38xx_reg_read_byte(config->mfd,
|
||||||
NCT38XX_REG_GPIO_ALERT_LEVEL(config->gpio_port), ®);
|
NCT38XX_REG_GPIO_ALERT_LEVEL(config->gpio_port), ®);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -419,7 +418,7 @@ static int gpio_nct38xx_pin_interrupt_configure(const struct device *dev, gpio_p
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
ret = nct38xx_reg_update(config->nct38xx_dev,
|
ret = nct38xx_reg_update(config->mfd,
|
||||||
NCT38XX_REG_GPIO_ALERT_LEVEL(config->gpio_port), reg,
|
NCT38XX_REG_GPIO_ALERT_LEVEL(config->gpio_port), reg,
|
||||||
new_reg);
|
new_reg);
|
||||||
|
|
||||||
|
@ -429,24 +428,24 @@ static int gpio_nct38xx_pin_interrupt_configure(const struct device *dev, gpio_p
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear pending bit */
|
/* Clear pending bit */
|
||||||
ret = nct38xx_reg_write_byte(config->nct38xx_dev,
|
ret = nct38xx_reg_write_byte(config->mfd,
|
||||||
NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port), mask);
|
NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port), mask);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable it after configuration is completed */
|
/* Enable it after configuration is completed */
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev,
|
ret = nct38xx_reg_read_byte(config->mfd,
|
||||||
NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), ®);
|
NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), ®);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
new_reg = reg | mask;
|
new_reg = reg | mask;
|
||||||
ret = nct38xx_reg_update(config->nct38xx_dev,
|
ret = nct38xx_reg_update(config->mfd,
|
||||||
NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), reg, new_reg);
|
NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), reg, new_reg);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
k_sem_give(&data->lock);
|
k_sem_give(data->lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -468,12 +467,12 @@ static int gpio_nct38xx_port_get_direction(const struct device *dev, gpio_port_p
|
||||||
uint8_t dir_reg;
|
uint8_t dir_reg;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
k_sem_take(&data->lock, K_FOREVER);
|
k_sem_take(data->lock, K_FOREVER);
|
||||||
|
|
||||||
if (config->gpio_port == 0) {
|
if (config->gpio_port == 0) {
|
||||||
uint8_t enabled_gpios;
|
uint8_t enabled_gpios;
|
||||||
/* Remove the disabled GPIOs from the mask */
|
/* Remove the disabled GPIOs from the mask */
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev, NCT38XX_REG_MUX_CONTROL,
|
ret = nct38xx_reg_read_byte(config->mfd, NCT38XX_REG_MUX_CONTROL,
|
||||||
&enabled_gpios);
|
&enabled_gpios);
|
||||||
mask &= (enabled_gpios & config->common.port_pin_mask);
|
mask &= (enabled_gpios & config->common.port_pin_mask);
|
||||||
|
|
||||||
|
@ -483,7 +482,7 @@ static int gpio_nct38xx_port_get_direction(const struct device *dev, gpio_port_p
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read direction register, 0 - input, 1 - output */
|
/* Read direction register, 0 - input, 1 - output */
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev, NCT38XX_REG_GPIO_DIR(config->gpio_port),
|
ret = nct38xx_reg_read_byte(config->mfd, NCT38XX_REG_GPIO_DIR(config->gpio_port),
|
||||||
&dir_reg);
|
&dir_reg);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -498,7 +497,7 @@ static int gpio_nct38xx_port_get_direction(const struct device *dev, gpio_port_p
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
k_sem_give(&data->lock);
|
k_sem_give(data->lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_GPIO_GET_DIRECTION */
|
#endif /* CONFIG_GPIO_GET_DIRECTION */
|
||||||
|
@ -511,32 +510,32 @@ int gpio_nct38xx_dispatch_port_isr(const struct device *dev)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
k_sem_take(&data->lock, K_FOREVER);
|
k_sem_take(data->lock, K_FOREVER);
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev,
|
ret = nct38xx_reg_read_byte(config->mfd,
|
||||||
NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port),
|
NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port),
|
||||||
&alert_pins);
|
&alert_pins);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
k_sem_give(&data->lock);
|
k_sem_give(data->lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = nct38xx_reg_read_byte(config->nct38xx_dev,
|
ret = nct38xx_reg_read_byte(config->mfd,
|
||||||
NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), &mask);
|
NCT38XX_REG_GPIO_ALERT_MASK(config->gpio_port), &mask);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
k_sem_give(&data->lock);
|
k_sem_give(data->lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
alert_pins &= mask;
|
alert_pins &= mask;
|
||||||
if (alert_pins) {
|
if (alert_pins) {
|
||||||
ret = nct38xx_reg_write_byte(config->nct38xx_dev,
|
ret = nct38xx_reg_write_byte(config->mfd,
|
||||||
NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port),
|
NCT38XX_REG_GPIO_ALERT_STAT(config->gpio_port),
|
||||||
alert_pins);
|
alert_pins);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
k_sem_give(&data->lock);
|
k_sem_give(data->lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
k_sem_give(&data->lock);
|
k_sem_give(data->lock);
|
||||||
|
|
||||||
gpio_fire_callbacks(&data->cb_list_gpio, dev, alert_pins);
|
gpio_fire_callbacks(&data->cb_list_gpio, dev, alert_pins);
|
||||||
|
|
||||||
|
@ -572,12 +571,12 @@ static int gpio_nct38xx_port_init(const struct device *dev)
|
||||||
const struct gpio_nct38xx_port_config *const config = dev->config;
|
const struct gpio_nct38xx_port_config *const config = dev->config;
|
||||||
struct gpio_nct38xx_port_data *const data = dev->data;
|
struct gpio_nct38xx_port_data *const data = dev->data;
|
||||||
|
|
||||||
if (!device_is_ready(config->nct38xx_dev)) {
|
if (!device_is_ready(config->mfd)) {
|
||||||
LOG_ERR("%s is not ready", config->nct38xx_dev->name);
|
LOG_ERR("%s is not ready", config->mfd->name);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
k_sem_init(&data->lock, 1, 1);
|
data->lock = mfd_nct38xx_get_lock_reference(config->mfd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -589,7 +588,7 @@ BUILD_ASSERT(CONFIG_GPIO_NCT38XX_PORT_INIT_PRIORITY > CONFIG_GPIO_NCT38XX_INIT_P
|
||||||
static const struct gpio_nct38xx_port_config gpio_nct38xx_port_cfg_##inst = { \
|
static const struct gpio_nct38xx_port_config gpio_nct38xx_port_cfg_##inst = { \
|
||||||
.common = {.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(inst) & \
|
.common = {.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(inst) & \
|
||||||
DT_INST_PROP(inst, pin_mask)}, \
|
DT_INST_PROP(inst, pin_mask)}, \
|
||||||
.nct38xx_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
|
.mfd = DEVICE_DT_GET(DT_INST_GPARENT(inst)), \
|
||||||
.gpio_port = DT_INST_REG_ADDR(inst), \
|
.gpio_port = DT_INST_REG_ADDR(inst), \
|
||||||
.pinmux_mask = COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, pinmux_mask), \
|
.pinmux_mask = COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, pinmux_mask), \
|
||||||
(DT_INST_PROP(inst, pinmux_mask)), (0)), \
|
(DT_INST_PROP(inst, pinmux_mask)), (0)), \
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
zephyr_library()
|
zephyr_library()
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
|
@ -19,6 +19,7 @@ config MFD_INIT_PRIORITY
|
||||||
Multi-function devices initialization priority.
|
Multi-function devices initialization priority.
|
||||||
|
|
||||||
source "drivers/mfd/Kconfig.axp192"
|
source "drivers/mfd/Kconfig.axp192"
|
||||||
|
source "drivers/mfd/Kconfig.nct38xx"
|
||||||
source "drivers/mfd/Kconfig.npm1300"
|
source "drivers/mfd/Kconfig.npm1300"
|
||||||
source "drivers/mfd/Kconfig.npm6001"
|
source "drivers/mfd/Kconfig.npm6001"
|
||||||
|
|
||||||
|
|
10
drivers/mfd/Kconfig.nct38xx
Normal file
10
drivers/mfd/Kconfig.nct38xx
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# Copyright (c) 2023 Google, LLC
|
||||||
|
# SPDX -License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
config MFD_NCT38XX
|
||||||
|
bool "Nuvton NCT38xx multi-function device driver"
|
||||||
|
default y
|
||||||
|
depends on DT_HAS_NUVOTON_NCT38XX_ENABLED
|
||||||
|
select I2C
|
||||||
|
help
|
||||||
|
Enable the Nuvoton NCT38xx TCPC multi-function device driver.
|
88
drivers/mfd/mfd_nct38xx.c
Normal file
88
drivers/mfd/mfd_nct38xx.c
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Google, LLC
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT nuvoton_nct38xx
|
||||||
|
|
||||||
|
#include <zephyr/drivers/i2c.h>
|
||||||
|
|
||||||
|
struct mfd_nct38xx_config {
|
||||||
|
const struct i2c_dt_spec i2c_dev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mfd_nct38xx_data {
|
||||||
|
/* lock NC38xx register access */
|
||||||
|
struct k_sem lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int mfd_nct38xx_init(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct mfd_nct38xx_config *config = dev->config;
|
||||||
|
struct mfd_nct38xx_data *data = dev->data;
|
||||||
|
|
||||||
|
if (!device_is_ready(config->i2c_dev.bus)) {
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_sem_init(&data->lock, 1, 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct k_sem *mfd_nct38xx_get_lock_reference(const struct device *dev)
|
||||||
|
{
|
||||||
|
struct mfd_nct38xx_data *data = dev->data;
|
||||||
|
|
||||||
|
return &data->lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nct38xx_reg_read_byte(const struct device *dev, uint8_t reg_addr, uint8_t *val)
|
||||||
|
{
|
||||||
|
const struct mfd_nct38xx_config *const 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MFD_NCT38XX_DEFINE(inst) \
|
||||||
|
static struct mfd_nct38xx_data nct38xx_data_##inst; \
|
||||||
|
static const struct mfd_nct38xx_config nct38xx_cfg_##inst = { \
|
||||||
|
.i2c_dev = I2C_DT_SPEC_INST_GET(inst), \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
DEVICE_DT_INST_DEFINE(inst, mfd_nct38xx_init, NULL, &nct38xx_data_##inst, \
|
||||||
|
&nct38xx_cfg_##inst, POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, NULL);
|
||||||
|
|
||||||
|
DT_INST_FOREACH_STATUS_OKAY(MFD_NCT38XX_DEFINE)
|
|
@ -2,7 +2,7 @@
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
description: |
|
description: |
|
||||||
Nuvoton NCT38XX series I2C-based GPIO expander alert handler
|
Nuvoton NCT38XX series I2C-based GPIO expander alert handler.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
nct3807_alert_1 {
|
nct3807_alert_1 {
|
||||||
|
@ -25,4 +25,4 @@ properties:
|
||||||
type: phandles
|
type: phandles
|
||||||
required: true
|
required: true
|
||||||
description: |
|
description: |
|
||||||
NCT38XX devices which alert are handled by this alert handler.
|
List of NCT38XX multi-function devices managed by this alert handler.
|
||||||
|
|
|
@ -4,13 +4,18 @@
|
||||||
description: |
|
description: |
|
||||||
Nuvoton NCT38XX series I2C-based GPIO expander
|
Nuvoton NCT38XX series I2C-based GPIO expander
|
||||||
|
|
||||||
|
This must be a child of the NCT38xx multi-function device.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
&i2c0_0 {
|
&i2c0_0 {
|
||||||
nct3807@70 {
|
nct3807@70 {
|
||||||
|
compatible = "nuvoton,nct38xx";
|
||||||
|
reg = <0x70>;
|
||||||
|
|
||||||
|
nct3807-gpio {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
compatible = "nuvoton,nct38xx-gpio";
|
compatible = "nuvoton,nct38xx-gpio";
|
||||||
reg = <0x70>;
|
|
||||||
|
|
||||||
gpio@0 {
|
gpio@0 {
|
||||||
compatible = "nuvoton,nct38xx-gpio-port";
|
compatible = "nuvoton,nct38xx-gpio-port";
|
||||||
|
@ -31,12 +36,16 @@ description: |
|
||||||
pin_mask = <0xff>;
|
pin_mask = <0xff>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
nct3808_0_P1@71 {
|
nct3808_0_P1@71 {
|
||||||
|
compatible = "nuvoton,nct38xx";
|
||||||
|
reg = <0x71>;
|
||||||
|
|
||||||
|
nct3808-0-p1-gpio {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
compatible = "nuvoton,nct38xx-gpio";
|
compatible = "nuvoton,nct38xx-gpio";
|
||||||
reg = <0x71>;
|
|
||||||
|
|
||||||
gpio@0 {
|
gpio@0 {
|
||||||
compatible = "nuvoton,nct38xx-gpio-port";
|
compatible = "nuvoton,nct38xx-gpio-port";
|
||||||
|
@ -48,12 +57,16 @@ description: |
|
||||||
pinmux_mask = <0xff>;
|
pinmux_mask = <0xff>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
nct3808_0_P2@75 {
|
nct3808_0_P2@75 {
|
||||||
|
compatible = "nuvoton,nct38xx";
|
||||||
|
reg = <0x75>;
|
||||||
|
|
||||||
|
nct3808-0-P2-gpio {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
compatible = "nuvoton,nct38xx-gpio";
|
compatible = "nuvoton,nct38xx-gpio";
|
||||||
reg = <0x75>;
|
|
||||||
|
|
||||||
gpio@0 {
|
gpio@0 {
|
||||||
compatible = "nuvoton,nct38xx-gpio-port";
|
compatible = "nuvoton,nct38xx-gpio-port";
|
||||||
|
@ -66,7 +79,8 @@ description: |
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
compatible: "nuvoton,nct38xx-gpio"
|
compatible: "nuvoton,nct38xx-gpio"
|
||||||
|
|
||||||
include: [i2c-device.yaml]
|
include: [base.yaml]
|
||||||
|
|
14
dts/bindings/mfd/nuvoton,nct38xx.yaml
Normal file
14
dts/bindings/mfd/nuvoton,nct38xx.yaml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# Copyright (c) 2023, Google, LLC
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
description: |
|
||||||
|
Nuvoton NCT38xx multi-function device
|
||||||
|
|
||||||
|
The NCT38xx provides a TCPC and an I/O Expander capabilities.
|
||||||
|
|
||||||
|
The TCPC and I/O expander drivers are added to the devicetree
|
||||||
|
as children of the nuvoton,nct38xx device.
|
||||||
|
|
||||||
|
compatible: "nuvoton,nct38xx"
|
||||||
|
|
||||||
|
include: i2c-device.yaml
|
91
include/zephyr/drivers/mfd/nct38xx.h
Normal file
91
include/zephyr/drivers/mfd/nct38xx.h
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Google, LLC
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_INCLUDE_DRIVERS_MFD_NCT38XX_H_
|
||||||
|
#define ZEPHYR_INCLUDE_DRIVERS_MFD_NCT38XX_H_
|
||||||
|
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the semaphore reference for a NCT38xx instance. Callers
|
||||||
|
* should pass the return value to k_sem_take/k_sem_give
|
||||||
|
*
|
||||||
|
* @param[in] dev Pointer to device struct of the driver instance
|
||||||
|
*
|
||||||
|
* @return Address of the semaphore
|
||||||
|
*/
|
||||||
|
struct k_sem *mfd_nct38xx_get_lock_reference(const struct device *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read a NCT38XX register
|
||||||
|
*
|
||||||
|
* @param dev NCT38XX multi-function device
|
||||||
|
* @param reg_addr Register address
|
||||||
|
* @param val A pointer to a buffer for the data to return
|
||||||
|
*
|
||||||
|
* @return 0 if successful, otherwise failed.
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_DRIVERS_MFD_NCT38XX_H_ */
|
|
@ -103,11 +103,13 @@
|
||||||
gpio-controller;
|
gpio-controller;
|
||||||
};
|
};
|
||||||
|
|
||||||
test_i2c_nct3807: nct3807@72 {
|
mfd-nct38xx@72 {
|
||||||
|
compatible = "nuvoton,nct38xx";
|
||||||
|
reg = <0x72>;
|
||||||
|
test_i2c_nct3807: nct3807 {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
compatible = "nuvoton,nct38xx-gpio";
|
compatible = "nuvoton,nct38xx-gpio";
|
||||||
reg = <0x72>;
|
|
||||||
|
|
||||||
gpio@0 {
|
gpio@0 {
|
||||||
compatible = "nuvoton,nct38xx-gpio-port";
|
compatible = "nuvoton,nct38xx-gpio-port";
|
||||||
|
@ -128,29 +130,15 @@
|
||||||
pin_mask = <0xff>;
|
pin_mask = <0xff>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
test_i2c_nct3808_p1: nct3808_0_P1@71 {
|
test_i2c_nct3808_p1: mfd-nct38xx@71 {
|
||||||
#address-cells = <1>;
|
compatible = "nuvoton,nct38xx";
|
||||||
#size-cells = <0>;
|
|
||||||
compatible = "nuvoton,nct38xx-gpio";
|
|
||||||
reg = <0x71>;
|
reg = <0x71>;
|
||||||
|
nct3808_0_P1 {
|
||||||
gpio@0 {
|
|
||||||
compatible = "nuvoton,nct38xx-gpio-port";
|
|
||||||
reg = <0x0>;
|
|
||||||
gpio-controller;
|
|
||||||
#gpio-cells = <2>;
|
|
||||||
ngpios = <8>;
|
|
||||||
pin_mask = <0xdc>;
|
|
||||||
pinmux_mask = <0xff>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
test_i2c_nct3808_p2: nct3808_0_P2@75 {
|
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
compatible = "nuvoton,nct38xx-gpio";
|
compatible = "nuvoton,nct38xx-gpio";
|
||||||
reg = <0x75>;
|
|
||||||
|
|
||||||
gpio@0 {
|
gpio@0 {
|
||||||
compatible = "nuvoton,nct38xx-gpio-port";
|
compatible = "nuvoton,nct38xx-gpio-port";
|
||||||
|
@ -162,6 +150,27 @@
|
||||||
pinmux_mask = <0xff>;
|
pinmux_mask = <0xff>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
test_i2c_nct3808_p2: mfd-nct38xx@75 {
|
||||||
|
compatible = "nuvoton,nct38xx";
|
||||||
|
reg = <0x75>;
|
||||||
|
nct3808_0_P2 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
compatible = "nuvoton,nct38xx-gpio";
|
||||||
|
|
||||||
|
gpio@0 {
|
||||||
|
compatible = "nuvoton,nct38xx-gpio-port";
|
||||||
|
reg = <0x0>;
|
||||||
|
gpio-controller;
|
||||||
|
#gpio-cells = <2>;
|
||||||
|
ngpios = <8>;
|
||||||
|
pin_mask = <0xdc>;
|
||||||
|
pinmux_mask = <0xff>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
test_i2c_tca6424a: tca6424a@23 {
|
test_i2c_tca6424a: tca6424a@23 {
|
||||||
compatible = "ti,tca6424a";
|
compatible = "ti,tca6424a";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue