soc: ti_simplelink: add support for TI CC13x2 / CC26x2 series

Add initial support for the TI CC13x2 / CC26x2 series with the CC2652R
and CC1352R SoCs. The UART and GPIO peripherals are supported. Drivers
use the driverlib HAL from the TI CC13x2 / CC26x2 SDK.

Signed-off-by: Brett Witherspoon <spoonb@cdspooner.com>
This commit is contained in:
Brett Witherspoon 2019-04-18 13:29:26 -05:00 committed by Kumar Gala
parent e490be387e
commit f101b77db2
29 changed files with 1299 additions and 0 deletions

View file

@ -4,6 +4,7 @@ zephyr_library()
zephyr_library_sources_ifdef(CONFIG_GPIO_ALTERA_NIOS2 gpio_altera_nios2.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_ATMEL_SAM3 gpio_atmel_sam3.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_CC13XX_CC26XX gpio_cc13xx_cc26xx.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_CC2650 gpio_cc2650.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_CC32XX gpio_cc32xx.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_CMSDK_AHB gpio_cmsdk_ahb.c)

View file

@ -46,6 +46,8 @@ source "drivers/gpio/Kconfig.nrfx"
source "drivers/gpio/Kconfig.cmsdk_ahb"
source "drivers/gpio/Kconfig.cc13xx_cc26xx"
source "drivers/gpio/Kconfig.cc32xx"
source "drivers/gpio/Kconfig.sifive"

View file

@ -0,0 +1,13 @@
# Kconfig.cc13xx_cc26xx - TI CC13xx / CC26xx GPIO configuration options
#
# Copyright (c) 2019 Brett Witherspoon
#
# SPDX-License-Identifier: Apache-2.0
#
config GPIO_CC13XX_CC26XX
bool "TI SimpleLink CC13xx / CC26xx GPIO driver"
depends on SOC_SERIES_CC13X2_CC26X2
select HAS_DTS_GPIO
help
Enable the TI SimpleLink CC13xx / CC26xx GPIO driver.

View file

