[PATCH 1/2] arch: arm: mach-socfpga: HSD #1508115548-1: Add SMMU status and Stream ID checking functions

Add functions for checking SMMU bypass status and matching valid hardware device Stream ID in SMMU Stream Mapping Registers.
Signed-off-by: Chee Hong Ang chee.hong.ang@intel.com Signed-off-by: Jit Loon Lim jit.loon.lim@intel.com --- arch/arm/mach-socfpga/include/mach/smmu_s10.h | 65 ++++++++++ arch/arm/mach-socfpga/smmu_s10.c | 118 ++++++++++++++++++ 2 files changed, 183 insertions(+) create mode 100644 arch/arm/mach-socfpga/include/mach/smmu_s10.h create mode 100644 arch/arm/mach-socfpga/smmu_s10.c
diff --git a/arch/arm/mach-socfpga/include/mach/smmu_s10.h b/arch/arm/mach-socfpga/include/mach/smmu_s10.h new file mode 100644 index 0000000000..dfcc99f82a --- /dev/null +++ b/arch/arm/mach-socfpga/include/mach/smmu_s10.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2018 Intel Corporation. All rights reserved + * + * SPDX-License-Identifier: GPL-2.0 + */ + +/* SMMU registers */ +#define SMMU_SCR0 0 +#define SMMU_SIDR0 0x20 +#define SMMU_SIDR1 0x24 + +#define SMMU_SCR0_CLIENTPD BIT(0) +#define SMMU_SIDR0_NUMSMRG_MASK GENMASK(7, 0) +#define SMMU_SIDR1_NUMCB_MASK GENMASK(7, 0) + +/* Stream mapping registers */ +#define SMMU_GR0_SMR(n) (0x800 + ((n) << 2)) +#define SMMU_SMR_VALID BIT(31) +#define SMMU_SMR_MASK GENMASK(30, 16) +#define SMMU_SMR_ID GENMASK(14, 0) + +#define SMMU_GR0_S2CR(n) (0xc00 + ((n) << 2)) +#define SMMU_S2CR_TYPE GENMASK(17, 16) +#define SMMU_S2CR_CBNDX GENMASK(7, 0) + +/* Register groups for Context Bank */ +#define SMMU_GR0_CB(n, r) (0x20000 + ((n) << 12) + ((r) << 2)) +#define SMMU_CB_SCTLR 0 +#define SMMU_CB_SCTLR_M BIT(0) + +#define SMMU_SID_SDM2HPS_PSI_BE 0 + +void socfpga_init_smmu(void); +int is_smmu_bypass(void); +int is_smmu_stream_id_enabled(u32 stream_id); + +#define SMMU_SET_STREAMID(x, r, w) ((x << r) | (x << w)) + +#define SYSMGR_EMAC0_SID_ADDR 0xffd12050 /* EMAC0 (emac0_ace) */ +#define SYSMGR_EMAC1_SID_ADDR 0xffd12054 /* EMAC0 (emac1_ace) */ +#define SYSMGR_EMAC2_SID_ADDR 0xffd12058 /* EMAC0 (emac2_ace) */ +#define SYSMGR_NAND_SID_ADDR 0xffd1205c /* NAND (nand_axuser) */ +#define SYSMGR_SDMMC_SID_ADDR 0xffd1202c /* SDMMC (sdmmcgrp_l3master) */ +#define SYSMGR_USB0_SID_ADDR 0xffd12038 /* USB0 (usb0_l3master) */ +#define SYSMGR_USB1_SID_ADDR 0xffd1203c /* USB0 (usb1_l3master) */ +#define SYSMGR_DMA_SID_ADDR 0xffd12074 /* DMA (dma_l3master) */ +#define SYSMGR_ETR_SID_ADDR 0xffd12078 /* ETR (etr_l3master) */ +/* Stream ID field offsets */ +#define EMAC_W_OFST 20 +#define EMAC_R_OFST 8 +#define NAND_W_OFST 0 +#define NAND_R_OFST 16 +#define SDMMC_OFST 16 +#define USB_OFST 16 +#define DMA_W_OFST 0 +#define DMA_R_OFST 16 +#define ETR_W_OFST 0 +#define ETR_R_OFST 16 +struct smmu_stream_id { + unsigned long addr; + u32 sid; + u32 r_bit_ofst; + u32 w_bit_ofst; + u32 secure_bit_offset; +}; \ No newline at end of file diff --git a/arch/arm/mach-socfpga/smmu_s10.c b/arch/arm/mach-socfpga/smmu_s10.c new file mode 100644 index 0000000000..d6ab39755d --- /dev/null +++ b/arch/arm/mach-socfpga/smmu_s10.c @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2018 Intel Corporation. All rights reserved + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <asm/arch/firewall.h> +#include <asm/arch/smmu_s10.h> +#include <asm/arch/system_manager.h> +DECLARE_GLOBAL_DATA_PTR; +static const struct smmu_stream_id dev_stream_id[] = { + {SYSMGR_EMAC0_SID_ADDR, 0x01, EMAC_W_OFST, EMAC_R_OFST}, + {SYSMGR_EMAC1_SID_ADDR, 0x02, EMAC_W_OFST, EMAC_R_OFST}, + {SYSMGR_EMAC2_SID_ADDR, 0x03, EMAC_W_OFST, EMAC_R_OFST}, + {SYSMGR_NAND_SID_ADDR, 0x04, NAND_W_OFST, NAND_R_OFST}, + {SYSMGR_SDMMC_SID_ADDR, 0x05, SDMMC_OFST, SDMMC_OFST}, + {SYSMGR_USB0_SID_ADDR, 0x06, USB_OFST, USB_OFST}, + {SYSMGR_USB1_SID_ADDR, 0x07, USB_OFST, USB_OFST}, + {SYSMGR_DMA_SID_ADDR, 0x08, DMA_W_OFST, DMA_R_OFST}, + {SYSMGR_ETR_SID_ADDR, 0x09, ETR_W_OFST, ETR_R_OFST}, +}; +static void set_smmu_streamid(void) +{ + int i; + for (i = 0; i < ARRAY_SIZE(dev_stream_id); i++) { + u32 mask = SMMU_SET_STREAMID(0x3FF, + dev_stream_id[i].r_bit_ofst, + dev_stream_id[i].w_bit_ofst); + u32 value = SMMU_SET_STREAMID(dev_stream_id[i].sid, + dev_stream_id[i].r_bit_ofst, + dev_stream_id[i].w_bit_ofst); + clrbits_le32(dev_stream_id[i].addr, mask); + setbits_le32(dev_stream_id[i].addr, value); + } +} +/* + * Need to set the Secure bit (to make it non-secure) on each peripheral + * so that SMMU can access the peripheral + */ +static void set_smmu_accessible_reg(void) +{ + setbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_EMAC0, + BIT(27) | BIT(25)); + setbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_EMAC1, + BIT(27) | BIT(25)); + setbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_EMAC2, + BIT(27) | BIT(25)); + setbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_NANDGRP_L3MASTER, + BIT(21) | BIT(17)); + setbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_SDMMC_L3MASTER, + BIT(5)); + setbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_USB0_L3MASTER, + BIT(9)); + setbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_USB1_L3MASTER, + BIT(9)); +} +static inline void setup_smmu_firewall(void) +{ + /* Enable nonsecure SMMU accesses */ + writel(FIREWALL_L4_DISABLE_ALL, SOCFPGA_FIREWALL_TCU); +} +void socfpga_init_smmu(void) +{ + setup_smmu_firewall(); + set_smmu_streamid(); + set_smmu_accessible_reg(); +} + +int is_smmu_bypass(void) +{ + return readl(SOCFPGA_SMMU_ADDRESS + SMMU_SCR0) & SMMU_SCR0_CLIENTPD; +} + +int is_smmu_stream_id_enabled(u32 stream_id) +{ + int i; + u32 smrg_num; + u32 smr, s2cr, sid_mask; + u32 cb, cb_index, cb_num; + + if (is_smmu_bypass()) + return 0; + + /* Get number of Stream Mapping Register Groups */ + smrg_num = readl(SOCFPGA_SMMU_ADDRESS + SMMU_SIDR0) & + SMMU_SIDR0_NUMSMRG_MASK; + + /* Get number of Context Bank */ + cb_num = readl(SOCFPGA_SMMU_ADDRESS + SMMU_SIDR1) & + SMMU_SIDR1_NUMCB_MASK; + + for (i = 0; i < smrg_num; i++) { + smr = readl(SOCFPGA_SMMU_ADDRESS + SMMU_GR0_SMR((u64)i)); + sid_mask = (smr & SMMU_SMR_MASK) >> 16; + + /* Skip if Stream ID is invalid or not matched */ + if (!(smr & SMMU_SMR_VALID) || (smr & sid_mask) != stream_id) + continue; + + /* Get Context Bank index from valid matching Stream ID */ + s2cr = readl(SOCFPGA_SMMU_ADDRESS + SMMU_GR0_S2CR((u64)i)); + cb_index = s2cr & SMMU_S2CR_CBNDX; + + /* Skip if Context Bank is invalid or not Translation mode */ + if (cb_index >= cb_num || (s2cr & SMMU_S2CR_TYPE)) + continue; + + cb = readl(SOCFPGA_SMMU_ADDRESS + SMMU_GR0_CB((u64)cb_index, + SMMU_CB_SCTLR)); + /* Return MMU enable status for this Context Bank */ + return (cb & SMMU_CB_SCTLR_M); + } + + return 0; +} \ No newline at end of file

