diff options
author | Nicolas Royer <nroyer@baylibre.com> | 2020-09-27 17:36:43 +0200 |
---|---|---|
committer | nicola-mazzucato-arm <42373140+nicola-mazzucato-arm@users.noreply.github.com> | 2020-10-15 17:45:38 +0100 |
commit | 6d92e073c3df3881f0d4c79bcb5be1fef400b579 (patch) | |
tree | 8a2f7ba2c29b71cb12bbc701dbc214a5482105a6 | |
parent | 3c45dfc2b23a3b939398184426ea71b9953f1a5e (diff) |
rcar/module: add rcar scif module and config data
Change-Id: I1e4b7df885634f599f652e88ea06b42a9a1d7ae1
Signed-off-by: Tsutomu Muroya <tsutomu.muroya.jy@bp.renesas.com>
Signed-off-by: Nicolas Royer <nroyer@baylibre.com>
-rw-r--r-- | product/rcar/module/rcar_scif/include/mod_rcar_scif.h | 58 | ||||
-rw-r--r-- | product/rcar/module/rcar_scif/src/Makefile | 11 | ||||
-rw-r--r-- | product/rcar/module/rcar_scif/src/mod_rcar_scif.c | 286 | ||||
-rw-r--r-- | product/rcar/module/rcar_scif/src/scif.h | 111 | ||||
-rw-r--r-- | product/rcar/scp_ramfw/config_rcar_scif.c | 31 | ||||
-rw-r--r-- | product/rcar/scp_ramfw/fmw_io.h | 17 |
6 files changed, 514 insertions, 0 deletions
diff --git a/product/rcar/module/rcar_scif/include/mod_rcar_scif.h b/product/rcar/module/rcar_scif/include/mod_rcar_scif.h new file mode 100644 index 00000000..0fdb916e --- /dev/null +++ b/product/rcar/module/rcar_scif/include/mod_rcar_scif.h @@ -0,0 +1,58 @@ +/* + * Renesas SCP/MCP Software + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MOD_RCAR_SCIF_H +#define MOD_RCAR_SCIF_H + +#include <fwk_id.h> + +#include <stdint.h> + +/*! + * \addtogroup GroupRCARModule RCAR Product Modules + * \{ + */ + +/*! + * \defgroup GroupRCARSCIF SCIF Driver + * + * \brief Device driver module for the Primecell® SCIF UART. + * + * \{ + */ + +/*! + * \brief SCIF element configuration data. + */ +struct mod_rcar_scif_element_cfg { + /*! + * \brief Base address of the device registers. + */ + uintptr_t reg_base; + + /*! + * \brief Baud rate in bits per second. + */ + unsigned int baud_rate_bps; + + /*! + * \brief Reference clock in Hertz. + */ + uint64_t clock_rate_hz; +}; + +/*! + * \} + */ + +/*! + * \} + */ + +int mod_rcar_scif_resume(); + +#endif /* MOD_RCAR_SCIF_H */ diff --git a/product/rcar/module/rcar_scif/src/Makefile b/product/rcar/module/rcar_scif/src/Makefile new file mode 100644 index 00000000..38cdd0e4 --- /dev/null +++ b/product/rcar/module/rcar_scif/src/Makefile @@ -0,0 +1,11 @@ +# +# Renesas SCP/MCP Software +# Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BS_LIB_NAME := "SCIF" +BS_LIB_SOURCES = mod_rcar_scif.c + +include $(BS_DIR)/lib.mk diff --git a/product/rcar/module/rcar_scif/src/mod_rcar_scif.c b/product/rcar/module/rcar_scif/src/mod_rcar_scif.c new file mode 100644 index 00000000..26ed7ffa --- /dev/null +++ b/product/rcar/module/rcar_scif/src/mod_rcar_scif.c @@ -0,0 +1,286 @@ +/* + * Renesas SCP/MCP Software + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "scif.h" + +#include <mmio.h> +#include <system_mmap.h> + +#include <mod_rcar_scif.h> + +#include <fwk_mm.h> +#include <fwk_module.h> +#include <fwk_module_idx.h> +#include <fwk_notification.h> +#include <fwk_status.h> + +#include <assert.h> + +struct mod_rcar_scif_element_ctx { + /* Whether the device has an open file stream */ + bool open; +}; + +static struct mod_rcar_scif_ctx { + bool initialized; /* Whether the context has been initialized */ + + struct mod_rcar_scif_element_ctx *elements; /* Element context table */ +} mod_rcar_scif_ctx = { + .initialized = false, +}; + +static const struct mod_rcar_scif_element_cfg *current_cfg; + +static int mod_rcar_scif_init_ctx(struct mod_rcar_scif_ctx *ctx) +{ + size_t element_count; + + fwk_assert(!mod_rcar_scif_ctx.initialized); + + element_count = fwk_module_get_element_count(fwk_module_id_rcar_scif); + if (element_count == 0) + return FWK_SUCCESS; + + ctx->elements = fwk_mm_alloc(element_count, sizeof(ctx->elements[0])); + if (!fwk_expect(ctx->elements != NULL)) + return FWK_E_NOMEM; + + for (size_t i = 0; i < element_count; i++) { + ctx->elements[i] = (struct mod_rcar_scif_element_ctx){ + .open = false, + }; + } + + mod_rcar_scif_ctx.initialized = true; + + return FWK_SUCCESS; +} + +/* + * For details on the constants and equations used to calculate the baud rate + * settings, please consult the SCIF TRM. + * However, this version does not support it. + */ +static int mod_rcar_scif_set_baud_rate( + const struct mod_rcar_scif_element_cfg *cfg) +{ + struct scif_reg *reg = (void *)cfg->reg_base; + uint32_t status; + int i; + + assert(reg); + current_cfg = cfg; + + if (reg == (void *)BOARD_UART1_BASE) { + /* SCSI-1 */ + status = mmio_read_32(CPG_SMSTPCR2); + status = (status & ~MSTP26); + mmio_write_32(CPG_CPGWPR, ~status); + mmio_write_32(CPG_SMSTPCR2, status); + + while (mmio_read_32(CPG_MSTPSR2) & MSTP26) + continue; + } else if (reg == (void *)BOARD_UART2_BASE) { + /* SCSI-2 */ + status = mmio_read_32(CPG_SMSTPCR3); + status = (status & ~MSTP310); + mmio_write_32(CPG_CPGWPR, ~status); + mmio_write_32(CPG_SMSTPCR3, status); + + while (mmio_read_32(CPG_MSTPSR3) & MSTP310) + continue; + } else { + return FWK_E_PARAM; + } + + /* Clear bits TE and RE in SCSCR to 0 */ + reg->SCSCR = (SCSCR_TE_DIS | SCSCR_RE_DIS); + /* Set bits TFRST and RFRST in SCFCR to 1 */ + reg->SCFCR |= (SCFCR_TFRST_EN | SCFCR_RFRS_EN); + /* Read flags of ER, DR, BRK, */ + reg->SCFSR = SCFSR_INIT_DATA; + reg->SCLSR = 0; + /* Set bits CKE[1:0] in SCSCR */ + reg->SCSCR = (reg->SCSCR & ~SCSCR_CKE_MASK) | SCSCR_CKE_INT_CLK; + /* Set data transfer format in SCSMR */ + reg->SCSMR = SCSMR_INIT_DATA; + /* Set value in SCBRR */ +#if SCIF_CLK == SCIF_INTERNAL_CLK + if ((mmio_read_32(PRR) & (PRR_PRODUCT_MASK | PRR_CUT_MASK)) == + PRR_PRODUCT_H3_VER_10) { + /* H3 Ver.1.0 sets clock to doubling */ + reg->SCBRR = SCBRR_230400BPS; + } else { + reg->SCBRR = SCBRR_115200BPS; + } +#else + reg->DL = DL_INIT_DATA; + reg->CKS = CKS_INIT_DATA; +#endif /* SCIF_CLK == SCIF_INTERNAL_CLK */ + for (i = 100; i; i--) + ; + reg->SCFCR = SCFCR_INIT_DATA; + reg->SCSCR = (reg->SCSCR | (SCSCR_TE_EN | SCSCR_RE_EN)); + return FWK_SUCCESS; +} + +int mod_rcar_scif_resume() +{ + return mod_rcar_scif_set_baud_rate(current_cfg); +} + +static void mod_rcar_scif_putch(fwk_id_t id, char c) +{ + const struct mod_rcar_scif_element_cfg *cfg = fwk_module_get_data(id); + struct scif_reg *reg = (void *)cfg->reg_base; + + /* Check if the transmit FIFO is full */ + while (GET_SCFDR_T(reg) >= FIFO_FULL) + continue; + + reg->SCFTDR = c; +} + +static bool mod_rcar_scif_getch(fwk_id_t id, char *ch) +{ + return false; /* Not implemented yet */ +} + +static void mod_rcar_scif_flush(fwk_id_t id) +{ + const struct mod_rcar_scif_element_cfg *cfg = fwk_module_get_data(id); + struct scif_reg *reg = (void *)cfg->reg_base; + + /* Check if the transmit data is available */ + while (GET_SCFDR_T(reg)) + continue; +} + +/* + * Framework module handlers + */ +static int mod_rcar_scif_init( + fwk_id_t module_id, + unsigned int element_count, + const void *data) +{ + if (mod_rcar_scif_ctx.initialized) + return FWK_SUCCESS; + + return mod_rcar_scif_init_ctx(&mod_rcar_scif_ctx); +} + +static int mod_rcar_scif_element_init( + fwk_id_t element_id, + unsigned int unused, + const void *data) +{ + return FWK_SUCCESS; +} + +static int mod_rcar_scif_start(fwk_id_t id) +{ + return FWK_SUCCESS; +} + +/* + * Framework io handlers + */ +static int mod_rcar_scif_io_open(const struct fwk_io_stream *stream) +{ + int status; + struct mod_rcar_scif_element_ctx *ctx; + const struct mod_rcar_scif_element_cfg *cfg; + + if (!fwk_id_is_type(stream->id, FWK_ID_TYPE_ELEMENT)) + return FWK_E_SUPPORT; + + if (!mod_rcar_scif_ctx.initialized) { + status = mod_rcar_scif_init_ctx(&mod_rcar_scif_ctx); + if (status != FWK_SUCCESS) + return FWK_E_STATE; + } + + ctx = &mod_rcar_scif_ctx.elements[fwk_id_get_element_idx(stream->id)]; + if (ctx->open) /* Refuse to open the same device twice */ + return FWK_E_BUSY; + + ctx->open = true; + + /* Enable the device if possible */ + cfg = fwk_module_get_data(stream->id); + status = mod_rcar_scif_set_baud_rate(cfg); + + return status; +} + +static int mod_rcar_scif_io_getch( + const struct fwk_io_stream *restrict stream, + char *restrict ch) +{ + const struct mod_rcar_scif_element_ctx *ctx = + &mod_rcar_scif_ctx.elements[fwk_id_get_element_idx(stream->id)]; + + bool ok = true; + + fwk_assert(ctx->open); + + ok = mod_rcar_scif_getch(stream->id, ch); + if (!ok) + return FWK_PENDING; + + return FWK_SUCCESS; +} + +static int mod_rcar_scif_io_putch(const struct fwk_io_stream *stream, char ch) +{ + const struct mod_rcar_scif_element_ctx *ctx = + &mod_rcar_scif_ctx.elements[fwk_id_get_element_idx(stream->id)]; + + fwk_assert(ctx->open); + + if ((ch == '\n') && !(stream->mode & FWK_IO_MODE_BINARY)) + mod_rcar_scif_putch(stream->id, '\r'); /* Prepend carriage return */ + + mod_rcar_scif_putch(stream->id, ch); + + return FWK_SUCCESS; +} + +static int mod_rcar_scif_io_close(const struct fwk_io_stream *stream) +{ + struct mod_rcar_scif_element_ctx *ctx; + + fwk_assert(stream != NULL); /* Validated by the framework */ + fwk_assert(fwk_module_is_valid_element_id(stream->id)); + + mod_rcar_scif_flush(stream->id); + + ctx = &mod_rcar_scif_ctx.elements[fwk_id_get_element_idx(stream->id)]; + fwk_assert(ctx->open); + + ctx->open = false; + + return FWK_SUCCESS; +} + +const struct fwk_module module_rcar_scif = { + .name = "RCAR SCIF", + .type = FWK_MODULE_TYPE_DRIVER, + + .init = mod_rcar_scif_init, + .element_init = mod_rcar_scif_element_init, + .start = mod_rcar_scif_start, + + .adapter = + (struct fwk_io_adapter){ + .open = mod_rcar_scif_io_open, + .getch = mod_rcar_scif_io_getch, + .putch = mod_rcar_scif_io_putch, + .close = mod_rcar_scif_io_close, + }, +}; diff --git a/product/rcar/module/rcar_scif/src/scif.h b/product/rcar/module/rcar_scif/src/scif.h new file mode 100644 index 00000000..464a671b --- /dev/null +++ b/product/rcar/module/rcar_scif/src/scif.h @@ -0,0 +1,111 @@ +/* + * Renesas SCP/MCP Software + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SCIF_H +#define SCIF_H + +#include <rcar_mmap.h> + +#include <fwk_macros.h> + +#define SCIF_INTERNAL_CLK 0 /* Internal clock(S3D4:66.66MHz) */ +#define SCIF_EXTARNAL_CLK 1 /* External clock(SCK2:14.7456MHz) */ +#define SCIF_CLK SCIF_INTERNAL_CLK + +struct scif_reg { + FWK_RW uint16_t SCSMR; /* H'00 */ + uint16_t RESERVED1; /* H'02 */ + FWK_RW uint8_t SCBRR; /* H'04 */ + uint8_t RESERVED2; /* H'05 */ + uint16_t RESERVED3; /* H'06 */ + FWK_RW uint16_t SCSCR; /* H'08 */ + uint16_t RESERVED4; /* H'0A */ + FWK_W uint8_t SCFTDR; /* H'0C */ + uint8_t RESERVED5; /* H'0D */ + uint16_t RESERVED6; /* H'0E */ + FWK_RW uint16_t SCFSR; /* H'10 */ + uint16_t RESERVED7; /* H'12 */ + FWK_R uint8_t SCFRDR; /* H'14 */ + uint8_t RESERVED8; /* H'15 */ + uint16_t RESERVED9; /* H'16 */ + FWK_RW uint16_t SCFCR; /* H'18 */ + uint16_t RESERVED10; /* H'1A */ + FWK_R uint16_t SCFDR; /* H'1C */ + uint16_t RESERVED11; /* H'1E */ + FWK_RW uint16_t SCSPTR; /* H'20 */ + uint16_t RESERVED12; /* H'22 */ + FWK_RW uint16_t SCLSR; /* H'24 */ + uint16_t RESERVED13; /* H'26 */ + uint32_t RESERVED14; /* H'28 */ + uint32_t RESERVED15; /* H'2C */ + FWK_RW uint16_t DL; /* H'30 */ + uint16_t RESERVED16; /* H'32 */ + FWK_RW uint16_t CKS; /* H'34 */ +}; + +#define CPG_SMSTPCR2 (CPG_BASE + 0x0138) +#define CPG_SMSTPCR3 (CPG_BASE + 0x013C) +#define CPG_MSTPSR2 (CPG_BASE + 0x0040) +#define CPG_MSTPSR3 (CPG_BASE + 0x0048) +#define CPG_CPGWPR (CPG_BASE + 0x0900) + +#define PRR (0xFFF00044) +#define PRR_PRODUCT_MASK (0x00007F00) +#define PRR_CUT_MASK (0x000000FF) +#define PRR_PRODUCT_H3_VER_10 (0x00004F00) /* R-Car H3 Ver.1.0 */ + +#define SCSMR_CA_MASK (1 << 7) +#define SCSMR_CA_ASYNC (0x0000) +#define SCSMR_CHR_MASK (1 << 6) +#define SCSMR_CHR_8 (0x0000) +#define SCSMR_PE_MASK (1 << 5) +#define SCSMR_PE_DIS (0x0000) +#define SCSMR_STOP_MASK (1 << 3) +#define SCSMR_STOP_1 (0x0000) +#define SCSMR_CKS_MASK (3 << 0) +#define SCSMR_CKS_DIV1 (0x0000) +#define SCSMR_INIT_DATA \ + (SCSMR_CA_ASYNC + SCSMR_CHR_8 + SCSMR_PE_DIS + SCSMR_STOP_1 + \ + SCSMR_CKS_DIV1) + +#define MSTP310 (1 << 10) +#define MSTP26 (1 << 6) + +#define SCSCR_TE_MASK (1 << 5) +#define SCSCR_TE_DIS (0x0000) +#define SCSCR_TE_EN (0x0020) +#define SCSCR_RE_MASK (1 << 4) +#define SCSCR_RE_DIS (0x0000) +#define SCSCR_RE_EN (0x0010) +#define SCSCR_CKE_MASK (3 << 0) +#define SCSCR_CKE_INT (0x0000) +#define SCSCR_CKE_BRG (0x0002) +#if SCIF_CLK == SCIF_EXTARNAL_CLK +# define SCSCR_CKE_INT_CLK (SCSCR_CKE_BRG) +#else +# define SCSCR_CKE_INT_CLK (SCSCR_CKE_INT) +#endif + +#define SCFSR_INIT_DATA (0x0000) + +#define SCFCR_TFRST_EN (0x0004) +#define SCFCR_RFRS_EN (0x0002) + +#define FIFO_SIZE_BIT (5) +#define FIFO_MASK ((1 << FIFO_SIZE_BIT) - 1) +#define FIFO_R_SHIFT (0) +#define FIFO_T_SHIFT (8) +#define FIFO_FULL (16) +#define GET_SCFDR_T(reg) ((reg->SCFDR >> FIFO_T_SHIFT) & FIFO_MASK) + +#define SCFCR_TTRG_8 (0x0000) +#define SCFCR_INIT_DATA (SCFCR_TTRG_8) + +#define SCBRR_115200BPS (17) /* 115200bps@66MHz */ +#define SCBRR_230400BPS (8) /* 230400bps@66MHz */ + +#endif /* SCIF_H */ diff --git a/product/rcar/scp_ramfw/config_rcar_scif.c b/product/rcar/scp_ramfw/config_rcar_scif.c new file mode 100644 index 00000000..a298bc40 --- /dev/null +++ b/product/rcar/scp_ramfw/config_rcar_scif.c @@ -0,0 +1,31 @@ +/* + * Renesas SCP/MCP Software + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <system_mmap.h> + +#include <mod_rcar_scif.h> + +#include <fwk_element.h> +#include <fwk_id.h> +#include <fwk_macros.h> +#include <fwk_module.h> +#include <fwk_module_idx.h> + +struct fwk_module_config config_rcar_scif = { + .elements = FWK_MODULE_STATIC_ELEMENTS({ + [0] = + { + .name = "board-uart1", + .data = + &(struct mod_rcar_scif_element_cfg){ + .reg_base = BOARD_UART1_BASE, + }, + }, + + [1] = { 0 }, + }), +}; diff --git a/product/rcar/scp_ramfw/fmw_io.h b/product/rcar/scp_ramfw/fmw_io.h new file mode 100644 index 00000000..40ba9245 --- /dev/null +++ b/product/rcar/scp_ramfw/fmw_io.h @@ -0,0 +1,17 @@ +/* + * Renesas SCP/MCP Software + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FMW_IO_H +#define FMW_IO_H + +#include <fwk_id.h> +#include <fwk_module_idx.h> + +#define FMW_IO_STDIN_ID FWK_ID_ELEMENT(FWK_MODULE_IDX_RCAR_SCIF, 0) +#define FMW_IO_STDOUT_ID FWK_ID_ELEMENT(FWK_MODULE_IDX_RCAR_SCIF, 0) + +#endif /* FMW_IO_H */ |