@ -0,0 +1,256 @@
/*
* Copyright (c) 2019 Brett Witherspoon
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/types.h>
#include <misc/__assert.h>
#include <device.h>
#include <errno.h>
#include <gpio.h>
#include <driverlib/gpio.h>
#include <driverlib/interrupt.h>
#include <driverlib/ioc.h>
#include <driverlib/prcm.h>
#include "gpio_utils.h"
struct gpio_cc13xx_cc26xx_data {
sys_slist_t callbacks;
u32_t pin_callback_enables;
};
static struct gpio_cc13xx_cc26xx_data gpio_cc13xx_cc26xx_data_0;
static int gpio_cc13xx_cc26xx_config(struct device *port, int access_op,
u32_t pin, int flags)
{
u32_t config;
if (access_op != GPIO_ACCESS_BY_PIN)
return -ENOTSUP;
__ASSERT_NO_MSG(pin < NUM_IO_MAX);
config = IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | IOC_SLEW_DISABLE |
IOC_NO_WAKE_UP;
if (flags & GPIO_INT) {
__ASSERT_NO_MSG((flags & GPIO_DIR_MASK) == GPIO_DIR_IN);
config |= IOC_INT_ENABLE | IOC_INPUT_ENABLE;
if (flags & GPIO_INT_EDGE) {
if (flags & GPIO_INT_DOUBLE_EDGE) {
config |= IOC_BOTH_EDGES;
} else if (flags & GPIO_INT_ACTIVE_LOW) {
config |= IOC_FALLING_EDGE;
} else {
config |= IOC_RISING_EDGE;
}
} else {
return -ENOTSUP;
}
config |= (flags & GPIO_INT_DEBOUNCE) ? IOC_HYST_ENABLE :
IOC_HYST_DISABLE;
} else {
config |= IOC_INT_DISABLE | IOC_NO_EDGE | IOC_HYST_DISABLE;
config |= (flags & GPIO_DIR_MASK) == GPIO_DIR_IN ?
IOC_INPUT_ENABLE :
IOC_INPUT_DISABLE;
}
config |= (flags & GPIO_POL_MASK) == GPIO_POL_INV ? IOC_IOMODE_INV :
IOC_IOMODE_NORMAL;
switch (flags & GPIO_PUD_MASK) {
case GPIO_PUD_NORMAL:
config |= IOC_NO_IOPULL;
break;
case GPIO_PUD_PULL_UP:
config |= IOC_IOPULL_UP;
break;
case GPIO_PUD_PULL_DOWN:
config |= IOC_IOPULL_DOWN;
break;
default:
return -EINVAL;
}
IOCPortConfigureSet(pin, IOC_PORT_GPIO, config);
if ((flags & GPIO_DIR_MASK) == GPIO_DIR_IN) {
GPIO_setOutputEnableDio(pin, GPIO_OUTPUT_DISABLE);
} else {
GPIO_setOutputEnableDio(pin, GPIO_OUTPUT_ENABLE);
}
return 0;
}
static int gpio_cc13xx_cc26xx_write(struct device *port, int access_op,
u32_t pin, u32_t value)
{
switch (access_op) {
case GPIO_ACCESS_BY_PIN:
__ASSERT_NO_MSG(pin < NUM_IO_MAX);
if (value) {
GPIO_setDio(pin);
} else {
GPIO_clearDio(pin);
}
break;
case GPIO_ACCESS_BY_PORT:
if (value) {
GPIO_setMultiDio(GPIO_DIO_ALL_MASK);
} else {
GPIO_clearMultiDio(GPIO_DIO_ALL_MASK);
}
break;
default:
return -EINVAL;
}
return 0;
}
static int gpio_cc13xx_cc26xx_read(struct device *port, int access_op,
u32_t pin, u32_t *value)
{
__ASSERT_NO_MSG(value != NULL);
switch (access_op) {
case GPIO_ACCESS_BY_PIN:
__ASSERT_NO_MSG(pin < NUM_IO_MAX);
*value = GPIO_readDio(pin);
break;
case GPIO_ACCESS_BY_PORT:
*value = GPIO_readMultiDio(GPIO_DIO_ALL_MASK);
break;
default:
return -EINVAL;
}
return 0;
}
static int gpio_cc13xx_cc26xx_manage_callback(struct device *port,
struct gpio_callback *callback,
bool set)
{
struct gpio_cc13xx_cc26xx_data *data = port->driver_data;
return gpio_manage_callback(&data->callbacks, callback, set);
}
static int gpio_cc13xx_cc26xx_enable_callback(struct device *port,
int access_op, u32_t pin)
{
struct gpio_cc13xx_cc26xx_data *data = port->driver_data;
switch (access_op) {
case GPIO_ACCESS_BY_PIN:
__ASSERT_NO_MSG(pin < NUM_IO_MAX);
data->pin_callback_enables |= (1 << pin);
break;
case GPIO_ACCESS_BY_PORT:
data->pin_callback_enables = 0xFFFFFFFF;
break;
default:
return -EINVAL;
}
return 0;
}
static int gpio_cc13xx_cc26xx_disable_callback(struct device *port,
int access_op, u32_t pin)
{
struct gpio_cc13xx_cc26xx_data *data = port->driver_data;
switch (access_op) {
case GPIO_ACCESS_BY_PIN:
__ASSERT_NO_MSG(pin < NUM_IO_MAX);
data->pin_callback_enables &= ~(1 << pin);
break;
case GPIO_ACCESS_BY_PORT:
data->pin_callback_enables = 0U;
break;
default:
return -EINVAL;
}
return 0;
}
static u32_t gpio_cc13xx_cc26xx_get_pending_int(struct device *dev)
{
return GPIO_getEventMultiDio(GPIO_DIO_ALL_MASK);
}
DEVICE_DECLARE(gpio_cc13xx_cc26xx);
static void gpio_cc13xx_cc26xx_isr(void *arg)
{
struct device *dev = arg;
struct gpio_cc13xx_cc26xx_data *data = dev->driver_data;
u32_t status = GPIO_getEventMultiDio(GPIO_DIO_ALL_MASK);
u32_t enabled = status & data->pin_callback_enables;
GPIO_clearEventMultiDio(status);
gpio_fire_callbacks(&data->callbacks, dev, enabled);
}
static int gpio_cc13xx_cc26xx_init(struct device *dev)
{
struct gpio_cc13xx_cc26xx_data *data = dev->driver_data;
/* Enable peripheral power domain */
PRCMPowerDomainOn(PRCM_DOMAIN_PERIPH);
/* Enable GPIO peripheral */
PRCMPeripheralRunEnable(PRCM_PERIPH_GPIO);
/* Load PRCM settings */
PRCMLoadSet();
while (!PRCMLoadGet()) {
continue;
}
/* Enable IRQ */
IRQ_CONNECT(DT_TI_CC13XX_CC26XX_GPIO_0_IRQ_0,
DT_TI_CC13XX_CC26XX_GPIO_0_IRQ_0_PRIORITY,
gpio_cc13xx_cc26xx_isr, DEVICE_GET(gpio_cc13xx_cc26xx), 0);
irq_enable(DT_TI_CC13XX_CC26XX_GPIO_0_IRQ_0);
/* Disable callbacks */
data->pin_callback_enables = 0;
/* Peripheral should not be accessed until power domain is on. */
while (PRCMPowerDomainStatus(PRCM_DOMAIN_PERIPH) !=
PRCM_DOMAIN_POWER_ON) {
continue;
}
return 0;
}
static const struct gpio_driver_api gpio_cc13xx_cc26xx_driver_api = {
.config = gpio_cc13xx_cc26xx_config,
.write = gpio_cc13xx_cc26xx_write,
.read = gpio_cc13xx_cc26xx_read,
.manage_callback = gpio_cc13xx_cc26xx_manage_callback,
.enable_callback = gpio_cc13xx_cc26xx_enable_callback,
.disable_callback = gpio_cc13xx_cc26xx_disable_callback,
.get_pending_int = gpio_cc13xx_cc26xx_get_pending_int
};
DEVICE_AND_API_INIT(gpio_cc13xx_cc26xx, DT_TI_CC13XX_CC26XX_GPIO_0_LABEL,
gpio_cc13xx_cc26xx_init, &gpio_cc13xx_cc26xx_data_0, NULL,
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
&gpio_cc13xx_cc26xx_driver_api);

View file

@ -1,6 +1,7 @@
# SPDX-License-Identifier: Apache-2.0
# Board initialization
zephyr_sources_ifdef(CONFIG_PINMUX_CC13XX_CC26XX pinmux_cc13xx_cc26xx.c)
zephyr_sources_ifdef(CONFIG_PINMUX_CC2650 pinmux_cc2650.c)
zephyr_sources_ifdef(CONFIG_PINMUX_ESP32 pinmux_esp32.c)
zephyr_sources_ifdef(CONFIG_PINMUX_SIFIVE pinmux_sifive.c)

