mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-08-03 14:54:26 +00:00
fixed a couple occurrences of not returning -errno. Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
282 lines
6.8 KiB
C
282 lines
6.8 KiB
C
/*
|
|
* Copyright (c) 2024 Texas Instruments Incorporated
|
|
* Copyright (c) 2024 BayLibre, SAS
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#define DT_DRV_COMPAT ti_cc23x0_gpio
|
|
|
|
#include <zephyr/types.h>
|
|
#include <zephyr/device.h>
|
|
#include <zephyr/irq.h>
|
|
#include <zephyr/drivers/gpio.h>
|
|
#include <zephyr/drivers/gpio/gpio_utils.h>
|
|
|
|
#include <driverlib/clkctl.h>
|
|
#include <driverlib/gpio.h>
|
|
#include <inc/hw_ioc.h>
|
|
|
|
#define IOC_ADDR(index) (IOC_BASE + IOC_O_IOC0 + (sizeof(uint32_t) * (index)))
|
|
|
|
struct gpio_cc23x0_config {
|
|
/* gpio_driver_config needs to be first */
|
|
struct gpio_driver_config common;
|
|
};
|
|
|
|
struct gpio_cc23x0_data {
|
|
/* gpio_driver_data needs to be first */
|
|
struct gpio_driver_data common;
|
|
sys_slist_t callbacks;
|
|
};
|
|
|
|
static void set_pin_mask_non_atomic(uint8_t index, uint32_t registerBaseAddress)
|
|
{
|
|
GPIOSetConfigDio(GPIO_BASE + registerBaseAddress, BIT(index));
|
|
}
|
|
|
|
static int gpio_cc23x0_config(const struct device *port, gpio_pin_t pin, gpio_flags_t flags)
|
|
{
|
|
uint32_t config = 0;
|
|
uint32_t iocfg_reg = IOC_ADDR(pin);
|
|
gpio_flags_t direction = flags & GPIO_DIR_MASK;
|
|
|
|
if (flags & GPIO_PULL_UP) {
|
|
config |= IOC_IOC0_PULLCTL_PULL_UP;
|
|
} else if (flags & GPIO_PULL_DOWN) {
|
|
config |= IOC_IOC0_PULLCTL_PULL_DOWN;
|
|
} else {
|
|
config |= IOC_IOC0_PULLCTL_PULL_DIS;
|
|
}
|
|
|
|
if (!(flags & GPIO_SINGLE_ENDED)) {
|
|
config |= IOC_IOC0_IOMODE_NORMAL;
|
|
} else {
|
|
if (flags & GPIO_LINE_OPEN_DRAIN) {
|
|
config |= IOC_IOC0_IOMODE_OPEND;
|
|
} else {
|
|
config |= IOC_IOC0_IOMODE_OPENS;
|
|
}
|
|
}
|
|
if (direction & GPIO_INPUT) {
|
|
config |= IOC_IOC0_INPEN_EN | IOC_IOC0_HYSTEN_EN;
|
|
}
|
|
|
|
GPIOSetConfigDio(iocfg_reg, config);
|
|
|
|
if (flags & GPIO_OUTPUT) {
|
|
if (flags & GPIO_OUTPUT_INIT_HIGH) {
|
|
GPIOSetDio(pin);
|
|
} else if (flags & GPIO_OUTPUT_INIT_LOW) {
|
|
GPIOClearDio(pin);
|
|
}
|
|
GPIOSetOutputEnableDio(pin, GPIO_OUTPUT_ENABLE);
|
|
} else {
|
|
GPIOSetOutputEnableDio(pin, GPIO_OUTPUT_DISABLE);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_GPIO_GET_CONFIG
|
|
static int gpio_cc23x0_get_config(const struct device *port, gpio_pin_t pin, gpio_flags_t *flags)
|
|
{
|
|
uint32_t out_flag = 0;
|
|
uint32_t iocfg_reg = IOC_ADDR(pin);
|
|
uint32_t config = GPIOGetConfigDio(iocfg_reg);
|
|
|
|
/* GPIO input/output configuration flags */
|
|
if (config & IOC_IOC0_INPEN_EN) {
|
|
out_flag |= GPIO_INPUT;
|
|
}
|
|
|
|
if (GPIOGetOutputEnableDio(pin)) {
|
|
out_flag |= GPIO_OUTPUT;
|
|
|
|
if (GPIOReadDio(pin)) {
|
|
out_flag |= GPIO_OUTPUT_INIT_HIGH;
|
|
} else {
|
|
/* This is the default value. If not explicitly set,
|
|
* the returned config will not be symmetric
|
|
*/
|
|
out_flag |= GPIO_OUTPUT_INIT_LOW;
|
|
}
|
|
}
|
|
|
|
/* GPIO interrupt configuration flags */
|
|
if ((config & IOC_IOC0_EDGEDET_M) != IOC_IOC0_EDGEDET_EDGE_DIS) {
|
|
if (config & IOC_IOC0_EDGEDET_EDGE_POS) {
|
|
out_flag |= GPIO_INT_EDGE_RISING;
|
|
}
|
|
|
|
if (config & IOC_IOC0_EDGEDET_EDGE_NEG) {
|
|
out_flag |= GPIO_INT_EDGE_FALLING;
|
|
}
|
|
} else {
|
|
/* This is the default value. If not explicitly set,
|
|
* the returned config will not be symmetric
|
|
*/
|
|
out_flag |= GPIO_INT_DISABLE;
|
|
}
|
|
|
|
/* GPIO pin drive flags */
|
|
if (config & IOC_IOC0_IOMODE_OPENS) {
|
|
out_flag |= GPIO_OPEN_SOURCE;
|
|
}
|
|
|
|
if (config & IOC_IOC0_IOMODE_OPEND) {
|
|
out_flag |= IOC_IOC0_IOMODE_OPEND;
|
|
}
|
|
|
|
if (config & IOC_IOC0_PULLCTL_PULL_UP) {
|
|
out_flag |= GPIO_PULL_UP;
|
|
}
|
|
|
|
if (config & IOC_IOC0_PULLCTL_PULL_DOWN) {
|
|
out_flag |= GPIO_PULL_DOWN;
|
|
}
|
|
|
|
*flags = out_flag;
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
static int gpio_cc23x0_port_get_raw(const struct device *port, uint32_t *value)
|
|
{
|
|
*value = GPIOReadMultiDio(GPIO_DIO_ALL_MASK);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int gpio_cc23x0_port_set_masked_raw(const struct device *port, uint32_t mask, uint32_t value)
|
|
{
|
|
GPIOWriteMultiDio(mask, value);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int gpio_cc23x0_port_set_bits_raw(const struct device *port, uint32_t mask)
|
|
{
|
|
GPIOSetMultiDio(mask);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int gpio_cc23x0_port_clear_bits_raw(const struct device *port, uint32_t mask)
|
|
{
|
|
GPIOClearMultiDio(mask);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int gpio_cc23x0_port_toggle_bits(const struct device *port, uint32_t mask)
|
|
{
|
|
GPIOToggleMultiDio(mask);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int gpio_cc23x0xx_pin_interrupt_configure(const struct device *port, gpio_pin_t pin,
|
|
enum gpio_int_mode mode, enum gpio_int_trig trig)
|
|
{
|
|
if (mode == GPIO_INT_MODE_LEVEL) {
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
uint32_t config = GPIOGetConfigDio(IOC_ADDR(pin)) & ~IOC_IOC0_EDGEDET_M;
|
|
|
|
if (mode == GPIO_INT_MODE_DISABLED) {
|
|
config |= IOC_IOC1_EDGEDET_EDGE_DIS;
|
|
|
|
GPIOSetConfigDio(IOC_ADDR(pin), config);
|
|
|
|
/* Disable interrupt mask */
|
|
set_pin_mask_non_atomic(pin, GPIO_O_IMCLR);
|
|
|
|
} else if (mode == GPIO_INT_MODE_EDGE) {
|
|
switch (trig) {
|
|
case GPIO_INT_TRIG_LOW:
|
|
config |= IOC_IOC1_EDGEDET_EDGE_NEG;
|
|
break;
|
|
case GPIO_INT_TRIG_HIGH:
|
|
config |= IOC_IOC1_EDGEDET_EDGE_POS;
|
|
break;
|
|
case GPIO_INT_TRIG_BOTH:
|
|
config |= IOC_IOC1_EDGEDET_EDGE_BOTH;
|
|
break;
|
|
default:
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
GPIOSetConfigDio(IOC_ADDR(pin), config);
|
|
|
|
/* Enable interrupt mask */
|
|
set_pin_mask_non_atomic(pin, GPIO_O_ICLR);
|
|
set_pin_mask_non_atomic(pin, GPIO_O_IMSET);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int gpio_cc23x0_manage_callback(const struct device *port, struct gpio_callback *callback,
|
|
bool set)
|
|
{
|
|
struct gpio_cc23x0_data *data = port->data;
|
|
|
|
return gpio_manage_callback(&data->callbacks, callback, set);
|
|
}
|
|
|
|
static uint32_t gpio_cc23x0_get_pending_int(const struct device *dev)
|
|
{
|
|
return GPIOGetEventMultiDio(GPIO_DIO_ALL_MASK);
|
|
}
|
|
|
|
static void gpio_cc23x0_isr(const struct device *dev)
|
|
{
|
|
struct gpio_cc23x0_data *data = dev->data;
|
|
|
|
uint32_t status = GPIOGetEventMultiDio(GPIO_DIO_ALL_MASK);
|
|
|
|
GPIOClearEventMultiDio(status);
|
|
|
|
gpio_fire_callbacks(&data->callbacks, dev, status);
|
|
}
|
|
|
|
static int gpio_cc23x0_init(const struct device *dev)
|
|
{
|
|
/* Enable GPIO domain clock */
|
|
CLKCTLEnable(CLKCTL_BASE, CLKCTL_GPIO);
|
|
|
|
/* Enable IRQ */
|
|
IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), gpio_cc23x0_isr,
|
|
DEVICE_DT_INST_GET(0), 0);
|
|
|
|
irq_enable(DT_INST_IRQN(0));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static DEVICE_API(gpio, gpio_cc23x0_driver_api) = {
|
|
.pin_configure = gpio_cc23x0_config,
|
|
#ifdef CONFIG_GPIO_GET_CONFIG
|
|
.pin_get_config = gpio_cc23x0_get_config,
|
|
#endif
|
|
.port_get_raw = gpio_cc23x0_port_get_raw,
|
|
.port_set_masked_raw = gpio_cc23x0_port_set_masked_raw,
|
|
.port_set_bits_raw = gpio_cc23x0_port_set_bits_raw,
|
|
.port_clear_bits_raw = gpio_cc23x0_port_clear_bits_raw,
|
|
.port_toggle_bits = gpio_cc23x0_port_toggle_bits,
|
|
.pin_interrupt_configure = gpio_cc23x0xx_pin_interrupt_configure,
|
|
.manage_callback = gpio_cc23x0_manage_callback,
|
|
.get_pending_int = gpio_cc23x0_get_pending_int,
|
|
};
|
|
|
|
static const struct gpio_cc23x0_config gpio_cc23x0_config_0 = {
|
|
.common = {/* Read ngpios from DT */
|
|
.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(0)}};
|
|
|
|
static struct gpio_cc23x0_data gpio_cc23x0_data_0;
|
|
|
|
DEVICE_DT_INST_DEFINE(0, gpio_cc23x0_init, NULL, &gpio_cc23x0_data_0, &gpio_cc23x0_config_0,
|
|
PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, &gpio_cc23x0_driver_api);
|