Skip to content

Commit

Permalink
drivers: serial: Add Cypress PSoC6 UART driver
Browse files Browse the repository at this point in the history
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 <nazar.chornenkyy@cypress.com>
Signed-off-by: Oleg Kapshii <oleg.kapshii@cypress.com>
  • Loading branch information
nazrchorn authored and nashif committed Sep 21, 2018
1 parent 93f938c commit edd6c7d
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/serial/CMakeLists.txt
Expand Up @@ -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)
2 changes: 2 additions & 0 deletions drivers/serial/Kconfig
Expand Up @@ -101,4 +101,6 @@ source "drivers/serial/Kconfig.msp432p4xx"

source "drivers/serial/Kconfig.sam0"

source "drivers/serial/Kconfig.psoc6"

endif
25 changes: 25 additions & 0 deletions 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.
171 changes: 171 additions & 0 deletions 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 <device.h>
#include <errno.h>
#include <init.h>
#include <misc/__assert.h>
#include <soc.h>
#include <uart.h>
#include <board.h>

#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 */
32 changes: 32 additions & 0 deletions 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
...

0 comments on commit edd6c7d

Please sign in to comment.