View file

@ -49,6 +49,8 @@ source "drivers/pinmux/Kconfig.beetle"
source "drivers/pinmux/Kconfig.sifive"
source "drivers/pinmux/Kconfig.cc13xx_cc26xx"
source "drivers/pinmux/Kconfig.cc2650"
source "drivers/pinmux/Kconfig.esp32"

View file

@ -0,0 +1,12 @@
# Kconfig.cc13xx_cc26xx - TI CC13xx / CC26xx PINMUX configuration options
#
# Copyright (c) 2019 Brett Witherspoon
#
# SPDX-License-Identifier: Apache-2.0
#
config PINMUX_CC13XX_CC26XX
bool "TI SimpleLink CC13xx / CC26xx pinmux driver"
depends on SOC_SERIES_CC13X2_CC26X2
help
Enable the TI SimpleLink CC13xx / CC26xx pinmux driver.

View file

@ -0,0 +1,89 @@
/*
* Copyright (c) 2019 Brett Witherspoon
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <device.h>
#include <errno.h>
#include <misc/__assert.h>
#include <pinmux.h>
#include <driverlib/ioc.h>
static int pinmux_cc13xx_cc26xx_set(struct device *dev, u32_t pin, u32_t func)
{
ARG_UNUSED(dev);
__ASSERT_NO_MSG(pin < NUM_IO_MAX);
__ASSERT_NO_MSG(func < NUM_IO_PORTS);
IOCIOPortIdSet(pin, func);
return 0;
}
static int pinmux_cc13xx_cc26xx_get(struct device *dev, u32_t pin, u32_t *func)
{
ARG_UNUSED(dev);
__ASSERT_NO_MSG(pin < NUM_IO_MAX);
*func = IOCPortConfigureGet(pin) & IOC_IOCFG0_PORT_ID_M;
return 0;
}
static int pinmux_cc13xx_cc26xx_pullup(struct device *dev, u32_t pin, u8_t func)
{
ARG_UNUSED(dev);
__ASSERT_NO_MSG(pin < NUM_IO_MAX);
switch (func) {
case PINMUX_PULLUP_ENABLE:
IOCIOPortPullSet(pin, IOC_IOPULL_UP);
return 0;
case PINMUX_PULLUP_DISABLE:
IOCIOPortPullSet(pin, IOC_NO_IOPULL);
return 0;
};
return -EINVAL;
}
static int pinmux_cc13xx_cc26xx_input(struct device *dev, u32_t pin, u8_t func)
{
ARG_UNUSED(dev);
__ASSERT_NO_MSG(pin < NUM_IO_MAX);
switch (func) {
case PINMUX_INPUT_ENABLED:
IOCIOInputSet(pin, IOC_INPUT_ENABLE);
return 0;
case PINMUX_OUTPUT_ENABLED:
IOCIOInputSet(pin, IOC_INPUT_DISABLE);
return 0;
};
return -EINVAL;
}
static int pinmux_cc13xx_cc26xx_init(struct device *dev)
{
ARG_UNUSED(dev);
return 0;
}
static const struct pinmux_driver_api pinmux_cc13xx_cc26xx_driver_api = {
.set = pinmux_cc13xx_cc26xx_set,
.get = pinmux_cc13xx_cc26xx_get,
.pullup = pinmux_cc13xx_cc26xx_pullup,
.input = pinmux_cc13xx_cc26xx_input,
};
DEVICE_AND_API_INIT(pinmux_cc13xx_cc26xx, CONFIG_PINMUX_NAME,
&pinmux_cc13xx_cc26xx_init, NULL, NULL, PRE_KERNEL_1,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&pinmux_cc13xx_cc26xx_driver_api);

View file

@ -3,6 +3,7 @@
zephyr_library()
zephyr_library_sources_ifdef(CONFIG_UART_ALTERA_JTAG uart_altera_jtag_hal.c)
zephyr_library_sources_if_kconfig(uart_imx.c)
zephyr_library_sources_if_kconfig(uart_cc13xx_cc26xx.c)
zephyr_library_sources_if_kconfig(uart_cc32xx.c)
zephyr_library_sources_if_kconfig(uart_cmsdk_apb.c)
zephyr_library_sources_if_kconfig(uart_esp32.c)

View file

@ -92,6 +92,8 @@ source "drivers/serial/Kconfig.nrfx"
source "drivers/serial/Kconfig.altera_jtag"
source "drivers/serial/Kconfig.cc13xx_cc26xx"
source "drivers/serial/Kconfig.cc32xx"
source "drivers/serial/Kconfig.cmsdk_apb"

View file

@ -0,0 +1,29 @@
# Kconfig.cc13xx_cc26xx - TI CC13xx / CC26xx UART configuration options
#
# Copyright (c) 2019 Brett Witherspoon
#
# SPDX-License-Identifier: Apache-2.0
#
menuconfig UART_CC13XX_CC26XX
bool "TI SimpleLink CC13xx / CC26xx UART driver"
depends on SOC_SERIES_CC13X2_CC26X2
select SERIAL_HAS_DRIVER
select SERIAL_SUPPORT_INTERRUPT
help
Enable the TI SimpleLink CC13xx / CC26xx UART driver.
if UART_CC13XX_CC26XX
config UART_CC13XX_CC26XX_0
bool "UART 0"
default y
help
Enable UART 0.
config UART_CC13XX_CC26XX_1
bool "UART 1"
help
Enable UART 1.
endif # UART_CC13XX_CC26XX

View file

@ -0,0 +1,464 @@
/*
* Copyright (c) 2019 Brett Witherspoon
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <device.h>
#include <errno.h>
#include <misc/__assert.h>
#include <uart.h>
#include <driverlib/ioc.h>
#include <driverlib/prcm.h>
#include <driverlib/uart.h>
struct uart_cc13xx_cc26xx_data {
struct uart_config uart_config;
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
uart_irq_callback_user_data_t callback;
void *user_data;
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
};
#ifdef CONFIG_UART_CC13XX_CC26XX_0
DEVICE_DECLARE(uart_cc13xx_cc26xx_0);
#endif /* CONFIG_UART_CC13XX_CC26XX_0 */
#ifdef CONFIG_UART_CC13XX_CC26XX_1
DEVICE_DECLARE(uart_cc13xx_cc26xx_1);
#endif /* CONFIG_UART_CC13XX_CC26XX_1 */
static inline struct uart_cc13xx_cc26xx_data *get_dev_data(struct device *dev)
{
return dev->driver_data;
}
static inline const struct uart_device_config *get_dev_conf(struct device *dev)
{
return dev->config->config_info;
}
static int uart_cc13xx_cc26xx_poll_in(struct device *dev, unsigned char *c)
{
if (!UARTCharsAvail(get_dev_conf(dev)->regs)) {
return -1;
}
*c = UARTCharGetNonBlocking(get_dev_conf(dev)->regs);
return 0;
}
static void uart_cc13xx_cc26xx_poll_out(struct device *dev, unsigned char c)
{
UARTCharPut(get_dev_conf(dev)->regs, c);
}
static int uart_cc13xx_cc26xx_err_check(struct device *dev)
{
u32_t flags = UARTRxErrorGet(get_dev_conf(dev)->regs);
int error = (flags & UART_RXERROR_FRAMING ? UART_ERROR_FRAMING : 0) |
(flags & UART_RXERROR_PARITY ? UART_ERROR_PARITY : 0) |
(flags & UART_RXERROR_BREAK ? UART_BREAK : 0) |
(flags & UART_RXERROR_OVERRUN ? UART_ERROR_OVERRUN : 0);
UARTRxErrorClear(get_dev_conf(dev)->regs);
return error;
}
static int uart_cc13xx_cc26xx_configure(struct device *dev,
const struct uart_config *cfg)
{
u32_t line_ctrl = 0;
bool flow_ctrl;
switch (cfg->parity) {
case UART_CFG_PARITY_NONE:
line_ctrl |= UART_CONFIG_PAR_NONE;
break;
case UART_CFG_PARITY_ODD:
line_ctrl |= UART_CONFIG_PAR_ODD;
break;
case UART_CFG_PARITY_EVEN:
line_ctrl |= UART_CONFIG_PAR_EVEN;
break;
case UART_CFG_PARITY_MARK:
line_ctrl |= UART_CONFIG_PAR_ONE;
break;
case UART_CFG_PARITY_SPACE:
line_ctrl |= UART_CONFIG_PAR_ZERO;
break;
default:
return -EINVAL;
}
switch (cfg->stop_bits) {
case UART_CFG_STOP_BITS_1:
line_ctrl |= UART_CONFIG_STOP_ONE;
break;
case UART_CFG_STOP_BITS_2:
line_ctrl |= UART_CONFIG_STOP_TWO;
break;
case UART_CFG_STOP_BITS_0_5:
case UART_CFG_STOP_BITS_1_5:
return -ENOTSUP;
default:
return -EINVAL;
}
switch (cfg->data_bits) {
case UART_CFG_DATA_BITS_5:
line_ctrl |= UART_CONFIG_WLEN_5;
break;
case UART_CFG_DATA_BITS_6:
line_ctrl |= UART_CONFIG_WLEN_6;
break;
case UART_CFG_DATA_BITS_7:
line_ctrl |= UART_CONFIG_WLEN_7;
break;
case UART_CFG_DATA_BITS_8:
line_ctrl |= UART_CONFIG_WLEN_8;
break;
default:
return -EINVAL;
}
switch (cfg->flow_ctrl) {
case UART_CFG_FLOW_CTRL_NONE:
flow_ctrl = false;
break;
case UART_CFG_FLOW_CTRL_RTS_CTS:
flow_ctrl = true;
break;
case UART_CFG_FLOW_CTRL_DTR_DSR:
return -ENOTSUP;
default:
return -EINVAL;
}
/* Disables UART before setting control registers */
UARTConfigSetExpClk(get_dev_conf(dev)->regs,
get_dev_conf(dev)->sys_clk_freq, cfg->baudrate,
line_ctrl);
if (flow_ctrl) {
UARTHwFlowControlEnable(get_dev_conf(dev)->regs);
} else {
UARTHwFlowControlDisable(get_dev_conf(dev)->regs);
}
/* Re-enable UART */
UARTEnable(get_dev_conf(dev)->regs);
/* Disabled FIFOs act as 1-byte-deep holding registers (character mode) */
UARTFIFODisable(get_dev_conf(dev)->regs);
get_dev_data(dev)->uart_config = *cfg;
return 0;
}
static int uart_cc13xx_cc26xx_config_get(struct device *dev,
struct uart_config *cfg)
{
*cfg = get_dev_data(dev)->uart_config;
return 0;
}
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
static int uart_cc13xx_cc26xx_fifo_fill(struct device *dev, const u8_t *buf,
int len)
{
int n = 0;
while (n < len) {
if (!UARTCharPutNonBlocking(get_dev_conf(dev)->regs, buf[n])) {
break;
}
n++;
}
return n;
}
static int uart_cc13xx_cc26xx_fifo_read(struct device *dev, u8_t *buf,
const int len)
{
int c, n;
n = 0;
while (n < len) {
c = UARTCharGetNonBlocking(get_dev_conf(dev)->regs);
if (c == -1) {
break;
}
buf[n++] = c;
}
return n;
}
static void uart_cc13xx_cc26xx_irq_tx_enable(struct device *dev)
{
UARTIntEnable(get_dev_conf(dev)->regs, UART_INT_TX);
}
static void uart_cc13xx_cc26xx_irq_tx_disable(struct device *dev)
{
UARTIntDisable(get_dev_conf(dev)->regs, UART_INT_TX);
}
static int uart_cc13xx_cc26xx_irq_tx_ready(struct device *dev)
{
return UARTSpaceAvail(get_dev_conf(dev)->regs) ? 1 : 0;
}
static void uart_cc13xx_cc26xx_irq_rx_enable(struct device *dev)
{
UARTIntEnable(get_dev_conf(dev)->regs, UART_INT_RX);
}
static void uart_cc13xx_cc26xx_irq_rx_disable(struct device *dev)
{
UARTIntDisable(get_dev_conf(dev)->regs, UART_INT_RX);
}
static int uart_cc13xx_cc26xx_irq_tx_complete(struct device *dev)
{
return UARTBusy(get_dev_conf(dev)->regs) ? 0 : 1;
}
static int uart_cc13xx_cc26xx_irq_rx_ready(struct device *dev)
{
return UARTCharsAvail(get_dev_conf(dev)->regs) ? 1 : 0;
}
static void uart_cc13xx_cc26xx_irq_err_enable(struct device *dev)
{
return UARTIntEnable(get_dev_conf(dev)->regs,
UART_INT_OE | UART_INT_BE | UART_INT_PE |
UART_INT_FE);
}
static void uart_cc13xx_cc26xx_irq_err_disable(struct device *dev)
{
return UARTIntDisable(get_dev_conf(dev)->regs,
UART_INT_OE | UART_INT_BE | UART_INT_PE |
UART_INT_FE);
}
static int uart_cc13xx_cc26xx_irq_is_pending(struct device *dev)
{
u32_t status = UARTIntStatus(get_dev_conf(dev)->regs, true);
return status & (UART_INT_TX | UART_INT_RX) ? 1 : 0;
}
static int uart_cc13xx_cc26xx_irq_update(struct device *dev)
{
ARG_UNUSED(dev);
return 1;
}
static void uart_cc13xx_cc26xx_irq_callback_set(
struct device *dev, uart_irq_callback_user_data_t cb, void *user_data)
{
struct uart_cc13xx_cc26xx_data *data = get_dev_data(dev);
data->callback = cb;
data->user_data = user_data;
}
static void uart_cc13xx_cc26xx_isr(void *arg)
{
struct uart_cc13xx_cc26xx_data *data = get_dev_data(arg);
if (data->callback) {
data->callback(data->user_data);
}
}
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
static const struct uart_driver_api uart_cc13xx_cc26xx_driver_api = {
.poll_in = uart_cc13xx_cc26xx_poll_in,
.poll_out = uart_cc13xx_cc26xx_poll_out,
.err_check = uart_cc13xx_cc26xx_err_check,
.configure = uart_cc13xx_cc26xx_configure,
.config_get = uart_cc13xx_cc26xx_config_get,
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
.fifo_fill = uart_cc13xx_cc26xx_fifo_fill,
.fifo_read = uart_cc13xx_cc26xx_fifo_read,
.irq_tx_enable = uart_cc13xx_cc26xx_irq_tx_enable,
.irq_tx_disable = uart_cc13xx_cc26xx_irq_tx_disable,
.irq_tx_ready = uart_cc13xx_cc26xx_irq_tx_ready,
.irq_rx_enable = uart_cc13xx_cc26xx_irq_rx_enable,
.irq_rx_disable = uart_cc13xx_cc26xx_irq_rx_disable,
.irq_tx_complete = uart_cc13xx_cc26xx_irq_tx_complete,
.irq_rx_ready = uart_cc13xx_cc26xx_irq_rx_ready,
.irq_err_enable = uart_cc13xx_cc26xx_irq_err_enable,
.irq_err_disable = uart_cc13xx_cc26xx_irq_err_disable,
.irq_is_pending = uart_cc13xx_cc26xx_irq_is_pending,
.irq_update = uart_cc13xx_cc26xx_irq_update,
.irq_callback_set = uart_cc13xx_cc26xx_irq_callback_set,
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
};
#ifdef CONFIG_UART_CC13XX_CC26XX_0
static int uart_cc13xx_cc26xx_init_0(struct device *dev)
{
int ret;
/* Enable UART power domain */
PRCMPowerDomainOn(PRCM_DOMAIN_SERIAL);
/* Enable UART peripherals */
PRCMPeripheralRunEnable(PRCM_PERIPH_UART0);
PRCMPeripheralSleepEnable(PRCM_PERIPH_UART0);
/* Load PRCM settings */
PRCMLoadSet();
while (!PRCMLoadGet()) {
continue;
}
/* UART should not be accessed until power domain is on. */
while (PRCMPowerDomainStatus(PRCM_DOMAIN_SERIAL) !=
PRCM_DOMAIN_POWER_ON) {
continue;
}
/* Configure IOC module to map UART signals to pins */
IOCPortConfigureSet(DT_TI_CC13XX_CC26XX_UART_40001000_TX_PIN,
IOC_PORT_MCU_UART0_TX, IOC_STD_OUTPUT);
IOCPortConfigureSet(DT_TI_CC13XX_CC26XX_UART_40001000_RX_PIN,
IOC_PORT_MCU_UART0_RX, IOC_STD_INPUT);
/* Configure and enable UART */
ret = uart_cc13xx_cc26xx_configure(dev,
&get_dev_data(dev)->uart_config);
/* Enable interrupts */
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
UARTIntClear(get_dev_conf(dev)->regs, UART_INT_RX);
IRQ_CONNECT(DT_TI_CC13XX_CC26XX_UART_40001000_IRQ_0,
DT_TI_CC13XX_CC26XX_UART_40001000_IRQ_0_PRIORITY,
uart_cc13xx_cc26xx_isr, DEVICE_GET(uart_cc13xx_cc26xx_0),
0);
irq_enable(DT_TI_CC13XX_CC26XX_UART_40001000_IRQ_0);
/* Causes an initial TX ready interrupt when TX interrupt is enabled */
UARTCharPutNonBlocking(get_dev_conf(dev)->regs, '\0');
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
return ret;
}
static const struct uart_device_config uart_cc13xx_cc26xx_config_0 = {
.regs = DT_TI_CC13XX_CC26XX_UART_40001000_BASE_ADDRESS,
.sys_clk_freq = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC,
};
static struct uart_cc13xx_cc26xx_data uart_cc13xx_cc26xx_data_0 = {
.uart_config = {
.baudrate = DT_TI_CC13XX_CC26XX_UART_40001000_CURRENT_SPEED,
.parity = UART_CFG_PARITY_NONE,
.stop_bits = UART_CFG_STOP_BITS_1,
.data_bits = UART_CFG_DATA_BITS_8,
.flow_ctrl = UART_CFG_FLOW_CTRL_NONE,
},
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
.callback = NULL,
.user_data = NULL,
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
};
DEVICE_AND_API_INIT(uart_cc13xx_cc26xx_0,
DT_TI_CC13XX_CC26XX_UART_40001000_LABEL,
uart_cc13xx_cc26xx_init_0, &uart_cc13xx_cc26xx_data_0,
&uart_cc13xx_cc26xx_config_0, PRE_KERNEL_1,
CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
&uart_cc13xx_cc26xx_driver_api);
#endif /* CONFIG_UART_CC13XX_CC26XX_0 */
#ifdef CONFIG_UART_CC13XX_CC26XX_1
static int uart_cc13xx_cc26xx_init_1(struct device *dev)
{
int ret;
/* Enable UART power domain */
PRCMPowerDomainOn(PRCM_DOMAIN_PERIPH);
/* Enable UART peripherals */
PRCMPeripheralRunEnable(PRCM_PERIPH_UART1);
/* Load PRCM settings */
PRCMLoadSet();
while (!PRCMLoadGet()) {
continue;
}
/* UART should not be accessed until power domain is on. */
while (PRCMPowerDomainStatus(PRCM_DOMAIN_PERIPH) !=
PRCM_DOMAIN_POWER_ON) {
continue;
}
/* Configure IOC module to map UART signals to pins */
IOCPortConfigureSet(DT_TI_CC13XX_CC26XX_UART_4000B000_TX_PIN,
IOC_PORT_MCU_UART1_TX, IOC_STD_OUTPUT);
IOCPortConfigureSet(DT_TI_CC13XX_CC26XX_UART_4000B000_RX_PIN,
IOC_PORT_MCU_UART1_RX, IOC_STD_INPUT);
/* Configure and enable UART */
ret = uart_cc13xx_cc26xx_configure(dev,
&get_dev_data(dev)->uart_config);
/* Enable interrupts */
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
UARTIntClear(get_dev_conf(dev)->regs, UART_INT_RX);
IRQ_CONNECT(DT_TI_CC13XX_CC26XX_UART_4000B000_IRQ_0,
DT_TI_CC13XX_CC26XX_UART_4000B000_IRQ_0_PRIORITY,
uart_cc13xx_cc26xx_isr, DEVICE_GET(uart_cc13xx_cc26xx_1),
0);
irq_enable(DT_TI_CC13XX_CC26XX_UART_4000B000_IRQ_0);
/* Causes an initial TX ready interrupt when TX interrupt is enabled */
UARTCharPutNonBlocking(get_dev_conf(dev)->regs, '\0');
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
return ret;
}
static const struct uart_device_config uart_cc13xx_cc26xx_config_1 = {
.regs = DT_TI_CC13XX_CC26XX_UART_4000B000_BASE_ADDRESS,
.sys_clk_freq = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC,
};
static struct uart_cc13xx_cc26xx_data uart_cc13xx_cc26xx_data_1 = {
.uart_config = {
.baudrate = DT_TI_CC13XX_CC26XX_UART_4000B000_CURRENT_SPEED,
.parity = UART_CFG_PARITY_NONE,
.stop_bits = UART_CFG_STOP_BITS_1,
.data_bits = UART_CFG_DATA_BITS_8,
.flow_ctrl = UART_CFG_FLOW_CTRL_NONE,
},
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
.callback = NULL,
.user_data = NULL,
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
};
DEVICE_AND_API_INIT(uart_cc13xx_cc26xx_1,
DT_TI_CC13XX_CC26XX_UART_4000B000_LABEL,
uart_cc13xx_cc26xx_init_1, &uart_cc13xx_cc26xx_data_1,
&uart_cc13xx_cc26xx_config_1, POST_KERNEL,
CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
&uart_cc13xx_cc26xx_driver_api);
#endif /* CONFIG_UART_CC13XX_CC26XX_1 */

