summaryrefslogtreecommitdiff
path: root/plat/imx/common/imx8m/imx_rdc.c
diff options
context:
space:
mode:
Diffstat (limited to 'plat/imx/common/imx8m/imx_rdc.c')
-rw-r--r--plat/imx/common/imx8m/imx_rdc.c187
1 files changed, 187 insertions, 0 deletions
diff --git a/plat/imx/common/imx8m/imx_rdc.c b/plat/imx/common/imx8m/imx_rdc.c
new file mode 100644
index 00000000..1929c99b
--- /dev/null
+++ b/plat/imx/common/imx8m/imx_rdc.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <platform_def.h>
+#include <utils_def.h>
+#include <imx_rdc.h>
+#include <mmio.h>
+
+/*
+ * Read RDC settings for one peripheral
+ * read the given domains field and lock bit
+ * for the given PDAP index [0..118]
+ */
+int imx_rdc_get_pdap(struct rdc_pdap_conf *p)
+{
+ struct imx_rdc_regs *imx_rdc = (struct imx_rdc_regs *)IMX_RDC_BASE;
+ uint32_t reg = 0;
+
+ reg = mmio_read_32((uintptr_t)&imx_rdc->pdap[p->index]);
+ p->lock = (reg & RDC_PDAP_LCK_MASK) >> RDC_PDAP_LCK_SHIFT;
+ p->domains = reg & 0xFF;
+
+ return 0;
+}
+
+/*
+ * Write RDC settings for one peripheral
+ * Check before write if is already locked then skip
+ */
+int imx_rdc_set_pdap(struct rdc_pdap_conf *p)
+{
+ struct imx_rdc_regs *imx_rdc = (struct imx_rdc_regs *)IMX_RDC_BASE;
+ struct rdc_pdap_conf r;
+ uint32_t i, reg = 0;
+ uint8_t multi_domain = 0;
+
+ /* Check if locked */
+ r.index = p->index;
+ imx_rdc_get_pdap(&r);
+ if (r.lock) {
+ WARN("RDC_PDAPn %d is already locked \n", p->index);
+ return -ENOENT;
+ }
+
+ /* Check if no domain assigned */
+ if (p->domains == 0)
+ return -EINVAL;
+ reg |= p->domains;
+
+ /* Check if SREQ is needed */
+ for (i = 0; i < 7; i += 2)
+ multi_domain += ((p->domains >> i) & 0x3) ? 1 : 0;
+ if (multi_domain > 1)
+ reg |= RDC_PDAP_SREQ_MASK;
+ /* Setup Lock from input */
+ reg |= p->lock << RDC_PDAP_LCK_SHIFT;
+ mmio_write_32((uintptr_t)&imx_rdc->pdap[p->index], reg);
+
+ return 0;
+}
+
+/*
+ * Setup RDC settings for multiple peripherals
+ */
+int imx_rdc_set_peripherals(struct rdc_pdap_conf *peripherals_list,
+ uint32_t count)
+{
+ int i, ret;
+
+ for (i = 0; i < count; i++) {
+ ret = imx_rdc_set_pdap(&peripherals_list[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
+ * Read RDC setting for one master
+ * For the given index in p.index it returns the lock bit
+ * and the domain field into p structure.
+ */
+int imx_rdc_get_mda(struct rdc_mda_conf *p)
+{
+ struct imx_rdc_regs *imx_rdc = (struct imx_rdc_regs *)IMX_RDC_BASE;
+ uint32_t reg = 0;
+
+ reg = mmio_read_32((uintptr_t)&imx_rdc->mda[p->index]);
+ p->domain = reg & RDC_MDA_DID_MASK;
+ p->lock = (reg & RDC_MDA_LCK_MASK) >> RDC_MDA_LCK_SHIFT;
+ return 0;
+}
+
+/*
+ * Write RDC setting for one master
+ */
+int imx_rdc_set_mda(struct rdc_mda_conf *p)
+{
+ struct imx_rdc_regs *imx_rdc = (struct imx_rdc_regs *)IMX_RDC_BASE;
+ struct rdc_mda_conf r;
+ uint32_t reg = 0;
+ int ret = 0;
+
+ /* Check if it is locked */
+ r.index = p->index;
+ imx_rdc_get_mda(&r);
+ if (!r.lock) {
+ reg = (p->domain & RDC_MDA_DID_MASK)
+ | ((p->lock << RDC_MDA_LCK_SHIFT) & RDC_MDA_LCK_MASK);
+ NOTICE("imx_rdc_setup_mda(): write addr=0x%p, reg=0x%x\n",
+ &imx_rdc->mda[p->index], reg);
+ mmio_write_32((uintptr_t)&imx_rdc->mda[p->index], reg);
+ } else {
+ WARN("RDC_MDAn %d is already locked \n", p->index);
+ ret = -ENOENT;
+ }
+
+ return ret;
+}
+
+/*
+ * Setup RDC settings for multiple masters
+ */
+int imx_rdc_set_masters(struct rdc_mda_conf *masters_list, uint32_t count)
+{
+ int i, ret;
+
+ for (i = 0; i < count; i++) {
+ ret = imx_rdc_set_mda(&masters_list[i]);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+#if defined (CSU_RDC_TEST)
+/* Default peripherals settings as an example */
+static struct rdc_pdap_conf periph_config[] = {
+ {RDC_PDAP_GPIO4, 0x30, 0},
+};
+
+
+/* Default masters settings as an example */
+static struct rdc_mda_conf masters_config[] = {
+ {RDC_MDA_A53, 0, 0},
+};
+#else
+/* Default peripherals settings as an example */
+static struct rdc_pdap_conf periph_config[] = {
+ {RDC_PDAP_GPIO1, 0x3, 0},
+ {RDC_PDAP_GPIO2, 0x3, 0},
+ {RDC_PDAP_GPIO3, 0x3, 0},
+ {RDC_PDAP_GPIO4, 0x3, 0},
+ {RDC_PDAP_GPIO5, 0x3, 0},
+};
+
+/* Default masters settings as an example */
+static struct rdc_mda_conf masters_config[] = {
+ {RDC_MDA_A53, 0, 0},
+ {RDC_MDA_CAAM, 0, 0},
+};
+#endif
+void imx_rdc_set_peripherals_default(void)
+{
+ imx_rdc_set_peripherals(periph_config, ARRAY_SIZE(periph_config));
+}
+
+void imx_rdc_set_masters_default(void)
+{
+ imx_rdc_set_masters(masters_config, ARRAY_SIZE(masters_config));
+}
+#if defined (CSU_RDC_TEST)
+void rdc_test(void)
+{
+ imx_rdc_set_peripherals_default();
+ imx_rdc_set_masters_default();
+}
+#endif