aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Royer <nroyer@baylibre.com>2020-09-27 17:36:43 +0200
committernicola-mazzucato-arm <42373140+nicola-mazzucato-arm@users.noreply.github.com>2020-10-15 17:45:38 +0100
commit6d92e073c3df3881f0d4c79bcb5be1fef400b579 (patch)
tree8a2f7ba2c29b71cb12bbc701dbc214a5482105a6
parent3c45dfc2b23a3b939398184426ea71b9953f1a5e (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.h58
-rw-r--r--product/rcar/module/rcar_scif/src/Makefile11
-rw-r--r--product/rcar/module/rcar_scif/src/mod_rcar_scif.c286
-rw-r--r--product/rcar/module/rcar_scif/src/scif.h111
-rw-r--r--product/rcar/scp_ramfw/config_rcar_scif.c31
-rw-r--r--product/rcar/scp_ramfw/fmw_io.h17
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 */