18
dts/arm/ti/cc1352r.dtsi Normal file
View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2019 Brett Witherspoon
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <mem.h>
#include <ti/cc13x2_cc26x2.dtsi>
/ {
sram0: memory@20000000 {
reg = <0x20000000 DT_SIZE_K(80)>;
};
flash0: serial-flash@0 {
reg = <0x0 DT_SIZE_K(352)>;
};
};

View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2019 Brett Witherspoon
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <arm/armv7-m.dtsi>
#include <dt-bindings/gpio/gpio.h>
/ {
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-m4";
reg = <0>;
};
};
sram0: memory@20000000 {
device_type = "memory";
compatible = "mmio-sram";
};
/* VIMS RAM configurable in CCFG as GPRAM or cache for FLASH (default) */
sram1: memory@11000000 {
device_type = "memory";
compatible = "mmio-sram";
reg = <0x11000000 0x2000>;
};
flash0: serial-flash@0 {
compatible = "serial-flash";
};
soc {
pinmux: pinmux@40081000 {
compatible = "ti,cc13xx-cc26xx-pinmux";
reg = <0x40081000 0x1000>;
label = "PINMUX";
};
gpio0: gpio@40022000 {
compatible = "ti,cc13xx-cc26xx-gpio";
reg = <0x40022000 0x400>;
interrupts = <0 0>;
status = "disabled";
label = "GPIO_0";
gpio-controller;
#gpio-cells = <2>;
};
uart0: uart@40001000 {
compatible = "ti,cc13xx-cc26xx-uart";
reg = <0x40001000 0x1000>;
interrupts = <5 0>;
status = "disabled";
label = "UART_0";
};
uart1: uart@4000b000 {
compatible = "ti,cc13xx-cc26xx-uart";
reg = <0x4000b000 0x1000>;
interrupts = <36 0>;
status = "disabled";
label = "UART_1";
};
};
};
&nvic {
arm,num-irq-priority-bits = <3>;
};

18
dts/arm/ti/cc2652r.dtsi Normal file
View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2019 Brett Witherspoon
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <mem.h>
#include <ti/cc13x2_cc26x2.dtsi>
/ {
sram0: memory@20000000 {
reg = <0x20000000 DT_SIZE_K(80)>;
};
flash0: serial-flash@0 {
reg = <0x0 DT_SIZE_K(352)>;
};
};

View file

@ -0,0 +1,44 @@
#
# Copyright (c) 2019 Brett Witherspoon
#
# SPDX-License-Identifier: Apache-2.0
#
---
title: TI SimpleLink CC13xx / CC26xx GPIO
version: 0.1
description: >
This is a representation of the TI SimpleLink CC13xx / CC26xx GPIO node
properties:
compatible:
type: string
category: required
description: compatible strings
constraint: "ti,cc13xx-cc26xx-gpio"
generation: define
reg:
type: int
category: required
description: mmio register space
generation: define
interrupts:
type: compound
category: required
description: required interrupts
generation: define
label:
type: string
category: required
description: Human readable string describing the device (used by Zephyr for API name)
generation: define
cell_string: GPIO
"#cells":
- pin
- flags
...

View file

@ -0,0 +1,32 @@
#
# Copyright (c) 2019 Brett Witherspoon
#
# SPDX-License-Identifier: Apache-2.0
#
---
title: TI SimpleLink CC13xx / CC26xx Pinmux
version: 0.1
description: >
This is a representation of the TI SimpleLink CC13xx / CC26xx pinmux node
properties:
compatible:
type: string
category: required
description: compatible strings
constraint: "ti,cc13xx-cc26xx-pinmux"
generation: define
reg:
type: int
description: mmio register space
generation: define
category: required
label:
type: string
category: required
description: Human readable string describing the device (used by Zephyr for API name)
generation: define
...