From: Chee Hong Ang chee.hong.ang@intel.com
Secure Device Manager(SDM) has only 512MB window address space to HPS over PSI BE link. The default access range is 0x0 to 0x1FFFFFFF. To allow SDM accessing the address space more than 512MB, SMMU has to be setup for address translation.
U-Boot will not allow the fpga reconfiguration with any bitstream data address exceed 512MB to proceed if PSI BE link address translation is not setup in SMMU.
Signed-off-by: Chee Hong Ang chee.hong.ang@intel.com Signed-off-by: Jit Loon Lim jit.loon.lim@intel.com --- arch/arm/mach-socfpga/include/mach/smmu_s10.h | 6 ++++++ drivers/fpga/intel_sdm_mb.c | 13 +++++++++++++ 2 files changed, 19 insertions(+)
diff --git a/arch/arm/mach-socfpga/include/mach/smmu_s10.h b/arch/arm/mach-socfpga/include/mach/smmu_s10.h index dfcc99f82a..61157c03d6 100644 --- a/arch/arm/mach-socfpga/include/mach/smmu_s10.h +++ b/arch/arm/mach-socfpga/include/mach/smmu_s10.h @@ -30,6 +30,12 @@
#define SMMU_SID_SDM2HPS_PSI_BE 0
+#define SDM2HPS_PSI_BE_ADDR_BASE 0 +/* PSI BE 512MB address window */ +#define SDM2HPS_PSI_BE_WINDOW_SZ 0x20000000 +#define SDM2HPS_PSI_BE_ADDR_END \ + (SDM2HPS_PSI_BE_ADDR_BASE + SDM2HPS_PSI_BE_WINDOW_SZ - 1) + void socfpga_init_smmu(void); int is_smmu_bypass(void); int is_smmu_stream_id_enabled(u32 stream_id); diff --git a/drivers/fpga/intel_sdm_mb.c b/drivers/fpga/intel_sdm_mb.c index f5fd9a14c2..a2191c1a16 100644 --- a/drivers/fpga/intel_sdm_mb.c +++ b/drivers/fpga/intel_sdm_mb.c @@ -9,6 +9,7 @@ #include <watchdog.h> #include <asm/arch/mailbox_s10.h> #include <asm/arch/smc_api.h> +#include <asm/arch/smmu_s10.h> #include <linux/delay.h> #include <linux/intel-smc.h>
@@ -394,6 +395,18 @@ int intel_sdm_mb_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size) u32 resp_len = 2; u32 resp_buf[2];
+ /* + * Don't start the FPGA reconfiguration if bitstream location exceed the + * PSI BE 512MB address window and SMMU is not setup for PSI BE address + * translation. + */ + if (((u64)rbf_data + rbf_size) >= SDM2HPS_PSI_BE_ADDR_END && + !is_smmu_stream_id_enabled(SMMU_SID_SDM2HPS_PSI_BE)) { + printf("Failed: Bitstream location must not exceed 0x%08x\n", + SDM2HPS_PSI_BE_ADDR_END); + return -EINVAL; + } + debug("Sending MBOX_RECONFIG...\n"); ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_RECONFIG, MBOX_CMD_DIRECT, 0, NULL, 0, &resp_len, resp_buf);
participants (1)
-
Jit Loon Lim