diff --git a/drivers/pinmux/Kconfig b/drivers/pinmux/Kconfig index a9f9062fe1a..8f6b5348b4e 100644 --- a/drivers/pinmux/Kconfig +++ b/drivers/pinmux/Kconfig @@ -54,4 +54,6 @@ source "drivers/pinmux/Kconfig.beetle" source "drivers/pinmux/Kconfig.fe310" +source "drivers/pinmux/Kconfig.cc2650" + endif # PINMUX diff --git a/drivers/pinmux/Kconfig.cc2650 b/drivers/pinmux/Kconfig.cc2650 new file mode 100644 index 00000000000..db7b85a79f9 --- /dev/null +++ b/drivers/pinmux/Kconfig.cc2650 @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Kconfig for TI CC2650 SoC pinmux driver. + +config PINMUX_CC2650 + bool "Pinmux driver for CC2650 SoC" + depends on PINMUX && SOC_SERIES_CC2650 + select GPIO + select GPIO_CC2650 + help + Enable pin multiplexer for CC2650 SoC. + + For hardware reasons, the pinmux depends on the GPIO module + being activated; it must initialize *before* the pinmux does. + Please take care that the pinmux init priority value is *lower* + that the GPIO driver init priority. diff --git a/drivers/pinmux/Makefile b/drivers/pinmux/Makefile index 717eac16db4..2d5c2ebdf7e 100644 --- a/drivers/pinmux/Makefile +++ b/drivers/pinmux/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_BOARD_OLIMEXINO_STM32) += stm32/pinmux_board_olimexino_stm32.o obj-$(CONFIG_BOARD_STM32_MINI_A15) += stm32/pinmux_board_stm32_mini_a15.o obj-$(CONFIG_PINMUX_QMSI) += pinmux_qmsi.o obj-$(CONFIG_PINMUX_FE310) += pinmux_fe310.o +obj-$(CONFIG_PINMUX_CC2650) += pinmux_cc2650.o # "runtime" pinmux obj-$(CONFIG_PINMUX_DEV) += dev/ diff --git a/drivers/pinmux/pinmux_cc2650.c b/drivers/pinmux/pinmux_cc2650.c new file mode 100644 index 00000000000..64d89c8b13b --- /dev/null +++ b/drivers/pinmux/pinmux_cc2650.c @@ -0,0 +1,155 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Driver for the I/O controller (pinmux) for + * Texas Instrument's CC2650 SoC. + * + * For these SoCs, available pin functions are as follows: + * + * 0x00 - GPIO + * 0x07 - AON 32 Khz clock + * 0x08 - AUX IO + * 0x09 - SSI0 RX + * 0x0A - SSI0 TX + * 0x0B - SSI0 FSS + * 0x0C - SSI0 CLK + * 0x0D - I2C SDA + * 0x0E - I2C SCL + * 0x0F - UART0 RX + * 0x10 - UART0 TX + * 0x11 - UART0 CTS + * 0x12 - UART0 RTS + * 0x17 - Port event 0 + * 0x18 - Port event 1 + * 0x19 - Port event 2 + * 0x1A - Port event 3 + * 0x1B - Port event 4 + * 0x1C - Port event 5 + * 0x1D - Port event 6 + * 0x1E - Port event 7 + * 0x20 - CPU SWV + * 0x21 - SSI1 RX + * 0x22 - SSI1 TX + * 0x23 - SSI1 FSS + * 0x24 - SSI1 CLK + * 0x25 - I2S data 0 + * 0x26 - I2S data 1 + * 0x27 - I2S WCLK + * 0x28 - I2S BCLK + * 0x29 - I2S MCLK + * 0x2E - RF Core Trace + * 0x2F - RF Core data out 0 + * 0x30 - RF Core data out 1 + * 0x31 - RF Core data out 2 + * 0x32 - RF Core data out 3 + * 0x33 - RF Core data in 0 + * 0x34 - RF Core data in 1 + * 0x35 - RF Core SMI data link out + * 0x36 - RF Core SMI data link in + * 0x37 - RF Core SMI command link out + * 0x38 - RF Core SMI command link in + */ + +#include +#include +#include +#include +#include +#include +#include + + +#define IOCFG_REG(Func) \ + REG_ADDR(TI_CC2650_PINMUX_40081000_BASE_ADDRESS, \ + CC2650_IOC_IOCFG0 + 0x4 * Func) + +static int pinmux_cc2650_init(struct device *dev) +{ + /* Do nothing */ + ARG_UNUSED(dev); + return 0; +} + +static int pinmux_cc2650_set(struct device *dev, u32_t pin, + u32_t func) +{ + const u32_t iocfg = IOCFG_REG(pin); + u32_t conf = sys_read32(iocfg); + + conf &= ~CC2650_IOC_IOCFGX_PORT_ID_MASK; + conf |= func & CC2650_IOC_IOCFGX_PORT_ID_MASK; + sys_write32(conf, iocfg); + + return 0; +}; + +static int pinmux_cc2650_get(struct device *dev, u32_t pin, + u32_t *func) +{ + const u32_t iocfg = IOCFG_REG(pin); + u32_t conf = sys_read32(iocfg); + + *func = conf & CC2650_IOC_IOCFGX_PORT_ID_MASK; + return 0; +} + +static int pinmux_cc2650_pullup(struct device *dev, u32_t pin, + u8_t func) +{ + __ASSERT((func == PINMUX_PULLUP_ENABLE) | + (func == PINMUX_PULLUP_DISABLE), + "Pullup mode is invalid"); + + const u32_t iocfg = IOCFG_REG(pin); + u32_t conf = sys_read32(iocfg); + + conf &= ~CC2650_IOC_IOCFGX_PULL_CTL_MASK; + if (func == PINMUX_PULLUP_ENABLE) { + conf |= CC2650_IOC_PULL_UP; + } else { + conf |= CC2650_IOC_NO_PULL; + } + sys_write32(conf, iocfg); + + return 0; +} + +static int pinmux_cc2650_input(struct device *dev, u32_t pin, + u8_t func) +{ + __ASSERT((func == PINMUX_INPUT_ENABLED) | + (func == PINMUX_OUTPUT_ENABLED), + "I/O mode is invalid"); + + const u32_t iocfg = IOCFG_REG(pin); + const u32_t gpio_doe = TI_CC2650_GPIO_40022000_BASE_ADDRESS + + CC2650_GPIO_DOE31_0; + u32_t iocfg_conf = sys_read32(iocfg); + u32_t gpio_doe_conf = sys_read32(gpio_doe); + + iocfg_conf &= ~CC2650_IOC_IOCFGX_IE_MASK; + if (func == PINMUX_INPUT_ENABLED) { + iocfg_conf |= CC2650_IOC_INPUT_ENABLED; + gpio_doe_conf &= ~BIT(pin); + } else { + iocfg_conf |= CC2650_IOC_INPUT_DISABLED; + gpio_doe_conf |= BIT(pin); + } + sys_write32(iocfg_conf, iocfg); + sys_write32(gpio_doe_conf, gpio_doe); + + return 0; + +} + +const struct pinmux_driver_api pinmux_cc2650_funcs = { + .set = pinmux_cc2650_set, + .get = pinmux_cc2650_get, + .pullup = pinmux_cc2650_pullup, + .input = pinmux_cc2650_input +}; + +DEVICE_AND_API_INIT(pinmux_cc2650_0, CONFIG_PINMUX_NAME, + pinmux_cc2650_init, NULL, NULL, + PRE_KERNEL_1, CONFIG_PINMUX_INIT_PRIORITY, + &pinmux_cc2650_funcs); diff --git a/dts/arm/yaml/ti,cc2650-pinmux.yaml b/dts/arm/yaml/ti,cc2650-pinmux.yaml new file mode 100644 index 00000000000..e18362e403a --- /dev/null +++ b/dts/arm/yaml/ti,cc2650-pinmux.yaml @@ -0,0 +1,27 @@ +--- +# SPDX-License-Identifier: Apache-2.0 +title: TI CC2650 Pinmux +version: 0.1 + +description: > + This is a representation of the TI CC2650 pinmux node + +properties: + - compatible: + type: string + category: required + description: compatible strings + constraint: "ti,cc2650-pinmux" + + - reg: + type: int + description: mmio register space + generation: define + category: required + +cell_string: PINMUX + +"#cells": + - pin + - function +...