View file

@ -0,0 +1,43 @@
#
# Copyright (c) 2019 Brett Witherspoon
#
# SPDX-License-Identifier: Apache-2.0
#
---
title: TI SimpleLink CC13xx / CC26xx UART
version: 0.1
description: >
This is a representation of the TI SimpleLink CC13xx / CC26xx UART node
inherits:
!include uart.yaml
properties:
compatible:
constraint: "ti,cc13xx-cc26xx-uart"
reg:
type: array
description: mmio register space
generation: define
category: required
interrupts:
type: array
category: required
description: required interrupts
generation: define
tx-pin:
type: int
category: required
description: TX pin
generation: define
rx-pin:
type: int
category: required
description: RX pin
generation: define
...

View file

@ -3,3 +3,14 @@
zephyr_include_directories(
.
)
zephyr_library()
zephyr_library_compile_definitions(${COMPILER})
zephyr_library_sources(
# Required for SystemTrimDevice which is not in ROM
driverlib/setup.c
driverlib/chipinfo.c
driverlib/aux_sysif.c
# Required for default CCFG confguration
startup_files/ccfg.c
)

View file

@ -0,0 +1,5 @@
# Copyright (c) 2019 Brett Witherspoon
#
# SPDX-License-Identifier: Apache-2.0
zephyr_sources(soc.c)

