drivers: gpio: AXP192 GPIO driver
AXP192 is a small power management IC, that also features 5 GPIOS. Besides GPIO driver this commit also includes needed modifications in axp192 regulator and mfd driver as LDOIO0 functioanlity is multiplexed with GPIO0 pin. Signed-off-by: Martin Kiepfer <mrmarteng@teleschirm.org>
This commit is contained in:
parent
d4169c93fd
commit
74db02bad1
11 changed files with 1055 additions and 6 deletions
|
@ -4,6 +4,7 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/gpio.h)
|
|||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_AXP192 gpio_axp192.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_TELINK_B91 gpio_b91.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_INFINEON_CAT1 gpio_ifx_cat1.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_CC13XX_CC26XX gpio_cc13xx_cc26xx.c)
|
||||
|
|
|
@ -69,6 +69,8 @@ config GPIO_ENABLE_DISABLE_INTERRUPT
|
|||
pending register, etc. The driver must implement it to work.
|
||||
|
||||
|
||||
source "drivers/gpio/Kconfig.axp192"
|
||||
|
||||
source "drivers/gpio/Kconfig.b91"
|
||||
|
||||
source "drivers/gpio/Kconfig.dw"
|
||||
|
|
21
drivers/gpio/Kconfig.axp192
Normal file
21
drivers/gpio/Kconfig.axp192
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Copyright (c) 2023 Martin Kiepfer
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config GPIO_AXP192
|
||||
bool "AXP192 GPIO driver"
|
||||
default y
|
||||
depends on DT_HAS_X_POWERS_AXP192_GPIO_ENABLED
|
||||
depends on DT_HAS_X_POWERS_AXP192_ENABLED
|
||||
select I2C
|
||||
select MFD
|
||||
help
|
||||
Enable the AXP192 GPIO driver.
|
||||
|
||||
config GPIO_AXP192_INIT_PRIORITY
|
||||
int "AXP192 GPIO driver initialization priority"
|
||||
depends on GPIO_AXP192
|
||||
default 80
|
||||
help
|
||||
Initialization priority for the AXP192 GPIO driver. It must be
|
||||
greater than the I2C controller init priority and the mfd driver
|
||||
init priority.
|
321
drivers/gpio/gpio_axp192.c
Normal file
321
drivers/gpio/gpio_axp192.c
Normal file
|
@ -0,0 +1,321 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Martin Kiepfer
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT x_powers_axp192_gpio
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/drivers/gpio/gpio_utils.h>
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/sys/util_macro.h>
|
||||
#include <zephyr/toolchain.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/drivers/mfd/axp192.h>
|
||||
|
||||
LOG_MODULE_REGISTER(gpio_axp192, CONFIG_GPIO_LOG_LEVEL);
|
||||
|
||||
struct gpio_axp192_config {
|
||||
struct gpio_driver_config common;
|
||||
struct i2c_dt_spec i2c;
|
||||
const struct device *mfd;
|
||||
uint32_t ngpios;
|
||||
};
|
||||
|
||||
struct gpio_axp192_data {
|
||||
struct gpio_driver_data common;
|
||||
struct k_mutex mutex;
|
||||
sys_slist_t cb_list_gpio;
|
||||
};
|
||||
|
||||
static int gpio_axp192_port_get_raw(const struct device *dev, uint32_t *value)
|
||||
{
|
||||
int ret;
|
||||
uint8_t port_val;
|
||||
const struct gpio_axp192_config *config = dev->config;
|
||||
|
||||
if (k_is_in_isr()) {
|
||||
return -EWOULDBLOCK;
|
||||
}
|
||||
|
||||
ret = mfd_axp192_gpio_read_port(config->mfd, &port_val);
|
||||
if (ret == 0) {
|
||||
*value = port_val;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gpio_axp192_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask,
|
||||
gpio_port_value_t value)
|
||||
{
|
||||
int ret;
|
||||
const struct gpio_axp192_config *config = dev->config;
|
||||
|
||||
if (k_is_in_isr()) {
|
||||
return -EWOULDBLOCK;
|
||||
}
|
||||
|
||||
ret = mfd_axp192_gpio_write_port(config->mfd, value, mask);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gpio_axp192_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins)
|
||||
{
|
||||
return gpio_axp192_port_set_masked_raw(dev, pins, pins);
|
||||
}
|
||||
|
||||
static int gpio_axp192_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins)
|
||||
{
|
||||
return gpio_axp192_port_set_masked_raw(dev, pins, 0);
|
||||
}
|
||||
|
||||
static int gpio_axp192_configure(const struct device *dev, gpio_pin_t pin,
|
||||
gpio_flags_t flags)
|
||||
{
|
||||
const struct gpio_axp192_config *config = dev->config;
|
||||
int ret;
|
||||
enum axp192_gpio_func func;
|
||||
|
||||
if (pin >= config->ngpios) {
|
||||
LOG_ERR("Invalid gpio pin (%d)", pin);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (k_is_in_isr()) {
|
||||
return -EWOULDBLOCK;
|
||||
}
|
||||
|
||||
/* Configure pin */
|
||||
LOG_DBG("Pin: %d / flags=0x%x", pin, flags);
|
||||
if ((flags & GPIO_OUTPUT) != 0) {
|
||||
|
||||
/* Initialize output function */
|
||||
func = AXP192_GPIO_FUNC_OUTPUT_LOW;
|
||||
if ((flags & GPIO_OPEN_DRAIN) != 0) {
|
||||
func = AXP192_GPIO_FUNC_OUTPUT_OD;
|
||||
}
|
||||
ret = mfd_axp192_gpio_func_ctrl(config->mfd, dev, pin, func);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set init value */
|
||||
if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) {
|
||||
ret = mfd_axp192_gpio_write_port(config->mfd, BIT(pin), 0);
|
||||
} else if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) {
|
||||
ret = mfd_axp192_gpio_write_port(config->mfd, BIT(pin), BIT(pin));
|
||||
}
|
||||
} else if ((flags & GPIO_INPUT) != 0) {
|
||||
|
||||
/* Initialize input function */
|
||||
func = AXP192_GPIO_FUNC_INPUT;
|
||||
|
||||
ret = mfd_axp192_gpio_func_ctrl(config->mfd, dev, pin, func);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Configure pull-down */
|
||||
if ((flags & GPIO_PULL_UP) != 0) {
|
||||
/* not supported */
|
||||
LOG_ERR("Pull-Up not supported");
|
||||
ret = -ENOTSUP;
|
||||
} else if ((flags & GPIO_PULL_DOWN) != 0) {
|
||||
/* out = 0 means pull-down*/
|
||||
ret = mfd_axp192_gpio_pd_ctrl(config->mfd, pin, true);
|
||||
} else {
|
||||
ret = mfd_axp192_gpio_pd_ctrl(config->mfd, pin, false);
|
||||
}
|
||||
} else {
|
||||
/* Neither input nor output mode is selected */
|
||||
LOG_INF("No valid gpio mode selected");
|
||||
ret = -ENOTSUP;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gpio_axp192_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins)
|
||||
{
|
||||
struct gpio_axp192_data *data = dev->data;
|
||||
int ret;
|
||||
uint32_t value;
|
||||
|
||||
k_mutex_lock(&data->mutex, K_FOREVER);
|
||||
|
||||
ret = gpio_axp192_port_get_raw(dev, &value);
|
||||
if (ret == 0) {
|
||||
ret = gpio_axp192_port_set_masked_raw(dev, pins, ~value);
|
||||
}
|
||||
|
||||
k_mutex_unlock(&data->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gpio_axp192_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin,
|
||||
enum gpio_int_mode mode, enum gpio_int_trig trig)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
ARG_UNUSED(pin);
|
||||
ARG_UNUSED(mode);
|
||||
ARG_UNUSED(trig);
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GPIO_GET_CONFIG
|
||||
static int gpio_axp192_get_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t *out_flags)
|
||||
{
|
||||
const struct gpio_axp192_config *config = dev->config;
|
||||
enum axp192_gpio_func func;
|
||||
bool pd_enabled;
|
||||
int ret;
|
||||
|
||||
if (k_is_in_isr()) {
|
||||
return -EWOULDBLOCK;
|
||||
}
|
||||
|
||||
ret = mfd_axp192_gpio_func_get(config->mfd, pin, &func);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set OUTPUT/INPUT flags */
|
||||
*out_flags = 0;
|
||||
switch (func) {
|
||||
case AXP192_GPIO_FUNC_INPUT:
|
||||
*out_flags |= GPIO_INPUT;
|
||||
break;
|
||||
case AXP192_GPIO_FUNC_OUTPUT_OD:
|
||||
*out_flags |= GPIO_OUTPUT | GPIO_OPEN_DRAIN;
|
||||
break;
|
||||
case AXP192_GPIO_FUNC_OUTPUT_LOW:
|
||||
*out_flags |= GPIO_OUTPUT;
|
||||
break;
|
||||
|
||||
case AXP192_GPIO_FUNC_LDO:
|
||||
__fallthrough;
|
||||
case AXP192_GPIO_FUNC_ADC:
|
||||
__fallthrough;
|
||||
case AXP192_GPIO_FUNC_FLOAT:
|
||||
__fallthrough;
|
||||
default:
|
||||
LOG_DBG("Pin %d not configured as GPIO", pin);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Query pull-down config status */
|
||||
ret = mfd_axp192_gpio_pd_get(config->mfd, pin, &pd_enabled);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pd_enabled) {
|
||||
*out_flags |= GPIO_PULL_DOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_GPIO_GET_CONFIG */
|
||||
|
||||
#ifdef CONFIG_GPIO_GET_DIRECTION
|
||||
static int gpio_axp192_port_get_direction(const struct device *dev, gpio_port_pins_t map,
|
||||
gpio_port_pins_t *inputs, gpio_port_pins_t *outputs)
|
||||
{
|
||||
const struct gpio_axp192_config *config = dev->config;
|
||||
gpio_flags_t flags;
|
||||
int ret;
|
||||
|
||||
/* reset output variables */
|
||||
*inputs = 0;
|
||||
*outputs = 0;
|
||||
|
||||
/* loop through all */
|
||||
for (gpio_pin_t gpio = 0; gpio < config->ngpios; gpio++) {
|
||||
|
||||
if ((map & (1u << gpio)) != 0) {
|
||||
|
||||
/* use internal get_config method to get gpio flags */
|
||||
ret = gpio_axp192_get_config(dev, gpio, &flags);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set output and input flags */
|
||||
if ((flags & GPIO_OUTPUT) != 0) {
|
||||
*outputs |= (1u << gpio);
|
||||
} else if (0 != (flags & GPIO_INPUT)) {
|
||||
*inputs |= (1u << gpio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_GPIO_GET_DIRECTION */
|
||||
|
||||
static int gpio_axp192_manage_callback(const struct device *dev, struct gpio_callback *callback,
|
||||
bool set)
|
||||
{
|
||||
struct gpio_axp192_data *const data = dev->data;
|
||||
|
||||
return gpio_manage_callback(&data->cb_list_gpio, callback, set);
|
||||
}
|
||||
|
||||
static const struct gpio_driver_api gpio_axp192_api = {
|
||||
.pin_configure = gpio_axp192_configure,
|
||||
.port_get_raw = gpio_axp192_port_get_raw,
|
||||
.port_set_masked_raw = gpio_axp192_port_set_masked_raw,
|
||||
.port_set_bits_raw = gpio_axp192_port_set_bits_raw,
|
||||
.port_clear_bits_raw = gpio_axp192_port_clear_bits_raw,
|
||||
.port_toggle_bits = gpio_axp192_port_toggle_bits,
|
||||
.pin_interrupt_configure = gpio_axp192_pin_interrupt_configure,
|
||||
.manage_callback = gpio_axp192_manage_callback,
|
||||
#ifdef CONFIG_GPIO_GET_DIRECTION
|
||||
.port_get_direction = gpio_axp192_port_get_direction,
|
||||
#endif /* CONFIG_GPIO_GET_DIRECTION */
|
||||
#ifdef CONFIG_GPIO_GET_CONFIG
|
||||
.pin_get_config = gpio_axp192_get_config,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int gpio_axp192_init(const struct device *dev)
|
||||
{
|
||||
const struct gpio_axp192_config *config = dev->config;
|
||||
struct gpio_axp192_data *data = dev->data;
|
||||
|
||||
LOG_DBG("Initializing");
|
||||
|
||||
if (!i2c_is_ready_dt(&config->i2c)) {
|
||||
LOG_ERR("device not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return k_mutex_init(&data->mutex);
|
||||
}
|
||||
|
||||
#define GPIO_AXP192_DEFINE(inst) \
|
||||
static const struct gpio_axp192_config gpio_axp192_config##inst = { \
|
||||
.common = \
|
||||
{ \
|
||||
.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(inst), \
|
||||
}, \
|
||||
.i2c = I2C_DT_SPEC_GET(DT_INST_PARENT(inst)), \
|
||||
.mfd = DEVICE_DT_GET(DT_INST_PARENT(inst)), \
|
||||
.ngpios = DT_INST_PROP(inst, ngpios), \
|
||||
}; \
|
||||
\
|
||||
static struct gpio_axp192_data gpio_axp192_data##inst; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(inst, &gpio_axp192_init, NULL, &gpio_axp192_data##inst, \
|
||||
&gpio_axp192_config##inst, POST_KERNEL, \
|
||||
CONFIG_GPIO_AXP192_INIT_PRIORITY, &gpio_axp192_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(GPIO_AXP192_DEFINE)
|
|
@ -6,7 +6,9 @@
|
|||
#define DT_DRV_COMPAT x_powers_axp192
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <zephyr/drivers/mfd/axp192.h>
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
@ -19,10 +21,111 @@ LOG_MODULE_REGISTER(mfd_axp192, CONFIG_MFD_LOG_LEVEL);
|
|||
/* Registers definitions */
|
||||
#define AXP192_REG_CHIP_ID 0x03U
|
||||
|
||||
/* AXP192 GPIO register addresses */
|
||||
#define AXP192_GPIO0_REG_FUNC 0x90U
|
||||
#define AXP192_GPIO1_REG_FUNC 0x92U
|
||||
#define AXP192_GPIO2_REG_FUNC 0x93U
|
||||
#define AXP192_GPIO34_REG_FUNC 0x95U
|
||||
#define AXP192_GPIO012_REG_PINVAL 0x94U
|
||||
#define AXP192_GPIO34_REG_PINVAL 0x96U
|
||||
#define AXP192_GPIO012_REG_PULLDOWN 0x97U
|
||||
|
||||
/* GPIO function control parameters */
|
||||
#define AXP192_GPIO012_FUNC_VAL_OUTPUT_OD 0x00U
|
||||
#define AXP192_GPIO012_FUNC_VAL_INPUT 0x01U
|
||||
#define AXP192_GPIO012_FUNC_VAL_LDO 0x02U /* only applicable for GPIO0 */
|
||||
#define AXP192_GPIO012_FUNC_VAL_ADC 0x04U
|
||||
#define AXP192_GPIO012_FUNC_VAL_OUTPUT_LOW 0x05U
|
||||
#define AXP192_GPIO012_FUNC_VAL_FLOAT 0x06U
|
||||
#define AXP192_GPIO012_FUNC_MASK \
|
||||
(AXP192_GPIO012_FUNC_VAL_OUTPUT_OD | AXP192_GPIO012_FUNC_VAL_INPUT | \
|
||||
AXP192_GPIO012_FUNC_VAL_LDO | AXP192_GPIO012_FUNC_VAL_ADC | \
|
||||
AXP192_GPIO012_FUNC_VAL_OUTPUT_LOW | AXP192_GPIO012_FUNC_VAL_FLOAT)
|
||||
|
||||
#define AXP192_GPIO34_FUNC_ENA 0x80U
|
||||
#define AXP192_GPIO3_FUNC_VAL_CHARGE_CTL 0x00U
|
||||
#define AXP192_GPIO3_FUNC_VAL_OUTPUT_OD 0x01U
|
||||
#define AXP192_GPIO3_FUNC_VAL_INPUT 0x02U
|
||||
#define AXP192_GPIO3_FUNC_MASK \
|
||||
(AXP192_GPIO34_FUNC_ENA | AXP192_GPIO3_FUNC_VAL_CHARGE_CTL | \
|
||||
AXP192_GPIO3_FUNC_VAL_OUTPUT_OD | AXP192_GPIO3_FUNC_VAL_INPUT)
|
||||
|
||||
#define AXP192_GPIO4_FUNC_VAL_CHARGE_CTL 0x00U
|
||||
#define AXP192_GPIO4_FUNC_VAL_OUTPUT_OD 0x04U
|
||||
#define AXP192_GPIO4_FUNC_VAL_INPUT 0x08U
|
||||
#define AXP192_GPIO4_FUNC_VAL_ADC 0x0CU
|
||||
#define AXP192_GPIO4_FUNC_MASK \
|
||||
(AXP192_GPIO34_FUNC_ENA | AXP192_GPIO4_FUNC_VAL_CHARGE_CTL | \
|
||||
AXP192_GPIO4_FUNC_VAL_OUTPUT_OD | AXP192_GPIO4_FUNC_VAL_INPUT)
|
||||
|
||||
/* Pull-Down enable parameters */
|
||||
#define AXP192_GPIO0_PULLDOWN_ENABLE 0x01U
|
||||
#define AXP192_GPIO1_PULLDOWN_ENABLE 0x02U
|
||||
#define AXP192_GPIO2_PULLDOWN_ENABLE 0x04U
|
||||
|
||||
/* GPIO Value parameters */
|
||||
#define AXP192_GPIO0_INPUT_VAL 0x10U
|
||||
#define AXP192_GPIO1_INPUT_VAL 0x20U
|
||||
#define AXP192_GPIO2_INPUT_VAL 0x40U
|
||||
#define AXP192_GPIO012_INTPUT_SHIFT 4U
|
||||
#define AXP192_GPIO012_INTPUT_MASK \
|
||||
(AXP192_GPIO0_INPUT_VAL | AXP192_GPIO1_INPUT_VAL | AXP192_GPIO2_INPUT_VAL)
|
||||
#define AXP192_GPIO3_INPUT_VAL 0x10U
|
||||
#define AXP192_GPIO4_INPUT_VAL 0x20U
|
||||
#define AXP192_GPIO34_INTPUT_SHIFT 4U
|
||||
#define AXP192_GPIO34_INTPUT_MASK (AXP192_GPIO3_INPUT_VAL | AXP192_GPIO4_INPUT_VAL)
|
||||
|
||||
#define AXP192_GPIO0_OUTPUT_VAL 0x01U
|
||||
#define AXP192_GPIO1_OUTPUT_VAL 0x02U
|
||||
#define AXP192_GPIO2_OUTPUT_VAL 0x04U
|
||||
#define AXP192_GPIO012_OUTPUT_MASK \
|
||||
(AXP192_GPIO0_OUTPUT_VAL | AXP192_GPIO1_OUTPUT_VAL | AXP192_GPIO2_OUTPUT_VAL)
|
||||
#define AXP192_GPIO3_OUTPUT_VAL 0x01U
|
||||
#define AXP192_GPIO4_OUTPUT_VAL 0x02U
|
||||
#define AXP192_GPIO34_OUTPUT_MASK (AXP192_GPIO3_OUTPUT_VAL | AXP192_GPIO4_OUTPUT_VAL)
|
||||
|
||||
struct mfd_axp192_config {
|
||||
struct i2c_dt_spec i2c;
|
||||
};
|
||||
|
||||
struct mfd_axp192_data {
|
||||
const struct device *gpio_mask_used[AXP192_GPIO_MAX_NUM];
|
||||
uint8_t gpio_mask_output;
|
||||
};
|
||||
|
||||
struct mfd_axp192_func_reg_desc {
|
||||
uint8_t reg;
|
||||
uint8_t mask;
|
||||
};
|
||||
|
||||
const struct mfd_axp192_func_reg_desc gpio_reg_desc[AXP192_GPIO_MAX_NUM] = {
|
||||
{
|
||||
/* GPIO0 */
|
||||
.reg = AXP192_GPIO0_REG_FUNC,
|
||||
.mask = AXP192_GPIO012_FUNC_MASK,
|
||||
},
|
||||
{
|
||||
/* GPIO1 */
|
||||
.reg = AXP192_GPIO1_REG_FUNC,
|
||||
.mask = AXP192_GPIO012_FUNC_MASK,
|
||||
},
|
||||
{
|
||||
/* GPIO2 */
|
||||
.reg = AXP192_GPIO2_REG_FUNC,
|
||||
.mask = AXP192_GPIO012_FUNC_MASK,
|
||||
},
|
||||
{
|
||||
/* GPIO3 */
|
||||
.reg = AXP192_GPIO34_REG_FUNC,
|
||||
.mask = AXP192_GPIO3_FUNC_MASK,
|
||||
},
|
||||
{
|
||||
/* GPIO4 */
|
||||
.reg = AXP192_GPIO34_REG_FUNC,
|
||||
.mask = AXP192_GPIO4_FUNC_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static int mfd_axp192_init(const struct device *dev)
|
||||
{
|
||||
const struct mfd_axp192_config *config = dev->config;
|
||||
|
@ -50,12 +153,405 @@ static int mfd_axp192_init(const struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int mfd_axp192_gpio_func_get(const struct device *dev, uint8_t gpio, enum axp192_gpio_func *func)
|
||||
{
|
||||
const struct mfd_axp192_config *config = dev->config;
|
||||
int ret;
|
||||
uint8_t reg_fnc;
|
||||
|
||||
if (gpio >= AXP192_GPIO_MAX_NUM) {
|
||||
LOG_ERR("Invalid gpio (%d)", gpio);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = i2c_reg_read_byte_dt(&(config->i2c), gpio_reg_desc[gpio].reg, ®_fnc);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (gpio) {
|
||||
case 0U:
|
||||
__fallthrough;
|
||||
case 1U:
|
||||
__fallthrough;
|
||||
case 2U:
|
||||
/* GPIO 0-2*/
|
||||
switch (reg_fnc) {
|
||||
case AXP192_GPIO012_FUNC_VAL_INPUT:
|
||||
*func = AXP192_GPIO_FUNC_INPUT;
|
||||
break;
|
||||
case AXP192_GPIO012_FUNC_VAL_OUTPUT_OD:
|
||||
*func = AXP192_GPIO_FUNC_OUTPUT_OD;
|
||||
break;
|
||||
case AXP192_GPIO012_FUNC_VAL_OUTPUT_LOW:
|
||||
*func = AXP192_GPIO_FUNC_OUTPUT_LOW;
|
||||
break;
|
||||
case AXP192_GPIO012_FUNC_VAL_LDO:
|
||||
if (gpio == 0) {
|
||||
/* LDO is only applicable on GPIO0 */
|
||||
*func = AXP192_GPIO_FUNC_LDO;
|
||||
} else {
|
||||
ret = -ENOTSUP;
|
||||
}
|
||||
break;
|
||||
case AXP192_GPIO012_FUNC_VAL_ADC:
|
||||
*func = AXP192_GPIO_FUNC_ADC;
|
||||
break;
|
||||
case AXP192_GPIO012_FUNC_VAL_FLOAT:
|
||||
*func = AXP192_GPIO_FUNC_FLOAT;
|
||||
break;
|
||||
default:
|
||||
ret = -ENOTSUP;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3U:
|
||||
/* GPIO3 */
|
||||
switch (reg_fnc) {
|
||||
case (AXP192_GPIO3_FUNC_VAL_INPUT | AXP192_GPIO34_FUNC_ENA):
|
||||
*func = AXP192_GPIO_FUNC_INPUT;
|
||||
break;
|
||||
case (AXP192_GPIO3_FUNC_VAL_OUTPUT_OD | AXP192_GPIO34_FUNC_ENA):
|
||||
*func = AXP192_GPIO_FUNC_OUTPUT_OD;
|
||||
break;
|
||||
case AXP192_GPIO3_FUNC_VAL_CHARGE_CTL:
|
||||
*func = AXP192_GPIO_FUNC_CHARGE_CTL;
|
||||
break;
|
||||
default:
|
||||
ret = -ENOTSUP;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4U:
|
||||
/* GPIO4 */
|
||||
switch (reg_fnc) {
|
||||
case (AXP192_GPIO4_FUNC_VAL_INPUT | AXP192_GPIO34_FUNC_ENA):
|
||||
*func = AXP192_GPIO_FUNC_INPUT;
|
||||
break;
|
||||
case (AXP192_GPIO4_FUNC_VAL_OUTPUT_OD | AXP192_GPIO34_FUNC_ENA):
|
||||
*func = AXP192_GPIO_FUNC_OUTPUT_OD;
|
||||
break;
|
||||
case (AXP192_GPIO4_FUNC_VAL_ADC | AXP192_GPIO34_FUNC_ENA):
|
||||
*func = AXP192_GPIO_FUNC_ADC;
|
||||
break;
|
||||
case AXP192_GPIO4_FUNC_VAL_CHARGE_CTL:
|
||||
*func = AXP192_GPIO_FUNC_CHARGE_CTL;
|
||||
break;
|
||||
default:
|
||||
ret = -ENOTSUP;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mfd_axp192_gpio_func_ctrl(const struct device *dev, const struct device *client_dev,
|
||||
uint8_t gpio, enum axp192_gpio_func func)
|
||||
{
|
||||
const struct mfd_axp192_config *config = dev->config;
|
||||
struct mfd_axp192_data *data = dev->data;
|
||||
bool is_output = false;
|
||||
int ret = 0;
|
||||
uint8_t reg_cfg;
|
||||
|
||||
if (!AXP192_GPIO_FUNC_VALID(func)) {
|
||||
LOG_ERR("Invalid function");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (gpio >= AXP192_GPIO_MAX_NUM) {
|
||||
LOG_ERR("Invalid gpio (%d)", gpio);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((data->gpio_mask_used[gpio] != 0) && (data->gpio_mask_used[gpio] != client_dev)) {
|
||||
LOG_INF("Warning: Pin already configured. Please check dt configuration");
|
||||
}
|
||||
|
||||
switch (gpio) {
|
||||
case 0U:
|
||||
__fallthrough;
|
||||
case 1U:
|
||||
__fallthrough;
|
||||
case 2U:
|
||||
/* GPIO 0-2*/
|
||||
switch (func) {
|
||||
case AXP192_GPIO_FUNC_INPUT:
|
||||
reg_cfg = AXP192_GPIO012_FUNC_VAL_INPUT;
|
||||
break;
|
||||
case AXP192_GPIO_FUNC_OUTPUT_OD:
|
||||
reg_cfg = AXP192_GPIO012_FUNC_VAL_OUTPUT_OD;
|
||||
is_output = true;
|
||||
break;
|
||||
case AXP192_GPIO_FUNC_OUTPUT_LOW:
|
||||
reg_cfg = AXP192_GPIO012_FUNC_VAL_OUTPUT_LOW;
|
||||
is_output = true;
|
||||
break;
|
||||
case AXP192_GPIO_FUNC_LDO:
|
||||
if (gpio == 0) {
|
||||
/* LDO is only applicable on GPIO0 */
|
||||
reg_cfg = AXP192_GPIO012_FUNC_VAL_LDO;
|
||||
} else {
|
||||
ret = -ENOTSUP;
|
||||
}
|
||||
break;
|
||||
case AXP192_GPIO_FUNC_ADC:
|
||||
reg_cfg = AXP192_GPIO012_FUNC_VAL_ADC;
|
||||
break;
|
||||
case AXP192_GPIO_FUNC_FLOAT:
|
||||
reg_cfg = AXP192_GPIO012_FUNC_VAL_FLOAT;
|
||||
break;
|
||||
default:
|
||||
ret = -ENOTSUP;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3U:
|
||||
/* GPIO3 */
|
||||
switch (func) {
|
||||
case AXP192_GPIO_FUNC_INPUT:
|
||||
reg_cfg = AXP192_GPIO3_FUNC_VAL_INPUT | AXP192_GPIO34_FUNC_ENA;
|
||||
break;
|
||||
case AXP192_GPIO_FUNC_OUTPUT_OD:
|
||||
reg_cfg = AXP192_GPIO3_FUNC_VAL_OUTPUT_OD | AXP192_GPIO34_FUNC_ENA;
|
||||
is_output = true;
|
||||
break;
|
||||
case AXP192_GPIO_FUNC_CHARGE_CTL:
|
||||
reg_cfg = AXP192_GPIO3_FUNC_VAL_CHARGE_CTL;
|
||||
break;
|
||||
default:
|
||||
ret = -ENOTSUP;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4U:
|
||||
/* GPIO4 */
|
||||
switch (func) {
|
||||
case AXP192_GPIO_FUNC_INPUT:
|
||||
reg_cfg = AXP192_GPIO4_FUNC_VAL_INPUT | AXP192_GPIO34_FUNC_ENA;
|
||||
break;
|
||||
case AXP192_GPIO_FUNC_OUTPUT_OD:
|
||||
reg_cfg = AXP192_GPIO4_FUNC_VAL_OUTPUT_OD | AXP192_GPIO34_FUNC_ENA;
|
||||
is_output = true;
|
||||
break;
|
||||
case AXP192_GPIO_FUNC_ADC:
|
||||
reg_cfg = AXP192_GPIO4_FUNC_VAL_ADC | AXP192_GPIO34_FUNC_ENA;
|
||||
break;
|
||||
case AXP192_GPIO_FUNC_CHARGE_CTL:
|
||||
reg_cfg = AXP192_GPIO4_FUNC_VAL_CHARGE_CTL;
|
||||
break;
|
||||
default:
|
||||
ret = -ENOTSUP;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (ret != 0) {
|
||||
LOG_ERR("Invalid function (0x%x) for gpio %d", func, gpio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = i2c_reg_update_byte_dt(&(config->i2c), gpio_reg_desc[gpio].reg,
|
||||
gpio_reg_desc[gpio].mask, reg_cfg);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Save gpio configuration state */
|
||||
data->gpio_mask_used[gpio] = client_dev;
|
||||
if (is_output) {
|
||||
data->gpio_mask_output |= (1u << gpio);
|
||||
} else {
|
||||
data->gpio_mask_output &= ~(1u << gpio);
|
||||
}
|
||||
LOG_DBG("GPIO %d configured successfully (func=0x%x)", gpio, reg_cfg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mfd_axp192_gpio_pd_get(const struct device *dev, uint8_t gpio, bool *enabled)
|
||||
{
|
||||
const struct mfd_axp192_config *config = dev->config;
|
||||
uint8_t gpio_val;
|
||||
uint8_t pd_reg_mask = 0;
|
||||
int ret = 0;
|
||||
|
||||
switch (gpio) {
|
||||
case 0U:
|
||||
pd_reg_mask = AXP192_GPIO0_PULLDOWN_ENABLE;
|
||||
break;
|
||||
case 1U:
|
||||
pd_reg_mask = AXP192_GPIO1_PULLDOWN_ENABLE;
|
||||
break;
|
||||
case 2U:
|
||||
pd_reg_mask = AXP192_GPIO2_PULLDOWN_ENABLE;
|
||||
break;
|
||||
|
||||
case 3U:
|
||||
__fallthrough;
|
||||
case 4U:
|
||||
__fallthrough;
|
||||
case 5U:
|
||||
LOG_DBG("Pull-Down not support on gpio %d", gpio);
|
||||
return -ENOTSUP;
|
||||
|
||||
default:
|
||||
LOG_ERR("Invalid gpio (%d)", gpio);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = i2c_reg_read_byte_dt(&(config->i2c), AXP192_GPIO012_REG_PULLDOWN, &gpio_val);
|
||||
|
||||
if (ret == 0) {
|
||||
*enabled = ((gpio_val & pd_reg_mask) != 0);
|
||||
LOG_DBG("Pull-Down stats of gpio %d: %d", gpio, *enabled);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mfd_axp192_gpio_pd_ctrl(const struct device *dev, uint8_t gpio, bool enable)
|
||||
{
|
||||
uint8_t reg_pd_val = 0;
|
||||
uint8_t reg_pd_mask = 0;
|
||||
const struct mfd_axp192_config *config = dev->config;
|
||||
int ret = 0;
|
||||
|
||||
/* Configure pull-down. Pull-down is only supported by GPIO3 and GPIO4 */
|
||||
switch (gpio) {
|
||||
case 0U:
|
||||
reg_pd_mask = AXP192_GPIO0_PULLDOWN_ENABLE;
|
||||
if (enable) {
|
||||
reg_pd_val = AXP192_GPIO0_PULLDOWN_ENABLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1U:
|
||||
reg_pd_mask = AXP192_GPIO1_PULLDOWN_ENABLE;
|
||||
if (enable) {
|
||||
reg_pd_val = AXP192_GPIO1_PULLDOWN_ENABLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2U:
|
||||
reg_pd_mask = AXP192_GPIO2_PULLDOWN_ENABLE;
|
||||
if (enable) {
|
||||
reg_pd_val = AXP192_GPIO2_PULLDOWN_ENABLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3U:
|
||||
__fallthrough;
|
||||
case 4U:
|
||||
__fallthrough;
|
||||
case 5U:
|
||||
LOG_ERR("Pull-Down not support on gpio %d", gpio);
|
||||
return -ENOTSUP;
|
||||
|
||||
default:
|
||||
LOG_ERR("Invalid gpio (%d)", gpio);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = i2c_reg_update_byte_dt(&(config->i2c), AXP192_GPIO012_REG_PULLDOWN, reg_pd_mask,
|
||||
reg_pd_val);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mfd_axp192_gpio_read_port(const struct device *dev, uint8_t *value)
|
||||
{
|
||||
const struct mfd_axp192_config *config = dev->config;
|
||||
const struct mfd_axp192_data *data = dev->data;
|
||||
int ret;
|
||||
uint8_t gpio012_val;
|
||||
uint8_t gpio34_val;
|
||||
uint8_t gpio_input_val;
|
||||
uint8_t gpio_output_val;
|
||||
|
||||
/* read gpio0-2 */
|
||||
ret = i2c_reg_read_byte_dt(&(config->i2c), AXP192_GPIO012_REG_PINVAL, &gpio012_val);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* read gpio3-4 */
|
||||
ret = i2c_reg_read_byte_dt(&(config->i2c), AXP192_GPIO34_REG_PINVAL, &gpio34_val);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
LOG_DBG("GPIO012 pinval-reg=0x%x", gpio012_val);
|
||||
LOG_DBG("GPIO34 pinval-reg =0x%x", gpio34_val);
|
||||
LOG_DBG("Output-Mask =0x%x", data->gpio_mask_output);
|
||||
|
||||
gpio_input_val =
|
||||
((gpio012_val & AXP192_GPIO012_INTPUT_MASK) >> AXP192_GPIO012_INTPUT_SHIFT);
|
||||
gpio_input_val |=
|
||||
(((gpio34_val & AXP192_GPIO34_INTPUT_MASK) >> AXP192_GPIO34_INTPUT_SHIFT) << 3u);
|
||||
|
||||
gpio_output_val = (gpio012_val & AXP192_GPIO012_OUTPUT_MASK);
|
||||
gpio_output_val |= ((gpio34_val & AXP192_GPIO34_OUTPUT_MASK) << 3u);
|
||||
|
||||
*value = gpio_input_val & ~(data->gpio_mask_output);
|
||||
*value |= (gpio_output_val & data->gpio_mask_output);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mfd_axp192_gpio_write_port(const struct device *dev, uint8_t value, uint8_t mask)
|
||||
{
|
||||
const struct mfd_axp192_config *config = dev->config;
|
||||
int ret;
|
||||
uint8_t gpio_reg_val;
|
||||
uint8_t gpio_reg_mask;
|
||||
|
||||
/* Write gpio0-2. Mask out other port pins */
|
||||
gpio_reg_val = (value & AXP192_GPIO012_OUTPUT_MASK);
|
||||
gpio_reg_mask = mask & AXP192_GPIO012_OUTPUT_MASK;
|
||||
if (gpio_reg_mask != 0) {
|
||||
ret = i2c_reg_update_byte_dt(&(config->i2c), AXP192_GPIO012_REG_PINVAL,
|
||||
gpio_reg_mask, gpio_reg_val);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
LOG_DBG("GPIO012 pinval-reg=0x%x mask=0x%x", gpio_reg_val, gpio_reg_mask);
|
||||
}
|
||||
|
||||
/* Write gpio3-4. Mask out other port pins */
|
||||
gpio_reg_val = value >> 3U;
|
||||
gpio_reg_mask = (mask >> 3U) & AXP192_GPIO34_OUTPUT_MASK;
|
||||
if (gpio_reg_mask != 0) {
|
||||
ret = i2c_reg_update_byte_dt(&(config->i2c), AXP192_GPIO34_REG_PINVAL,
|
||||
gpio_reg_mask, gpio_reg_val);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
LOG_DBG("GPIO34 pinval-reg =0x%x mask=0x%x", gpio_reg_val, gpio_reg_mask);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MFD_AXP192_DEFINE(inst) \
|
||||
static const struct mfd_axp192_config config##inst = { \
|
||||
.i2c = I2C_DT_SPEC_INST_GET(inst), \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(inst, mfd_axp192_init, NULL, NULL, &config##inst, POST_KERNEL, \
|
||||
CONFIG_MFD_INIT_PRIORITY, NULL);
|
||||
static struct mfd_axp192_data data##inst; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(inst, mfd_axp192_init, NULL, &data##inst, &config##inst, \
|
||||
POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, NULL);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(MFD_AXP192_DEFINE)
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <zephyr/dt-bindings/regulator/axp192.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/logging/log_instance.h>
|
||||
#include <zephyr/drivers/mfd/axp192.h>
|
||||
|
||||
LOG_MODULE_REGISTER(regulator_axp192, CONFIG_REGULATOR_LOG_LEVEL);
|
||||
|
||||
|
@ -28,6 +29,8 @@ LOG_MODULE_REGISTER(regulator_axp192, CONFIG_REGULATOR_LOG_LEVEL);
|
|||
#define AXP192_REG_DCDC3_VOLTAGE 0x27U
|
||||
#define AXP192_REG_LDO23_VOLTAGE 0x28U
|
||||
#define AXP192_REG_DCDC123_WORKMODE 0x80U
|
||||
#define AXP192_REG_GPIO0_CONTROL 0x90U
|
||||
#define AXP192_REG_LDOIO0_VOLTAGE 0x91U
|
||||
|
||||
struct regulator_axp192_desc {
|
||||
const uint8_t enable_reg;
|
||||
|
@ -114,6 +117,24 @@ static const struct regulator_axp192_desc dcdc3_desc = {
|
|||
.num_ranges = ARRAY_SIZE(dcdc3_ranges),
|
||||
};
|
||||
|
||||
static const struct linear_range ldoio0_ranges[] = {
|
||||
LINEAR_RANGE_INIT(1800000u, 100000u, 0x00u, 0x0Fu),
|
||||
};
|
||||
|
||||
static const struct regulator_axp192_desc ldoio0_desc = {
|
||||
.enable_reg = AXP192_REG_GPIO0_CONTROL,
|
||||
.enable_mask = 0x07u,
|
||||
.enable_val = 0x03u,
|
||||
.vsel_reg = AXP192_REG_LDOIO0_VOLTAGE,
|
||||
.vsel_mask = 0xF0u,
|
||||
.vsel_bitpos = 4u,
|
||||
.max_ua = 50000u,
|
||||
.workmode_reg = 0u,
|
||||
.workmode_mask = 0u,
|
||||
.ranges = ldoio0_ranges,
|
||||
.num_ranges = ARRAY_SIZE(ldoio0_ranges),
|
||||
};
|
||||
|
||||
static const struct linear_range ldo2_ranges[] = {
|
||||
LINEAR_RANGE_INIT(1800000U, 100000U, 0x00U, 0x0FU),
|
||||
};
|
||||
|
@ -159,8 +180,14 @@ static int axp192_enable(const struct device *dev)
|
|||
LOG_INST_DBG(config->log, "[0x%02x]=0x%02x mask=0x%02x", config->desc->enable_reg,
|
||||
config->desc->enable_val, config->desc->enable_mask);
|
||||
|
||||
ret = i2c_reg_update_byte_dt(&config->i2c, config->desc->enable_reg,
|
||||
config->desc->enable_mask, config->desc->enable_val);
|
||||
/* special case for LDOIO0, which is multiplexed with GPIO0 */
|
||||
if (config->desc->enable_reg == AXP192_REG_GPIO0_CONTROL) {
|
||||
ret = mfd_axp192_gpio_func_ctrl(config->mfd, dev, 0, AXP192_GPIO_FUNC_LDO);
|
||||
} else {
|
||||
ret = i2c_reg_update_byte_dt(&config->i2c, config->desc->enable_reg,
|
||||
config->desc->enable_mask, config->desc->enable_val);
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
LOG_INST_ERR(config->log, "Failed to enable regulator");
|
||||
}
|
||||
|
@ -177,8 +204,13 @@ static int axp192_disable(const struct device *dev)
|
|||
LOG_INST_DBG(config->log, "[0x%02x]=0 mask=0x%x", config->desc->enable_reg,
|
||||
config->desc->enable_mask);
|
||||
|
||||
ret = i2c_reg_update_byte_dt(&config->i2c, config->desc->enable_reg,
|
||||
config->desc->enable_mask, 0u);
|
||||
/* special case for LDOIO0, which is multiplexed with GPIO0 */
|
||||
if (config->desc->enable_reg == AXP192_REG_GPIO0_CONTROL) {
|
||||
ret = mfd_axp192_gpio_func_ctrl(config->mfd, dev, 0, AXP192_GPIO_FUNC_OUTPUT_LOW);
|
||||
} else {
|
||||
ret = i2c_reg_update_byte_dt(&config->i2c, config->desc->enable_reg,
|
||||
config->desc->enable_mask, 0u);
|
||||
}
|
||||
if (ret != 0) {
|
||||
LOG_INST_ERR(config->log, "Failed to disable regulator");
|
||||
}
|
||||
|
@ -354,6 +386,7 @@ static int regulator_axp192_init(const struct device *dev)
|
|||
REGULATOR_AXP192_DEFINE_COND(inst, dcdc1) \
|
||||
REGULATOR_AXP192_DEFINE_COND(inst, dcdc2) \
|
||||
REGULATOR_AXP192_DEFINE_COND(inst, dcdc3) \
|
||||
REGULATOR_AXP192_DEFINE_COND(inst, ldoio0) \
|
||||
REGULATOR_AXP192_DEFINE_COND(inst, ldo2) \
|
||||
REGULATOR_AXP192_DEFINE_COND(inst, ldo3)
|
||||
|
||||
|
|
22
dts/bindings/gpio/x-powers,axp192-gpio.yaml
Normal file
22
dts/bindings/gpio/x-powers,axp192-gpio.yaml
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Copyright (c) 2023 Martin Kiepfer
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: PXA192 GPIO Controller
|
||||
|
||||
compatible: "x-powers,axp192-gpio"
|
||||
|
||||
include: gpio-controller.yaml
|
||||
|
||||
properties:
|
||||
"#gpio-cells":
|
||||
const: 2
|
||||
|
||||
ngpios:
|
||||
required: true
|
||||
const: 5
|
||||
description: |
|
||||
Number of GPIOs available on axp192.
|
||||
|
||||
gpio-cells:
|
||||
- pin
|
||||
- flags
|
|
@ -25,6 +25,9 @@ description: |
|
|||
DCDC3 {
|
||||
/* all properties for DCDC3 */
|
||||
};
|
||||
LDOIO0 {
|
||||
/* all properties for LDOIO0 */
|
||||
};
|
||||
LDO2 {
|
||||
/* all properties for LDO2 */
|
||||
};
|
||||
|
|
137
include/zephyr/drivers/mfd/axp192.h
Normal file
137
include/zephyr/drivers/mfd/axp192.h
Normal file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Martin Kiepfer
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_DRIVERS_MFD_AXP192_H_
|
||||
#define ZEPHYR_INCLUDE_DRIVERS_MFD_AXP192_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPIO function type. Only one function can be configured per GPIO.
|
||||
*/
|
||||
enum axp192_gpio_func {
|
||||
AXP192_GPIO_FUNC_INPUT = BIT(0),
|
||||
AXP192_GPIO_FUNC_OUTPUT_OD = BIT(1),
|
||||
AXP192_GPIO_FUNC_OUTPUT_LOW = BIT(2),
|
||||
AXP192_GPIO_FUNC_LDO = BIT(3),
|
||||
AXP192_GPIO_FUNC_ADC = BIT(4),
|
||||
AXP192_GPIO_FUNC_PWM = BIT(5),
|
||||
AXP192_GPIO_FUNC_FLOAT = BIT(6),
|
||||
AXP192_GPIO_FUNC_CHARGE_CTL = BIT(7),
|
||||
AXP192_GPIO_FUNC_INVALID
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Check if a given GPIO function value is valid.
|
||||
*/
|
||||
#define AXP192_GPIO_FUNC_VALID(func) (func < AXP192_GPIO_FUNC_INVALID)
|
||||
|
||||
/**
|
||||
* @brief Maximum number of GPIOs supported by AXP192 PMIC.
|
||||
*/
|
||||
#define AXP192_GPIO_MAX_NUM 5U
|
||||
|
||||
/**
|
||||
* @defgroup mdf_interface_axp192 MFD AXP192 interface
|
||||
* @ingroup mfd_interfaces
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Request a GPIO pin to be configured to a specific function. GPIO0..4
|
||||
* of AXP192 feature various functions (see @ref axp192_gpio_func for details).
|
||||
* A GPIO can only be used by one driver instance. Subsequential calls on the
|
||||
* same GPIO will overwrite according function.
|
||||
*
|
||||
* @param dev axp192 mfd device
|
||||
* @param client_dev client device the gpio is used in
|
||||
* @param gpio GPIO to be configured (0..4)
|
||||
* @param func Function to be configured (see @ref axp192_gpio_func for details)
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL if an invalid GPIO number is passed
|
||||
* @retval -ENOTSUP if the requested function is not supported by the given
|
||||
* @retval -errno in case of any bus error
|
||||
*/
|
||||
int mfd_axp192_gpio_func_ctrl(const struct device *dev, const struct device *client_dev,
|
||||
uint8_t gpio, enum axp192_gpio_func func);
|
||||
|
||||
/**
|
||||
* @brief Read out current configuration of a specific GPIO pin.
|
||||
*
|
||||
* @param dev axp192 mfd device
|
||||
* @param gpio GPIO to read configuration from
|
||||
* @param func Pointer to store current function configuration in.
|
||||
* @return 0 on success
|
||||
* @retval -EINVAL if an invalid GPIO number is passed
|
||||
* @retval -errno in case of any bus error
|
||||
*/
|
||||
int mfd_axp192_gpio_func_get(const struct device *dev, uint8_t gpio, enum axp192_gpio_func *func);
|
||||
|
||||
/**
|
||||
* @brief Enable pull-down on specified GPIO pin. AXP192 only supports
|
||||
* pull-down on GPIO3..4. Pull-ups are not supprted.
|
||||
*
|
||||
* @param dev axp192 mfd device
|
||||
* @param gpio GPIO to control pull-downs
|
||||
* @param enable true to enable, false to disable pull-down
|
||||
* @retval 0 on success
|
||||
* @retval -EINVAL if an invalid argument is given (e.g. invalid GPIO number)
|
||||
* @retval -ENOTSUP if pull-down is not supported by the givenn GPIO
|
||||
* @retval -errno in case of any bus error
|
||||
*/
|
||||
int mfd_axp192_gpio_pd_ctrl(const struct device *dev, uint8_t gpio, bool enable);
|
||||
|
||||
/**
|
||||
* @brief Read out the current pull-down configuration of a specific GPIO.
|
||||
*
|
||||
* @param dev axp192 mfd device
|
||||
* @param gpio GPIO to control pull-downs
|
||||
* @param enabled Pointer to current pull-down configuration (true: pull-down
|
||||
* enabled/ false: pull-down disabled)
|
||||
* @retval -EINVAL if an invalid argument is given (e.g. invalid GPIO number)
|
||||
* @retval -ENOTSUP if pull-down is not supported by the givenn GPIO
|
||||
* @retval -errno in case of any bus error
|
||||
*/
|
||||
int mfd_axp192_gpio_pd_get(const struct device *dev, uint8_t gpio, bool *enabled);
|
||||
|
||||
/**
|
||||
* @brief Read GPIO port.
|
||||
*
|
||||
* @param dev axp192 mfd device
|
||||
* @param value Pointer to port value
|
||||
* @retval 0 on success
|
||||
* @retval -errno in case of any bus error
|
||||
*/
|
||||
int mfd_axp192_gpio_read_port(const struct device *dev, uint8_t *value);
|
||||
|
||||
/**
|
||||
* @brief Write GPIO port.
|
||||
*
|
||||
* @param dev axp192 mfd device
|
||||
* @param value port value
|
||||
* @param mask pin mask within the port
|
||||
* @retval 0 on success
|
||||
* @retval -errno in case of any bus error
|
||||
*/
|
||||
int mfd_axp192_gpio_write_port(const struct device *dev, uint8_t value, uint8_t mask);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_DRIVERS_MFD_AXP192_H_ */
|
|
@ -172,6 +172,18 @@
|
|||
int-gpios = <&test_gpio 0 0>;
|
||||
reset-gpios = <&test_gpio 0 0>;
|
||||
};
|
||||
|
||||
test_i2c_axp192: axp192@24 {
|
||||
compatible = "x-powers,axp192";
|
||||
reg = <0x24>;
|
||||
|
||||
axp192_gpio {
|
||||
compatible = "x-powers,axp192-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
ngpios = <5>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nct3807_alert_1 {
|
||||
|
|
|
@ -69,6 +69,7 @@ axp192@4 {
|
|||
DCDC1 {};
|
||||
DCDC2 {};
|
||||
DCDC3 {};
|
||||
LDOIO0 {};
|
||||
LDO1 {};
|
||||
LDO2 {};
|
||||
LDO3 {};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue