From: Peng Fan <peng....@nxp.com>

There is xrdc inside i.MX8ULP, we need to configure permission to make
sure AP non-secure world could access the resources.

Signed-off-by: Peng Fan <peng....@nxp.com>
---
 arch/arm/include/asm/arch-imx8ulp/sys_proto.h |   2 +
 arch/arm/mach-imx/imx8ulp/Makefile            |   2 +-
 arch/arm/mach-imx/imx8ulp/xrdc.c              | 144 ++++++++++++++++++
 3 files changed, 147 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/imx8ulp/xrdc.c

diff --git a/arch/arm/include/asm/arch-imx8ulp/sys_proto.h 
b/arch/arm/include/asm/arch-imx8ulp/sys_proto.h
index a8f632f45e..47ee46bdf4 100644
--- a/arch/arm/include/asm/arch-imx8ulp/sys_proto.h
+++ b/arch/arm/include/asm/arch-imx8ulp/sys_proto.h
@@ -13,4 +13,6 @@ extern unsigned long rom_pointer[];
 ulong spl_romapi_raw_seekable_read(u32 offset, u32 size, void *buf);
 ulong spl_romapi_get_uboot_base(u32 image_offset, u32 rom_bt_dev);
 enum bt_mode get_boot_mode(void);
+int xrdc_config_pdac(u32 bridge, u32 index, u32 dom, u32 perm);
+int xrdc_config_pdac_openacc(u32 bridge, u32 index);
 #endif
diff --git a/arch/arm/mach-imx/imx8ulp/Makefile 
b/arch/arm/mach-imx/imx8ulp/Makefile
index 78c81d78bb..453589e6a2 100644
--- a/arch/arm/mach-imx/imx8ulp/Makefile
+++ b/arch/arm/mach-imx/imx8ulp/Makefile
@@ -4,4 +4,4 @@
 #
 
 obj-y += lowlevel_init.o
-obj-y += soc.o clock.o iomux.o pcc.o cgc.o
+obj-y += soc.o clock.o iomux.o pcc.o cgc.o xrdc.o
diff --git a/arch/arm/mach-imx/imx8ulp/xrdc.c b/arch/arm/mach-imx/imx8ulp/xrdc.c
new file mode 100644
index 0000000000..7a098718da
--- /dev/null
+++ b/arch/arm/mach-imx/imx8ulp/xrdc.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 NXP
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/io.h>
+#include <errno.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define XRDC_ADDR      0x292f0000
+#define MRC_OFFSET     0x2000
+#define MRC_STEP       0x200
+
+#define SP(X)          ((X) << 9)
+#define SU(X)          ((X) << 6)
+#define NP(X)          ((X) << 3)
+#define NU(X)          ((X) << 0)
+
+#define RWX            7
+#define RW             6
+#define R              4
+#define X              1
+
+#define D7SEL_CODE     (SP(RW) | SU(RW) | NP(RWX) | NU(RWX))
+#define D6SEL_CODE     (SP(RW) | SU(RW) | NP(RWX))
+#define D5SEL_CODE     (SP(RW) | SU(RWX))
+#define D4SEL_CODE     SP(RWX)
+#define D3SEL_CODE     (SP(X) | SU(X) | NP(X) | NU(X))
+#define D0SEL_CODE     0
+
+#define D7SEL_DAT      (SP(RW) | SU(RW) | NP(RW) | NU(RW))
+#define D6SEL_DAT      (SP(RW) | SU(RW) | NP(RW))
+#define D5SEL_DAT      (SP(RW) | SU(RW) | NP(R) | NU(R))
+#define D4SEL_DAT      (SP(RW) | SU(RW))
+#define D3SEL_DAT      SP(RW)
+
+union dxsel_perm {
+       struct {
+               u8 dx;
+               u8 perm;
+       };
+
+       u32 dom_perm;
+};
+
+int xrdc_config_mrc_dx_perm(u32 mrc_con, u32 region, u32 dom, u32 dxsel)
+{
+       ulong w2_addr;
+       u32 val = 0;
+
+       w2_addr = XRDC_ADDR + MRC_OFFSET + mrc_con * 0x200 + region * 0x20 + 
0x8;
+
+       val = (readl(w2_addr) & (~(7 << (3 * dom)))) | (dxsel << (3 * dom));
+       writel(val, w2_addr);
+
+       return 0;
+}
+
+int xrdc_config_mrc_w0_w1(u32 mrc_con, u32 region, u32 w0, u32 size)
+{
+       ulong w0_addr, w1_addr;
+
+       w0_addr = XRDC_ADDR + MRC_OFFSET + mrc_con * 0x200 + region * 0x20;
+       w1_addr = w0_addr + 4;
+
+       if ((size % 32) != 0)
+               return -EINVAL;
+
+       writel(w0 & ~0x1f, w0_addr);
+       writel(w0 + size - 1, w1_addr);
+
+       return 0;
+}
+
+int xrdc_config_mrc_w3_w4(u32 mrc_con, u32 region, u32 w3, u32 w4)
+{
+       ulong w3_addr = XRDC_ADDR + MRC_OFFSET + mrc_con * 0x200 + region * 
0x20 + 0xC;
+       ulong w4_addr = w3_addr + 4;
+
+       writel(w3, w3_addr);
+       writel(w4, w4_addr);
+
+       return 0;
+}
+
+int xrdc_config_pdac_openacc(u32 bridge, u32 index)
+{
+       ulong w0_addr;
+       u32 val;
+
+       switch (bridge) {
+       case 3:
+               w0_addr = XRDC_ADDR + 0x1000 + 0x8 * index;
+               break;
+       case 4:
+               w0_addr = XRDC_ADDR + 0x1400 + 0x8 * index;
+               break;
+       case 5:
+               w0_addr = XRDC_ADDR + 0x1800 + 0x8 * index;
+               break;
+       default:
+               return -EINVAL;
+       }
+       writel(0xffffff, w0_addr);
+
+       val = readl(w0_addr + 4);
+       writel(val | BIT(31), w0_addr + 4);
+
+       return 0;
+}
+
+int xrdc_config_pdac(u32 bridge, u32 index, u32 dom, u32 perm)
+{
+       ulong w0_addr;
+       u32 val;
+
+       switch (bridge) {
+       case 3:
+               w0_addr = XRDC_ADDR + 0x1000 + 0x8 * index;
+               break;
+       case 4:
+               w0_addr = XRDC_ADDR + 0x1400 + 0x8 * index;
+               break;
+       case 5:
+               w0_addr = XRDC_ADDR + 0x1800 + 0x8 * index;
+               break;
+       default:
+               return -EINVAL;
+       }
+       val = readl(w0_addr);
+       writel((val & ~(0x7 << (dom * 3))) | (perm << (dom * 3)), w0_addr);
+
+       val = readl(w0_addr + 4);
+       writel(val | BIT(31), w0_addr + 4);
+
+       return 0;
+}
-- 
2.30.0

Reply via email to