From edd6c7df4132a1497685ba9026d6cb2374f01c60 Mon Sep 17 00:00:00 2001 From: Nazar Chornenkyy Date: Thu, 28 Jun 2018 15:20:16 -0500 Subject: [PATCH] drivers: serial: Add Cypress PSoC6 UART driver Added basic PSoC6 UART driver and added two UART nodes in the PSoC6 device tree to have output from CM0+ and CM4 cores. Signed-off-by: Nazar Chornenkyy Signed-off-by: Oleg Kapshii --- drivers/serial/CMakeLists.txt | 1 + drivers/serial/Kconfig | 2 + drivers/serial/Kconfig.psoc6 | 25 +++ drivers/serial/uart_psoc6.c | 171 ++++++++++++++++++++ dts/bindings/serial/cypress,psoc6-uart.yaml | 32 ++++ 5 files changed, 231 insertions(+) create mode 100644 drivers/serial/Kconfig.psoc6 create mode 100644 drivers/serial/uart_psoc6.c create mode 100644 dts/bindings/serial/cypress,psoc6-uart.yaml diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index 3bc2c2fbc42c43..fde8f643b06e09 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -23,5 +23,6 @@ zephyr_library_sources_if_kconfig(uart_stellaris.c) zephyr_library_sources_if_kconfig(uart_stm32.c) zephyr_library_sources_if_kconfig(uart_sam0.c) zephyr_library_sources_if_kconfig(usart_mcux_lpc.c) +zephyr_library_sources_if_kconfig(uart_psoc6.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE uart_handlers.c) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 65b97833876248..540141167d7e09 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -101,4 +101,6 @@ source "drivers/serial/Kconfig.msp432p4xx" source "drivers/serial/Kconfig.sam0" +source "drivers/serial/Kconfig.psoc6" + endif diff --git a/drivers/serial/Kconfig.psoc6 b/drivers/serial/Kconfig.psoc6 new file mode 100644 index 00000000000000..2d4340a5ba6aa8 --- /dev/null +++ b/drivers/serial/Kconfig.psoc6 @@ -0,0 +1,25 @@ +# Kconfig - Cypress UART configuration +# +# Copyright (c) 2018 Cypress +# +# SPDX-License-Identifier: Apache-2.0 +# + +menuconfig UART_PSOC6 + bool "PSoC6 MCU serial driver" + select SERIAL_HAS_DRIVER + depends on SOC_FAMILY_PSOC6 + help + This option enables the UART driver for PSoC6 family of processors. + +config UART_PSOC6_UART_5 + bool "Enable PSOC6 SCB6 as UART_5 on Port 5" + depends on UART_PSOC6 + help + Enable support for UART_5 on port 5 in the driver. + +config UART_PSOC6_UART_6 + bool "Enable PSOC6 SCB6 as UART_6 on Port 12" + depends on UART_PSOC6 + help + Enable support for UART_6 on port 12 in the driver. diff --git a/drivers/serial/uart_psoc6.c b/drivers/serial/uart_psoc6.c new file mode 100644 index 00000000000000..6197f39bb75538 --- /dev/null +++ b/drivers/serial/uart_psoc6.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2018 Cypress + * SPDX-License-Identifier: Apache-2.0 + */ + +/** @file + * @brief UART driver for Cypress PSoC6 MCU family. + * + * Note: + * - Error handling is not implemented. + * - The driver works only in polling mode, interrupt mode is not implemented. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "cy_syslib.h" +#include "cy_sysclk.h" +#include "cy_gpio.h" +#include "cy_scb_uart.h" + +/* + * Verify Kconfig configuration + */ + +struct cypress_psoc6_config { + CySCB_Type *base; + GPIO_PRT_Type *port; + u32_t rx_num; + u32_t tx_num; + en_hsiom_sel_t rx_val; + en_hsiom_sel_t tx_val; + en_clk_dst_t scb_clock; +}; + +/* Populate configuration structure */ +static const cy_stc_scb_uart_config_t uartConfig = { + .uartMode = CY_SCB_UART_STANDARD, + .enableMutliProcessorMode = false, + .smartCardRetryOnNack = false, + .irdaInvertRx = false, + .irdaEnableLowPowerReceiver = false, + + .oversample = CONFIG_UART_PSOC6_CONFIG_OVERSAMPLE, + + .enableMsbFirst = false, + .dataWidth = CONFIG_UART_PSOC6_CONFIG_DATAWIDTH, + .parity = CY_SCB_UART_PARITY_NONE, + .stopBits = CY_SCB_UART_STOP_BITS_1, + .enableInputFilter = false, + .breakWidth = CONFIG_UART_PSOC6_CONFIG_BREAKWIDTH, + .dropOnFrameError = false, + .dropOnParityError = false, + + .receiverAddress = 0UL, + .receiverAddressMask = 0UL, + .acceptAddrInFifo = false, + + .enableCts = false, + .ctsPolarity = CY_SCB_UART_ACTIVE_LOW, + .rtsRxFifoLevel = 0UL, + .rtsPolarity = CY_SCB_UART_ACTIVE_LOW, + + .rxFifoTriggerLevel = 0UL, + .rxFifoIntEnableMask = 0UL, + .txFifoTriggerLevel = 0UL, + .txFifoIntEnableMask = 0UL, +}; + +/** + * Function Name: uart_psoc6_init() + * + * Peforms hardware initialization: debug UART. + * + */ +static int uart_psoc6_init(struct device *dev) +{ + const struct cypress_psoc6_config *config = dev->config->config_info; + + /* Connect SCB5 UART function to pins */ + Cy_GPIO_SetHSIOM(config->port, config->rx_num, config->rx_val); + Cy_GPIO_SetHSIOM(config->port, config->tx_num, config->tx_val); + + /* Configure pins for UART operation */ + Cy_GPIO_SetDrivemode(config->port, config->rx_num, CY_GPIO_DM_HIGHZ); + Cy_GPIO_SetDrivemode(config->port, config->tx_num, + CY_GPIO_DM_STRONG_IN_OFF); + + /* Connect assigned divider to be a clock source for UART */ + Cy_SysClk_PeriphAssignDivider(config->scb_clock, + CONFIG_UART_PSOC6_UART_CLK_DIV_TYPE, + CONFIG_UART_PSOC6_UART_CLK_DIV_NUMBER); + + Cy_SysClk_PeriphSetDivider(CONFIG_UART_PSOC6_UART_CLK_DIV_TYPE, + CONFIG_UART_PSOC6_UART_CLK_DIV_NUMBER, + CONFIG_UART_PSOC6_UART_CLK_DIV_VAL); + Cy_SysClk_PeriphEnableDivider(CONFIG_UART_PSOC6_UART_CLK_DIV_TYPE, + CONFIG_UART_PSOC6_UART_CLK_DIV_NUMBER); + + /* Configure UART to operate */ + (void) Cy_SCB_UART_Init(config->base, &uartConfig, NULL); + Cy_SCB_UART_Enable(config->base); + + return 0; +} + +static int uart_psoc6_poll_in(struct device *dev, unsigned char *c) +{ + const struct cypress_psoc6_config *config = dev->config->config_info; + u32_t rec; + + rec = Cy_SCB_UART_Get(config->base); + *c = (unsigned char)(rec & 0xff); + + return ((rec == CY_SCB_UART_RX_NO_DATA) ? -1 : 0); +} + +static unsigned char uart_psoc6_poll_out(struct device *dev, unsigned char c) +{ + const struct cypress_psoc6_config *config = dev->config->config_info; + + while (Cy_SCB_UART_Put(config->base, (uint32_t)c) != 1UL) + ; + + return c; +} + +static const struct uart_driver_api uart_psoc6_driver_api = { + .poll_in = uart_psoc6_poll_in, + .poll_out = uart_psoc6_poll_out, +}; + +#ifdef CONFIG_UART_PSOC6_UART_5 +static const struct cypress_psoc6_config cypress_psoc6_uart5_config = { + .base = CONFIG_UART_PSOC6_UART_5_BASE_ADDRESS, + .port = CONFIG_UART_PSOC6_UART_5_PORT, + .rx_num = CONFIG_UART_PSOC6_UART_5_RX_NUM, + .tx_num = CONFIG_UART_PSOC6_UART_5_TX_NUM, + .rx_val = CONFIG_UART_PSOC6_UART_5_RX_VAL, + .tx_val = CONFIG_UART_PSOC6_UART_5_TX_VAL, + .scb_clock = CONFIG_UART_PSOC6_UART_5_CLOCK, +}; + +DEVICE_AND_API_INIT(uart_5, CONFIG_UART_PSOC6_UART_5_NAME, + uart_psoc6_init, NULL, + &cypress_psoc6_uart5_config, + PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + (void *)&uart_psoc6_driver_api); +#endif /* CONFIG_UART_PSOC6_UART_5 */ + +#ifdef CONFIG_UART_PSOC6_UART_6 +static const struct cypress_psoc6_config cypress_psoc6_uart6_config = { + .base = CONFIG_UART_PSOC6_UART_6_BASE_ADDRESS, + .port = CONFIG_UART_PSOC6_UART_6_PORT, + .rx_num = CONFIG_UART_PSOC6_UART_6_RX_NUM, + .tx_num = CONFIG_UART_PSOC6_UART_6_TX_NUM, + .rx_val = CONFIG_UART_PSOC6_UART_6_RX_VAL, + .tx_val = CONFIG_UART_PSOC6_UART_6_TX_VAL, + .scb_clock = CONFIG_UART_PSOC6_UART_6_CLOCK, +}; + +DEVICE_AND_API_INIT(uart_6, CONFIG_UART_PSOC6_UART_6_NAME, + uart_psoc6_init, NULL, + &cypress_psoc6_uart6_config, + PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + (void *)&uart_psoc6_driver_api); +#endif /* CONFIG_UART_PSOC6_UART_6 */ diff --git a/dts/bindings/serial/cypress,psoc6-uart.yaml b/dts/bindings/serial/cypress,psoc6-uart.yaml new file mode 100644 index 00000000000000..02a8dceb56c5cb --- /dev/null +++ b/dts/bindings/serial/cypress,psoc6-uart.yaml @@ -0,0 +1,32 @@ +# +# Copyright (c) 2018, Cypress +# +# SPDX-License-Identifier: Apache-2.0 +# +--- +title: CYPRESS UART +id: cypress,psoc6-uart +version: 0.1 + +description: > + This binding gives a base representation of the Cypress UART + +inherits: + !include uart.yaml + +properties: + compatible: + constraint: "cypress,psoc6-uart" + + reg: + type: array + description: mmio register space + generation: define + category: required + + interrupts: + type: array + category: required + description: required interrupts + generation: define +...