View file

@ -0,0 +1,14 @@
# Kconfig.defconfig.cc1352r - Texas Instruments SimpleLink CC1352R
#
# Copyright (c) 2019 Brett Witherspoon
#
# SPDX-License-Identifier: Apache-2.0
#
if SOC_CC1352R
config SOC
string
default "cc1352r"
endif # SOC_CC1352R

View file

@ -0,0 +1,14 @@
# Kconfig.defconfig.cc2652r - Texas Instruments SimpleLink CC2652R
#
# Copyright (c) 2019 Brett Witherspoon
#
# SPDX-License-Identifier: Apache-2.0
#
if SOC_CC2652R
config SOC
string
default "cc2652r"
endif # SOC_CC2652R

View file

@ -0,0 +1,49 @@
# Kconfig.defconfig.series - Texas Instruments SimpleLink CC13x2 / CC26x2
#
# Copyright (c) 2019 Brett Witherspoon
#
# SPDX-License-Identifier: Apache-2.0
#
if SOC_SERIES_CC13X2_CC26X2
source "soc/arm/ti_simplelink/cc13x2_cc26x2/Kconfig.defconfig.cc*"
config SOC_SERIES
string
default "cc13x2_cc26x2"
config SYS_CLOCK_HW_CYCLES_PER_SEC
int
default 48000000
config NUM_IRQS
int
default 38
config TI_CCFG_PRESENT
bool
default y
if PINMUX
config PINMUX_CC13XX_CC26XX
default y
endif # PINMUX
if GPIO
config GPIO_CC13XX_CC26XX
default y
endif # GPIO
if SERIAL
config UART_CC13XX_CC26XX
default y
endif # SERIAL
endif # SOC_SERIES_CC13X2_CC26X2

View file

@ -0,0 +1,16 @@
# Kconfig.series - Texas Instruments SimpleLink CC13x2 / CC26x2
#
# Copyright (c) 2019 Brett Witherspoon
#
# SPDX-License-Identifier: Apache-2.0
#
config SOC_SERIES_CC13X2_CC26X2
bool "TI SimpleLink Family CC13x2 / CC26x2"
select CPU_CORTEX_M4
select CPU_CORTEX_M_HAS_SYSTICK
select CPU_HAS_FPU
select SOC_FAMILY_TISIMPLELINK
select HAS_CC13X2_CC26X2_SDK
help
Enable support for TI SimpleLink CC13x2 / CC26x2 SoCs

View file

@ -0,0 +1,18 @@
# Kconfig.soc - Texas Instruments SimpleLink CC13x2 / CC26x2
#
# Copyright (c) 2019 Brett Witherspoon
#
# SPDX-License-Identifier: Apache-2.0
#
choice
prompt "TI SimpleLink MCU Selection"
depends on SOC_SERIES_CC13X2_CC26X2
config SOC_CC2652R
bool "CC2652R"
config SOC_CC1352R
bool "CC1352R"
endchoice

View file

@ -0,0 +1,11 @@
/*
* Copyright (c) 2019 Brett Witherspoon
*
* SPDX-License-Identifier: Apache-2.0
*/
/* SoC level DTS fixup file */
#define DT_NUM_IRQ_PRIO_BITS DT_ARM_V7M_NVIC_E000E100_ARM_NUM_IRQ_PRIORITY_BITS
/* End of SoC Level DTS fixup file */

View file

@ -0,0 +1,8 @@
/* linker.ld - Linker command/script file
*
* Copyright (c) 2019 Brett Witherspoon
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <arch/arm/cortex_m/scripts/linker.ld>

View file

@ -0,0 +1,21 @@
/*
* Copyright (c) 2019 Brett Witherspoon
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <init.h>
#include <driverlib/setup.h>
static int ti_cc13x2_cc26x2_init(struct device *dev)
{
ARG_UNUSED(dev);
/* Performs necessary trim of the device. */
SetupTrimDevice();
return 0;
}
SYS_INIT(ti_cc13x2_cc26x2_init, PRE_KERNEL_1, 0);

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2019 Brett Witherspoon
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef TI_SIMPLELINK_CC13X2_CC26X2_SOC_H_
#define TI_SIMPLELINK_CC13X2_CC26X2_SOC_H_
/* CMSIS required values */
typedef enum {
Reset_IRQn = -15,
NonMaskableInt_IRQn = -14,
HardFault_IRQn = -13,
MemoryManagement_IRQn = -12,
BusFault_IRQn = -11,
UsageFault_IRQn = -10,
SVCall_IRQn = -5,
DebugMonitor_IRQn = -4,
PendSV_IRQn = -2,
SysTick_IRQn = -1,
} IRQn_Type;
#define __CM4_REV 0
#define __MPU_PRESENT 1
#define __NVIC_PRIO_BITS DT_NUM_IRQ_PRIO_BITS
#define __Vendor_SysTickConfig 0
#define __FPU_PRESENT 1
#endif /* TI_SIMPLELINK_CC13X2_CC26X2_SOC_H_ */