diff --git a/Makefile b/Makefile index 23ebcaa92c6cfe4973100f99372920a8a5962844..b57b2129176c07d233d433cac198a6220f12a05b 100644 --- a/Makefile +++ b/Makefile @@ -465,7 +465,6 @@ $(eval $(call assert_numeric,ARM_ARCH_MINOR)) # platform to overwrite the default options ################################################################################ -$(eval $(call add_define,ARM_CCI_PRODUCT_ID)) $(eval $(call add_define,ARM_ARCH_MAJOR)) $(eval $(call add_define,ARM_ARCH_MINOR)) $(eval $(call add_define,ARM_GIC_ARCH)) diff --git a/docs/user-guide.rst b/docs/user-guide.rst index ec8c2333ede7c9f404e2aec5659a74e318b72a7b..99625e43855d99405e759ad028be0d64fa1b6b92 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -213,10 +213,6 @@ Common build options It can take either ``aarch64`` or ``aarch32`` as values. By default, it is defined to ``aarch64``. -- ``ARM_CCI_PRODUCT_ID``: Choice of ARM CCI product used by the platform. This - is used to determine the number of valid slave interfaces available in the - ARM CCI driver. Default is 400 (that is, CCI-400). - - ``ARM_ARCH_MAJOR``: The major version of ARM Architecture to target when compiling ARM Trusted Firmware. Its value must be numeric, and defaults to 8 . See also, *ARMv8 Architecture Extensions* in `Firmware Design`_. @@ -231,10 +227,10 @@ Common build options This build option is deprecated. - ``ARM_PLAT_MT``: This flag determines whether the ARM platform layer has to - cater for the multi-threading ``MT`` bit when accessing MPIDR. When this - flag is set, the functions which deal with MPIDR assume that the ``MT`` bit - in MPIDR is set and access the bit-fields in MPIDR accordingly. Default - value of this flag is 0. + cater for the multi-threading ``MT`` bit when accessing MPIDR. When this flag + is set, the functions which deal with MPIDR assume that the ``MT`` bit in + MPIDR is set and access the bit-fields in MPIDR accordingly. Default value of + this flag is 0. Note that this option is not used on FVP platforms. - ``BL2``: This is an optional build option which specifies the path to BL2 image for the ``fip`` target. In this case, the BL2 in the ARM Trusted @@ -677,6 +673,10 @@ ARM FVP platform specific build options - ``FVP_CCN`` : The CCN driver is selected. This is the default if ``FVP_CLUSTER_COUNT`` > 2. +- ``FVP_MAX_PE_PER_CPU``: Sets the maximum number of PEs implemented on any CPU + in the system. This option defaults to 1. Note that the build option + ``ARM_PLAT_MT`` doesn't have any effect on FVP platforms. + - ``FVP_USE_GIC_DRIVER`` : Selects the GIC driver to be built. Options: - ``FVP_GIC600`` : The GIC600 implementation of GICv3 is selected diff --git a/drivers/arm/cci/cci.c b/drivers/arm/cci/cci.c index 04530b01cb159c7cf96f03dc308ff6e0e4bdc3f6..e15683840dc00e2438f97f75548301ba13600a29 100644 --- a/drivers/arm/cci/cci.c +++ b/drivers/arm/cci/cci.c @@ -11,11 +11,26 @@ #include <mmio.h> #include <stdint.h> -static uintptr_t g_cci_base; -static unsigned int g_max_master_id; -static const int *g_cci_slave_if_map; +#define MAKE_CCI_PART_NUMBER(hi, lo) ((hi << 8) | lo) +#define CCI_PART_LO_MASK 0xff +#define CCI_PART_HI_MASK 0xf + +/* CCI part number codes read from Peripheral ID registers 0 and 1 */ +#define CCI400_PART_NUM 0x420 +#define CCI500_PART_NUM 0x422 +#define CCI550_PART_NUM 0x423 + +#define CCI400_SLAVE_PORTS 5 +#define CCI500_SLAVE_PORTS 7 +#define CCI550_SLAVE_PORTS 7 + +static uintptr_t cci_base; +static const int *cci_slave_if_map; #if ENABLE_ASSERTIONS +static unsigned int max_master_id; +static int cci_num_slave_ports; + static int validate_cci_map(const int *map) { unsigned int valid_cci_map = 0; @@ -23,13 +38,13 @@ static int validate_cci_map(const int *map) int i; /* Validate the map */ - for (i = 0; i <= g_max_master_id; i++) { + for (i = 0; i <= max_master_id; i++) { slave_if_id = map[i]; if (slave_if_id < 0) continue; - if (slave_if_id >= CCI_SLAVE_INTERFACE_COUNT) { + if (slave_if_id >= cci_num_slave_ports) { ERROR("Slave interface ID is invalid\n"); return 0; } @@ -48,70 +63,105 @@ static int validate_cci_map(const int *map) return 1; } + +/* + * Read CCI part number from Peripheral ID registers + */ +static unsigned int read_cci_part_number(uintptr_t base) +{ + unsigned int part_lo, part_hi; + + part_lo = mmio_read_32(base + PERIPHERAL_ID0) & CCI_PART_LO_MASK; + part_hi = mmio_read_32(base + PERIPHERAL_ID1) & CCI_PART_HI_MASK; + + return MAKE_CCI_PART_NUMBER(part_hi, part_lo); +} + +/* + * Identify a CCI device, and return the number of slaves. Return -1 for an + * unidentified device. + */ +static int get_slave_ports(unsigned int part_num) +{ + /* Macro to match CCI products */ +#define RET_ON_MATCH(product) \ + case CCI ## product ## _PART_NUM: \ + return CCI ## product ## _SLAVE_PORTS + + switch (part_num) { + + RET_ON_MATCH(400); + RET_ON_MATCH(500); + RET_ON_MATCH(550); + + default: + return -1; + } + +#undef RET_ON_MATCH +} #endif /* ENABLE_ASSERTIONS */ -void cci_init(uintptr_t cci_base, - const int *map, - unsigned int num_cci_masters) +void cci_init(uintptr_t base, const int *map, unsigned int num_cci_masters) { assert(map); - assert(cci_base); + assert(base); - g_cci_base = cci_base; + cci_base = base; + cci_slave_if_map = map; +#if ENABLE_ASSERTIONS /* * Master Id's are assigned from zero, So in an array of size n * the max master id is (n - 1). */ - g_max_master_id = num_cci_masters - 1; + max_master_id = num_cci_masters - 1; + cci_num_slave_ports = get_slave_ports(read_cci_part_number(base)); +#endif + assert(cci_num_slave_ports >= 0); assert(validate_cci_map(map)); - g_cci_slave_if_map = map; } void cci_enable_snoop_dvm_reqs(unsigned int master_id) { - int slave_if_id; + int slave_if_id = cci_slave_if_map[master_id]; - assert(g_cci_base); - assert(master_id <= g_max_master_id); - - slave_if_id = g_cci_slave_if_map[master_id]; - assert((slave_if_id < CCI_SLAVE_INTERFACE_COUNT) && (slave_if_id >= 0)); + assert(master_id <= max_master_id); + assert((slave_if_id < cci_num_slave_ports) && (slave_if_id >= 0)); + assert(cci_base); /* * Enable Snoops and DVM messages, no need for Read/Modify/Write as * rest of bits are write ignore */ - mmio_write_32(g_cci_base + - SLAVE_IFACE_OFFSET(slave_if_id) + - SNOOP_CTRL_REG, DVM_EN_BIT | SNOOP_EN_BIT); + mmio_write_32(cci_base + + SLAVE_IFACE_OFFSET(slave_if_id) + SNOOP_CTRL_REG, + DVM_EN_BIT | SNOOP_EN_BIT); /* Wait for the dust to settle down */ - while (mmio_read_32(g_cci_base + STATUS_REG) & CHANGE_PENDING_BIT) + while (mmio_read_32(cci_base + STATUS_REG) & CHANGE_PENDING_BIT) ; } void cci_disable_snoop_dvm_reqs(unsigned int master_id) { - int slave_if_id; - - assert(g_cci_base); - assert(master_id <= g_max_master_id); + int slave_if_id = cci_slave_if_map[master_id]; - slave_if_id = g_cci_slave_if_map[master_id]; - assert((slave_if_id < CCI_SLAVE_INTERFACE_COUNT) && (slave_if_id >= 0)); + assert(master_id <= max_master_id); + assert((slave_if_id < cci_num_slave_ports) && (slave_if_id >= 0)); + assert(cci_base); /* * Disable Snoops and DVM messages, no need for Read/Modify/Write as * rest of bits are write ignore. */ - mmio_write_32(g_cci_base + - SLAVE_IFACE_OFFSET(slave_if_id) + - SNOOP_CTRL_REG, ~(DVM_EN_BIT | SNOOP_EN_BIT)); + mmio_write_32(cci_base + + SLAVE_IFACE_OFFSET(slave_if_id) + SNOOP_CTRL_REG, + ~(DVM_EN_BIT | SNOOP_EN_BIT)); /* Wait for the dust to settle down */ - while (mmio_read_32(g_cci_base + STATUS_REG) & CHANGE_PENDING_BIT) + while (mmio_read_32(cci_base + STATUS_REG) & CHANGE_PENDING_BIT) ; } diff --git a/drivers/arm/smmu/smmu_v3.c b/drivers/arm/smmu/smmu_v3.c new file mode 100644 index 0000000000000000000000000000000000000000..cfe8c2a473c16bcc862ac6565514a94c134bb050 --- /dev/null +++ b/drivers/arm/smmu/smmu_v3.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <mmio.h> +#include <smmu_v3.h> + +/* Test for pending invalidate */ +#define INVAL_PENDING(base) \ + smmuv3_read_s_init(base) & SMMU_S_INIT_INV_ALL_MASK + +static inline uint32_t smmuv3_read_s_idr1(uintptr_t base) +{ + return mmio_read_32(base + SMMU_S_IDR1); +} + +static inline uint32_t smmuv3_read_s_init(uintptr_t base) +{ + return mmio_read_32(base + SMMU_S_INIT); +} + +static inline void smmuv3_write_s_init(uintptr_t base, uint32_t value) +{ + mmio_write_32(base + SMMU_S_INIT, value); +} + +/* + * Initialize the SMMU by invalidating all secure caches and TLBs. + * + * Returns 0 on success, and -1 on failure. + */ +int smmuv3_init(uintptr_t smmu_base) +{ + uint32_t idr1_reg; + + /* + * Invalidation of secure caches and TLBs is required only if the SMMU + * supports secure state. If not, it's implementation defined as to how + * SMMU_S_INIT register is accessed. + */ + idr1_reg = smmuv3_read_s_idr1(smmu_base); + if (!((idr1_reg >> SMMU_S_IDR1_SECURE_IMPL_SHIFT) & + SMMU_S_IDR1_SECURE_IMPL_MASK)) { + return -1; + } + + /* Initiate invalidation, and wait for it to finish */ + smmuv3_write_s_init(smmu_base, SMMU_S_INIT_INV_ALL_MASK); + while (INVAL_PENDING(smmu_base)) + ; + + return 0; +} diff --git a/fdts/fvp-base-gicv3-psci-1t.dtb b/fdts/fvp-base-gicv3-psci-1t.dtb new file mode 100644 index 0000000000000000000000000000000000000000..23d360fc2755ccb504afa4264a4105ea0b5a64bc Binary files /dev/null and b/fdts/fvp-base-gicv3-psci-1t.dtb differ diff --git a/fdts/fvp-base-gicv3-psci-1t.dts b/fdts/fvp-base-gicv3-psci-1t.dts new file mode 100644 index 0000000000000000000000000000000000000000..36fbd44442a227ec36dc7bfc9d02bbb44f1b743f --- /dev/null +++ b/fdts/fvp-base-gicv3-psci-1t.dts @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/include/ "fvp-base-gicv3-psci-common.dtsi" + +&CPU0 { + reg = <0x0 0x0>; +}; + +&CPU1 { + reg = <0x0 0x100>; +}; + +&CPU2 { + reg = <0x0 0x200>; +}; + +&CPU3 { + reg = <0x0 0x300>; +}; + +&CPU4 { + reg = <0x0 0x10000>; +}; + +&CPU5 { + reg = <0x0 0x10100>; +}; + +&CPU6 { + reg = <0x0 0x10200>; +}; + +&CPU7 { + reg = <0x0 0x10300>; +}; diff --git a/fdts/fvp-base-gicv3-psci-common.dtsi b/fdts/fvp-base-gicv3-psci-common.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..2ef2df8ddbf1ea2a3dc74da752650cfee5b6ea95 --- /dev/null +++ b/fdts/fvp-base-gicv3-psci-common.dtsi @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/memreserve/ 0x80000000 0x00010000; + +/ { +}; + +/ { + model = "FVP Base"; + compatible = "arm,vfp-base", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + aliases { + serial0 = &v2m_serial0; + serial1 = &v2m_serial1; + serial2 = &v2m_serial2; + serial3 = &v2m_serial3; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; + method = "smc"; + cpu_suspend = <0xc4000001>; + cpu_off = <0x84000002>; + cpu_on = <0xc4000003>; + sys_poweroff = <0x84000008>; + sys_reset = <0x84000009>; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu-map { + cluster0 { + core0 { + cpu = <&CPU0>; + }; + core1 { + cpu = <&CPU1>; + }; + core2 { + cpu = <&CPU2>; + }; + core3 { + cpu = <&CPU3>; + }; + }; + + cluster1 { + core0 { + cpu = <&CPU4>; + }; + core1 { + cpu = <&CPU5>; + }; + core2 { + cpu = <&CPU6>; + }; + core3 { + cpu = <&CPU7>; + }; + }; + }; + + idle-states { + entry-method = "arm,psci"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <40>; + exit-latency-us = <100>; + min-residency-us = <150>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <500>; + exit-latency-us = <1000>; + min-residency-us = <2500>; + }; + }; + + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x0>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + next-level-cache = <&L2_0>; + }; + + CPU1:cpu@1 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x1>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + next-level-cache = <&L2_0>; + }; + + CPU2:cpu@2 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x2>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + next-level-cache = <&L2_0>; + }; + + CPU3:cpu@3 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x3>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + next-level-cache = <&L2_0>; + }; + + CPU4:cpu@100 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x100>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + next-level-cache = <&L2_0>; + }; + + CPU5:cpu@101 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x101>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + next-level-cache = <&L2_0>; + }; + + CPU6:cpu@102 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x102>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + next-level-cache = <&L2_0>; + }; + + CPU7:cpu@103 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x103>; + enable-method = "psci"; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + next-level-cache = <&L2_0>; + }; + + L2_0: l2-cache0 { + compatible = "cache"; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0 0x7F000000>, + <0x00000008 0x80000000 0 0x80000000>; + }; + + gic: interrupt-controller@2f000000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + interrupt-controller; + reg = <0x0 0x2f000000 0 0x10000>, // GICD + <0x0 0x2f100000 0 0x200000>, // GICR + <0x0 0x2c000000 0 0x2000>, // GICC + <0x0 0x2c010000 0 0x2000>, // GICH + <0x0 0x2c02f000 0 0x2000>; // GICV + interrupts = <1 9 4>; + + its: its@2f020000 { + compatible = "arm,gic-v3-its"; + msi-controller; + reg = <0x0 0x2f020000 0x0 0x20000>; // GITS + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <1 13 0xff01>, + <1 14 0xff01>, + <1 11 0xff01>, + <1 10 0xff01>; + clock-frequency = <100000000>; + }; + + timer@2a810000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x2a810000 0x0 0x10000>; + clock-frequency = <100000000>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + frame@2a830000 { + frame-number = <1>; + interrupts = <0 26 4>; + reg = <0x0 0x2a830000 0x0 0x10000>; + }; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <0 60 4>, + <0 61 4>, + <0 62 4>, + <0 63 4>; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + /include/ "rtsm_ve-motherboard.dtsi" + }; + + panels { + panel@0 { + compatible = "panel"; + mode = "XVGA"; + refresh = <60>; + xres = <1024>; + yres = <768>; + pixclock = <15748>; + left_margin = <152>; + right_margin = <48>; + upper_margin = <23>; + lower_margin = <3>; + hsync_len = <104>; + vsync_len = <4>; + sync = <0>; + vmode = "FB_VMODE_NONINTERLACED"; + tim2 = "TIM2_BCD", "TIM2_IPC"; + cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)"; + caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888"; + bpp = <16>; + }; + }; +}; diff --git a/fdts/fvp-base-gicv3-psci.dts b/fdts/fvp-base-gicv3-psci.dts index d81bfbb7b14b07d1e20dd69ffecab4b26046acd9..3ea429ce97b3e360586d2ebd73bc20adca5e790b 100644 --- a/fdts/fvp-base-gicv3-psci.dts +++ b/fdts/fvp-base-gicv3-psci.dts @@ -6,265 +6,4 @@ /dts-v1/; -/memreserve/ 0x80000000 0x00010000; - -/ { -}; - -/ { - model = "FVP Base"; - compatible = "arm,vfp-base", "arm,vexpress"; - interrupt-parent = <&gic>; - #address-cells = <2>; - #size-cells = <2>; - - chosen { }; - - aliases { - serial0 = &v2m_serial0; - serial1 = &v2m_serial1; - serial2 = &v2m_serial2; - serial3 = &v2m_serial3; - }; - - psci { - compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; - method = "smc"; - cpu_suspend = <0xc4000001>; - cpu_off = <0x84000002>; - cpu_on = <0xc4000003>; - sys_poweroff = <0x84000008>; - sys_reset = <0x84000009>; - }; - - cpus { - #address-cells = <2>; - #size-cells = <0>; - - cpu-map { - cluster0 { - core0 { - cpu = <&CPU0>; - }; - core1 { - cpu = <&CPU1>; - }; - core2 { - cpu = <&CPU2>; - }; - core3 { - cpu = <&CPU3>; - }; - }; - - cluster1 { - core0 { - cpu = <&CPU4>; - }; - core1 { - cpu = <&CPU5>; - }; - core2 { - cpu = <&CPU6>; - }; - core3 { - cpu = <&CPU7>; - }; - }; - }; - - idle-states { - entry-method = "arm,psci"; - - CPU_SLEEP_0: cpu-sleep-0 { - compatible = "arm,idle-state"; - local-timer-stop; - arm,psci-suspend-param = <0x0010000>; - entry-latency-us = <40>; - exit-latency-us = <100>; - min-residency-us = <150>; - }; - - CLUSTER_SLEEP_0: cluster-sleep-0 { - compatible = "arm,idle-state"; - local-timer-stop; - arm,psci-suspend-param = <0x1010000>; - entry-latency-us = <500>; - exit-latency-us = <1000>; - min-residency-us = <2500>; - }; - }; - - CPU0:cpu@0 { - device_type = "cpu"; - compatible = "arm,armv8"; - reg = <0x0 0x0>; - enable-method = "psci"; - cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; - next-level-cache = <&L2_0>; - }; - - CPU1:cpu@1 { - device_type = "cpu"; - compatible = "arm,armv8"; - reg = <0x0 0x1>; - enable-method = "psci"; - cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; - next-level-cache = <&L2_0>; - }; - - CPU2:cpu@2 { - device_type = "cpu"; - compatible = "arm,armv8"; - reg = <0x0 0x2>; - enable-method = "psci"; - cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; - next-level-cache = <&L2_0>; - }; - - CPU3:cpu@3 { - device_type = "cpu"; - compatible = "arm,armv8"; - reg = <0x0 0x3>; - enable-method = "psci"; - cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; - next-level-cache = <&L2_0>; - }; - - CPU4:cpu@100 { - device_type = "cpu"; - compatible = "arm,armv8"; - reg = <0x0 0x100>; - enable-method = "psci"; - cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; - next-level-cache = <&L2_0>; - }; - - CPU5:cpu@101 { - device_type = "cpu"; - compatible = "arm,armv8"; - reg = <0x0 0x101>; - enable-method = "psci"; - cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; - next-level-cache = <&L2_0>; - }; - - CPU6:cpu@102 { - device_type = "cpu"; - compatible = "arm,armv8"; - reg = <0x0 0x102>; - enable-method = "psci"; - cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; - next-level-cache = <&L2_0>; - }; - - CPU7:cpu@103 { - device_type = "cpu"; - compatible = "arm,armv8"; - reg = <0x0 0x103>; - enable-method = "psci"; - cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; - next-level-cache = <&L2_0>; - }; - - L2_0: l2-cache0 { - compatible = "cache"; - }; - }; - - memory@80000000 { - device_type = "memory"; - reg = <0x00000000 0x80000000 0 0x7F000000>, - <0x00000008 0x80000000 0 0x80000000>; - }; - - gic: interrupt-controller@2f000000 { - compatible = "arm,gic-v3"; - #interrupt-cells = <3>; - #address-cells = <2>; - #size-cells = <2>; - ranges; - interrupt-controller; - reg = <0x0 0x2f000000 0 0x10000>, // GICD - <0x0 0x2f100000 0 0x200000>, // GICR - <0x0 0x2c000000 0 0x2000>, // GICC - <0x0 0x2c010000 0 0x2000>, // GICH - <0x0 0x2c02f000 0 0x2000>; // GICV - interrupts = <1 9 4>; - - its: its@2f020000 { - compatible = "arm,gic-v3-its"; - msi-controller; - reg = <0x0 0x2f020000 0x0 0x20000>; // GITS - }; - }; - - timer { - compatible = "arm,armv8-timer"; - interrupts = <1 13 0xff01>, - <1 14 0xff01>, - <1 11 0xff01>, - <1 10 0xff01>; - clock-frequency = <100000000>; - }; - - timer@2a810000 { - compatible = "arm,armv7-timer-mem"; - reg = <0x0 0x2a810000 0x0 0x10000>; - clock-frequency = <100000000>; - #address-cells = <2>; - #size-cells = <2>; - ranges; - frame@2a830000 { - frame-number = <1>; - interrupts = <0 26 4>; - reg = <0x0 0x2a830000 0x0 0x10000>; - }; - }; - - pmu { - compatible = "arm,armv8-pmuv3"; - interrupts = <0 60 4>, - <0 61 4>, - <0 62 4>, - <0 63 4>; - }; - - smb { - compatible = "simple-bus"; - - #address-cells = <2>; - #size-cells = <1>; - ranges = <0 0 0 0x08000000 0x04000000>, - <1 0 0 0x14000000 0x04000000>, - <2 0 0 0x18000000 0x04000000>, - <3 0 0 0x1c000000 0x04000000>, - <4 0 0 0x0c000000 0x04000000>, - <5 0 0 0x10000000 0x04000000>; - - /include/ "rtsm_ve-motherboard.dtsi" - }; - - panels { - panel@0 { - compatible = "panel"; - mode = "XVGA"; - refresh = <60>; - xres = <1024>; - yres = <768>; - pixclock = <15748>; - left_margin = <152>; - right_margin = <48>; - upper_margin = <23>; - lower_margin = <3>; - hsync_len = <104>; - vsync_len = <4>; - sync = <0>; - vmode = "FB_VMODE_NONINTERLACED"; - tim2 = "TIM2_BCD", "TIM2_IPC"; - cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)"; - caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888"; - bpp = <16>; - }; - }; -}; +/include/ "fvp-base-gicv3-psci-common.dtsi" diff --git a/include/drivers/arm/cci.h b/include/drivers/arm/cci.h index 5ac79c61fb107fbaa6f86dbcb5e7b10996be8048..1def6a8f23c82f31012a9e4611b058685c7541f8 100644 --- a/include/drivers/arm/cci.h +++ b/include/drivers/arm/cci.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -98,14 +98,6 @@ #define SLAVE_IF_UNUSED -1 -#if ARM_CCI_PRODUCT_ID == 400 - #define CCI_SLAVE_INTERFACE_COUNT 5 -#elif ARM_CCI_PRODUCT_ID == 500 - #define CCI_SLAVE_INTERFACE_COUNT 7 -#else - #error "Invalid CCI product or CCI not supported" -#endif - #ifndef __ASSEMBLY__ #include <stdint.h> @@ -114,7 +106,7 @@ /* * The ARM CCI driver needs the following: - * 1. Base address of the CCI-500/CCI-400 + * 1. Base address of the CCI product * 2. An array of map between AMBA 4 master ids and ACE/ACE lite slave * interfaces. * 3. Size of the array. @@ -122,9 +114,7 @@ * SLAVE_IF_UNUSED should be used in the map to represent no AMBA 4 master exists * for that interface. */ -void cci_init(uintptr_t cci_base, - const int *map, - unsigned int num_cci_masters); +void cci_init(uintptr_t base, const int *map, unsigned int num_cci_masters); void cci_enable_snoop_dvm_reqs(unsigned int master_id); void cci_disable_snoop_dvm_reqs(unsigned int master_id); diff --git a/include/drivers/arm/smmu_v3.h b/include/drivers/arm/smmu_v3.h new file mode 100644 index 0000000000000000000000000000000000000000..b7efde46222b8b4cfebbc25edd0b13f67a942518 --- /dev/null +++ b/include/drivers/arm/smmu_v3.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SMMU_V3_H__ +#define __SMMU_V3_H__ + +#include <stdint.h> + +/* SMMUv3 register offsets from device base */ +#define SMMU_S_IDR1 0x8004 +#define SMMU_S_INIT 0x803c + +/* SMMU_S_IDR1 register fields */ +#define SMMU_S_IDR1_SECURE_IMPL_SHIFT 31 +#define SMMU_S_IDR1_SECURE_IMPL_MASK 0x1 + +/* SMMU_S_INIT register fields */ +#define SMMU_S_INIT_INV_ALL_MASK 0x1 + + +int smmuv3_init(uintptr_t smmu_base); + +#endif /* __SMMU_V3_H__ */ diff --git a/include/plat/arm/common/arm_config.h b/include/plat/arm/common/arm_config.h index 2ab7bf2e391e5d67a4191bbf1f2990ff6d79e9ed..02e04fd3be215e4912506d565f2980a6cb788d7f 100644 --- a/include/plat/arm/common/arm_config.h +++ b/include/plat/arm/common/arm_config.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,14 +7,20 @@ #define __ARM_CONFIG_H__ #include <stdint.h> +#include <utils_def.h> enum arm_config_flags { /* Whether Base memory map is in use */ - ARM_CONFIG_BASE_MMAP = 0x1, - /* Whether interconnect should be enabled */ - ARM_CONFIG_HAS_INTERCONNECT = 0x2, + ARM_CONFIG_BASE_MMAP = BIT(1), /* Whether TZC should be configured */ - ARM_CONFIG_HAS_TZC = 0x4 + ARM_CONFIG_HAS_TZC = BIT(2), + /* FVP model has shifted affinity */ + ARM_CONFIG_FVP_SHIFTED_AFF = BIT(3), + /* FVP model has SMMUv3 affinity */ + ARM_CONFIG_FVP_HAS_SMMUV3 = BIT(4), + /* FVP model has CCI (400 or 500/550) devices */ + ARM_CONFIG_FVP_HAS_CCI400 = BIT(5), + ARM_CONFIG_FVP_HAS_CCI5XX = BIT(6), }; typedef struct arm_config { diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index 9946fea109f6ddf397386a8e23607744074ed196..302d937f30fade7ab086c08ef659aab86adaeaf9 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -16,10 +16,6 @@ AARCH32_SP := none # The Target build architecture. Supported values are: aarch64, aarch32. ARCH := aarch64 -# Determine the version of ARM CCI product used in the platform. The platform -# port can change this value if needed. -ARM_CCI_PRODUCT_ID := 400 - # ARM Architecture major and minor versions: 8.0 by default. ARM_ARCH_MAJOR := 8 ARM_ARCH_MINOR := 0 diff --git a/plat/arm/board/fvp/aarch32/fvp_helpers.S b/plat/arm/board/fvp/aarch32/fvp_helpers.S index e80e199107dc4ad034ca79a51b8a4f68768834d6..143972d26813061863dca1be47cc4c6fc849dc50 100644 --- a/plat/arm/board/fvp/aarch32/fvp_helpers.S +++ b/plat/arm/board/fvp/aarch32/fvp_helpers.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -13,6 +13,7 @@ .globl plat_secondary_cold_boot_setup .globl plat_get_my_entrypoint .globl plat_is_my_cpu_primary + .globl plat_arm_calc_core_pos /* -------------------------------------------------------------------- * void plat_secondary_cold_boot_setup (void); @@ -95,10 +96,43 @@ endfunc plat_get_my_entrypoint */ func plat_is_my_cpu_primary ldcopr r0, MPIDR - ldr r1, =(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + ldr r1, =MPIDR_AFFINITY_MASK and r0, r1 cmp r0, #FVP_PRIMARY_CPU moveq r0, #1 movne r0, #0 bx lr endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Function to calculate the core position on FVP. + * + * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER) + + * (CPUId * FVP_MAX_PE_PER_CPU) + + * ThreadId + * ----------------------------------------------------- + */ +func plat_arm_calc_core_pos + mov r3, r0 + + /* + * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it + * look as if in a multi-threaded implementation + */ + tst r0, #MPIDR_MT_MASK + lsleq r3, r0, #MPIDR_AFFINITY_BITS + + /* Extract individual affinity fields from MPIDR */ + mov r2, #FVP_MAX_PE_PER_CPU + ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + mla r0, r1, r2, r0 + + mov r1, #FVP_MAX_CPUS_PER_CLUSTER + ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + mla r0, r1, r2, r0 + + bx lr +endfunc plat_arm_calc_core_pos diff --git a/plat/arm/board/fvp/aarch64/fvp_helpers.S b/plat/arm/board/fvp/aarch64/fvp_helpers.S index f4107de0d287ba8259701f43d3bec01f9ae8927e..6ea4585154a198340dfe9cdca1664020cafab010 100644 --- a/plat/arm/board/fvp/aarch64/fvp_helpers.S +++ b/plat/arm/board/fvp/aarch64/fvp_helpers.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -16,6 +16,7 @@ .globl plat_secondary_cold_boot_setup .globl plat_get_my_entrypoint .globl plat_is_my_cpu_primary + .globl plat_arm_calc_core_pos .macro fvp_choose_gicmmap param1, param2, x_tmp, w_tmp, res ldr \x_tmp, =V2M_SYSREGS_BASE + V2M_SYS_ID @@ -170,8 +171,43 @@ endfunc plat_get_my_entrypoint */ func plat_is_my_cpu_primary mrs x0, mpidr_el1 - and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + ldr x1, =MPIDR_AFFINITY_MASK + and x0, x0, x1 cmp x0, #FVP_PRIMARY_CPU cset w0, eq ret endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * unsigned int plat_arm_calc_core_pos(u_register_t mpidr) + * + * Function to calculate the core position on FVP. + * + * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER) + + * (CPUId * FVP_MAX_PE_PER_CPU) + + * ThreadId + * ----------------------------------------------------- + */ +func plat_arm_calc_core_pos + mov x3, x0 + + /* + * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it + * look as if in a multi-threaded implementation. + */ + tst x0, #MPIDR_MT_MASK + lsl x3, x0, #MPIDR_AFFINITY_BITS + csel x3, x3, x0, eq + + /* Extract individual affinity fields from MPIDR */ + ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + + /* Compute linear position */ + mov x4, #FVP_MAX_PE_PER_CPU + madd x0, x1, x4, x0 + mov x5, #FVP_MAX_CPUS_PER_CLUSTER + madd x0, x2, x5, x0 + ret +endfunc plat_arm_calc_core_pos diff --git a/plat/arm/board/fvp/fvp_bl31_setup.c b/plat/arm/board/fvp/fvp_bl31_setup.c index 52a4432dfe0e2bcce708aad0fa79f5aa0fe7a676..181c92319be5f7a7e70599e8457f3f0732bc14b1 100644 --- a/plat/arm/board/fvp/fvp_bl31_setup.c +++ b/plat/arm/board/fvp/fvp_bl31_setup.c @@ -1,10 +1,12 @@ /* - * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ +#include <arm_config.h> #include <plat_arm.h> +#include <smmu_v3.h> #include "fvp_private.h" #if LOAD_IMAGE_V2 @@ -34,4 +36,8 @@ void bl31_early_platform_setup(bl31_params_t *from_bl2, * FVP PSCI code will enable coherency for other clusters. */ fvp_interconnect_enable(); + + /* On FVP RevC, intialize SMMUv3 */ + if (arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) + smmuv3_init(PLAT_FVP_SMMUV3_BASE); } diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c index 2f5d7fcf5f64407ab8d13c50e695aaacfeef2d90..c1dcc02c60cab221bd0017438e981cbb9f862942 100644 --- a/plat/arm/board/fvp/fvp_common.c +++ b/plat/arm/board/fvp/fvp_common.c @@ -1,11 +1,13 @@ /* - * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include <arm_config.h> #include <arm_def.h> +#include <assert.h> +#include <cci.h> #include <ccn.h> #include <debug.h> #include <gicv2.h> @@ -118,6 +120,30 @@ const mmap_region_t plat_arm_mmap[] = { ARM_CASSERT_MMAP +#if FVP_INTERCONNECT_DRIVER != FVP_CCN +static const int fvp_cci400_map[] = { + PLAT_FVP_CCI400_CLUS0_SL_PORT, + PLAT_FVP_CCI400_CLUS1_SL_PORT, +}; + +static const int fvp_cci5xx_map[] = { + PLAT_FVP_CCI5XX_CLUS0_SL_PORT, + PLAT_FVP_CCI5XX_CLUS1_SL_PORT, +}; + +static unsigned int get_interconnect_master(void) +{ + unsigned int master; + u_register_t mpidr; + + mpidr = read_mpidr_el1(); + master = (arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) ? + MPIDR_AFFLVL2_VAL(mpidr) : MPIDR_AFFLVL1_VAL(mpidr); + + assert(master < FVP_CLUSTER_COUNT); + return master; +} +#endif /******************************************************************************* * A single boot loader stack is expected to work on both the Foundation FVP @@ -182,8 +208,7 @@ void fvp_config_setup(void) } break; case HBI_BASE_FVP: - arm_config.flags |= ARM_CONFIG_BASE_MMAP | - ARM_CONFIG_HAS_INTERCONNECT | ARM_CONFIG_HAS_TZC; + arm_config.flags |= (ARM_CONFIG_BASE_MMAP | ARM_CONFIG_HAS_TZC); /* * Check for supported revisions @@ -191,6 +216,12 @@ void fvp_config_setup(void) */ switch (rev) { case REV_BASE_FVP_V0: + arm_config.flags |= ARM_CONFIG_FVP_HAS_CCI400; + break; + case REV_BASE_FVP_REVC: + arm_config.flags |= (ARM_CONFIG_FVP_SHIFTED_AFF | + ARM_CONFIG_FVP_HAS_SMMUV3 | + ARM_CONFIG_FVP_HAS_CCI5XX); break; default: WARN("Unrecognized Base FVP revision %x\n", rev); @@ -206,26 +237,67 @@ void fvp_config_setup(void) void fvp_interconnect_init(void) { - if (arm_config.flags & ARM_CONFIG_HAS_INTERCONNECT) { #if FVP_INTERCONNECT_DRIVER == FVP_CCN - if (ccn_get_part0_id(PLAT_ARM_CCN_BASE) != CCN_502_PART0_ID) { - ERROR("Unrecognized CCN variant detected. Only CCN-502" - " is supported"); - panic(); - } -#endif - plat_arm_interconnect_init(); + if (ccn_get_part0_id(PLAT_ARM_CCN_BASE) != CCN_502_PART0_ID) { + ERROR("Unrecognized CCN variant detected. Only CCN-502" + " is supported"); + panic(); + } + + plat_arm_interconnect_init(); +#else + uintptr_t cci_base = 0; + const int *cci_map = 0; + unsigned int map_size = 0; + + if (!(arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 | + ARM_CONFIG_FVP_HAS_CCI5XX))) { + return; + } + + /* Initialize the right interconnect */ + if (arm_config.flags & ARM_CONFIG_FVP_HAS_CCI5XX) { + cci_base = PLAT_FVP_CCI5XX_BASE; + cci_map = fvp_cci5xx_map; + map_size = ARRAY_SIZE(fvp_cci5xx_map); + } else if (arm_config.flags & ARM_CONFIG_FVP_HAS_CCI400) { + cci_base = PLAT_FVP_CCI400_BASE; + cci_map = fvp_cci400_map; + map_size = ARRAY_SIZE(fvp_cci400_map); } + + assert(cci_base); + assert(cci_map); + cci_init(cci_base, cci_map, map_size); +#endif } void fvp_interconnect_enable(void) { - if (arm_config.flags & ARM_CONFIG_HAS_INTERCONNECT) - plat_arm_interconnect_enter_coherency(); +#if FVP_INTERCONNECT_DRIVER == FVP_CCN + plat_arm_interconnect_enter_coherency(); +#else + unsigned int master; + + if (arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 | + ARM_CONFIG_FVP_HAS_CCI5XX)) { + master = get_interconnect_master(); + cci_enable_snoop_dvm_reqs(master); + } +#endif } void fvp_interconnect_disable(void) { - if (arm_config.flags & ARM_CONFIG_HAS_INTERCONNECT) - plat_arm_interconnect_exit_coherency(); +#if FVP_INTERCONNECT_DRIVER == FVP_CCN + plat_arm_interconnect_exit_coherency(); +#else + unsigned int master; + + if (arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 | + ARM_CONFIG_FVP_HAS_CCI5XX)) { + master = get_interconnect_master(); + cci_disable_snoop_dvm_reqs(master); + } +#endif } diff --git a/plat/arm/board/fvp/fvp_def.h b/plat/arm/board/fvp/fvp_def.h index d4f9d925f14c9f7cb38245a5180b3a2eca442344..a430bcac1ac772bfa1547ece5d4fcd4194cb61dc 100644 --- a/plat/arm/board/fvp/fvp_def.h +++ b/plat/arm/board/fvp/fvp_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -12,6 +12,10 @@ #endif #define FVP_MAX_CPUS_PER_CLUSTER 4 +#ifndef FVP_MAX_PE_PER_CPU +# define FVP_MAX_PE_PER_CPU 1 +#endif + #define FVP_PRIMARY_CPU 0x0 /* Defines for the Interconnect build selection */ @@ -74,6 +78,7 @@ /* Constants to distinguish FVP type */ #define HBI_BASE_FVP 0x020 #define REV_BASE_FVP_V0 0x0 +#define REV_BASE_FVP_REVC 0x2 #define HBI_FOUNDATION_FVP 0x010 #define REV_FOUNDATION_FVP_V2_0 0x0 diff --git a/plat/arm/board/fvp/fvp_topology.c b/plat/arm/board/fvp/fvp_topology.c index 055b985a061316176db4acc4412551995df147a0..cf1492b676a7ab60eac9991d310c58ad035e8bc2 100644 --- a/plat/arm/board/fvp/fvp_topology.c +++ b/plat/arm/board/fvp/fvp_topology.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include <arch.h> +#include <arm_config.h> #include <cassert.h> #include <plat_arm.h> #include <platform_def.h> @@ -55,11 +56,38 @@ unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr) ******************************************************************************/ int plat_core_pos_by_mpidr(u_register_t mpidr) { - if (arm_check_mpidr(mpidr) == -1) + unsigned int clus_id, cpu_id, thread_id; + + /* Validate affinity fields */ + if (arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) { + thread_id = MPIDR_AFFLVL0_VAL(mpidr); + cpu_id = MPIDR_AFFLVL1_VAL(mpidr); + clus_id = MPIDR_AFFLVL2_VAL(mpidr); + } else { + thread_id = 0; + cpu_id = MPIDR_AFFLVL0_VAL(mpidr); + clus_id = MPIDR_AFFLVL1_VAL(mpidr); + } + + if (clus_id >= FVP_CLUSTER_COUNT) + return -1; + if (cpu_id >= FVP_MAX_CPUS_PER_CLUSTER) + return -1; + if (thread_id >= FVP_MAX_PE_PER_CPU) return -1; if (fvp_pwrc_read_psysr(mpidr) == PSYSR_INVALID) return -1; + /* + * Core position calculation for FVP platform depends on the MT bit in + * MPIDR. This function cannot assume that the supplied MPIDR has the MT + * bit set even if the implementation has. For example, PSCI clients + * might supply MPIDR values without the MT bit set. Therefore, we + * inject the current PE's MT bit so as to get the calculation correct. + * This of course assumes that none or all CPUs on the platform has MT + * bit set. + */ + mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); return plat_arm_calc_core_pos(mpidr); } diff --git a/plat/arm/board/fvp/include/plat_macros.S b/plat/arm/board/fvp/include/plat_macros.S index d3d70e45d7809c64533fd496f6066aad281a411f..4dcde2d2743b164df031fa8438304fccaff1fa63 100644 --- a/plat/arm/board/fvp/include/plat_macros.S +++ b/plat/arm/board/fvp/include/plat_macros.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,15 +7,13 @@ #define __PLAT_MACROS_S__ #include <arm_macros.S> -#include <cci_macros.S> #include <v2m_def.h> #include "../fvp_def.h" /* --------------------------------------------- * The below required platform porting macro - * prints out relevant GIC and CCI registers - * whenever an unhandled exception is taken in - * BL31. + * prints out relevant GIC registers whenever an + * unhandled exception is taken in BL31. * Clobbers: x0 - x10, x16, x17, sp * --------------------------------------------- */ @@ -40,9 +38,6 @@ use_ve_mmap: mov_imm x16, VE_GICD_BASE print_gic_regs: arm_print_gic_regs -#if FVP_INTERCONNECT_DRIVER == FVP_CCI - print_cci_regs -#endif .endm #endif /* __PLAT_MACROS_S__ */ diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h index f13fc8e6133aa131cbe68d5ec0dd1d2274915b8f..bf038e92a665de32bd30d65ee76b6f0fd70ffc1a 100644 --- a/plat/arm/board/fvp/include/platform_def.h +++ b/plat/arm/board/fvp/include/platform_def.h @@ -16,10 +16,13 @@ #include "../fvp_def.h" /* Required platform porting definitions */ +#define PLATFORM_CORE_COUNT \ + (FVP_CLUSTER_COUNT * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU) + #define PLAT_NUM_PWR_DOMAINS (FVP_CLUSTER_COUNT + \ PLATFORM_CORE_COUNT) + #define PLAT_MAX_PWR_LVL ARM_PWR_LVL1 -#define PLATFORM_CORE_COUNT (FVP_CLUSTER_COUNT * FVP_MAX_CPUS_PER_CLUSTER) /* * Other platform porting definitions are provided by included headers @@ -65,10 +68,17 @@ #define PLAT_ARM_TSP_UART_BASE V2M_IOFPGA_UART2_BASE #define PLAT_ARM_TSP_UART_CLK_IN_HZ V2M_IOFPGA_UART2_CLK_IN_HZ +#define PLAT_FVP_SMMUV3_BASE 0x2b400000 + /* CCI related constants */ -#define PLAT_ARM_CCI_BASE 0x2c090000 -#define PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX 3 -#define PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX 4 +#define PLAT_FVP_CCI400_BASE 0x2c090000 +#define PLAT_FVP_CCI400_CLUS0_SL_PORT 3 +#define PLAT_FVP_CCI400_CLUS1_SL_PORT 4 + +/* CCI-500/CCI-550 on Base platform */ +#define PLAT_FVP_CCI5XX_BASE 0x2a000000 +#define PLAT_FVP_CCI5XX_CLUS0_SL_PORT 5 +#define PLAT_FVP_CCI5XX_CLUS1_SL_PORT 6 /* CCN related constants. Only CCN 502 is currently supported */ #define PLAT_ARM_CCN_BASE 0x2e000000 diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index d6e8ced43675de855e07fdcecdb6efd54beb16ed..0b6e1da54ae983b8805a1aa0deaa357a7eb64df3 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -6,19 +6,28 @@ # Use the GICv3 driver on the FVP by default FVP_USE_GIC_DRIVER := FVP_GICV3 + # Use the SP804 timer instead of the generic one FVP_USE_SP804_TIMER := 0 +# Default cluster count for FVP +FVP_CLUSTER_COUNT := 2 + +# Default number of threads per CPU on FVP +FVP_MAX_PE_PER_CPU := 1 + $(eval $(call assert_boolean,FVP_USE_SP804_TIMER)) $(eval $(call add_define,FVP_USE_SP804_TIMER)) # The FVP platform depends on this macro to build with correct GIC driver. $(eval $(call add_define,FVP_USE_GIC_DRIVER)) -# Define default FVP_CLUSTER_COUNT to 2 and pass it into the build system. -FVP_CLUSTER_COUNT := 2 +# Pass FVP_CLUSTER_COUNT to the build system. $(eval $(call add_define,FVP_CLUSTER_COUNT)) +# Pass FVP_MAX_PE_PER_CPU to the build system. +$(eval $(call add_define,FVP_MAX_PE_PER_CPU)) + # Sanity check the cluster count and if FVP_CLUSTER_COUNT <= 2, # choose the CCI driver , else the CCN driver ifeq ($(FVP_CLUSTER_COUNT), 0) @@ -63,8 +72,7 @@ $(error "Incorrect GIC driver chosen on FVP port") endif ifeq (${FVP_INTERCONNECT_DRIVER}, FVP_CCI) -FVP_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c \ - plat/arm/common/arm_cci.c +FVP_INTERCONNECT_SOURCES := drivers/arm/cci/cci.c else ifeq (${FVP_INTERCONNECT_DRIVER}, FVP_CCN) FVP_INTERCONNECT_SOURCES := drivers/arm/ccn/ccn.c \ plat/arm/common/arm_ccn.c @@ -127,7 +135,8 @@ endif BL2U_SOURCES += plat/arm/board/fvp/fvp_bl2u_setup.c \ ${FVP_SECURITY_SOURCES} -BL31_SOURCES += plat/arm/board/fvp/fvp_bl31_setup.c \ +BL31_SOURCES += drivers/arm/smmu/smmu_v3.c \ + plat/arm/board/fvp/fvp_bl31_setup.c \ plat/arm/board/fvp/fvp_pm.c \ plat/arm/board/fvp/fvp_topology.c \ plat/arm/board/fvp/aarch64/fvp_helpers.S \ diff --git a/plat/arm/common/arm_gicv3.c b/plat/arm/common/arm_gicv3.c index 960f69174df7ba85597c5a404ae134aa3ee60ece..c9bba095027f707ba32d74897e0caf0a861894c7 100644 --- a/plat/arm/common/arm_gicv3.c +++ b/plat/arm/common/arm_gicv3.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -35,6 +35,26 @@ static const unsigned int g0_interrupt_array[] = { PLAT_ARM_G0_IRQS }; +/* + * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register + * to core position. + * + * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity + * values read from GICR_TYPER don't have an MT field. To reuse the same + * translation used for CPUs, we insert MT bit read from the PE's MPIDR into + * that read from GICR_TYPER. + * + * Assumptions: + * + * - All CPUs implemented in the system have MPIDR_EL1.MT bit set; + * - No CPUs implemented in the system use affinity level 3. + */ +static unsigned int arm_gicv3_mpidr_hash(u_register_t mpidr) +{ + mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); + return plat_arm_calc_core_pos(mpidr); +} + const gicv3_driver_data_t arm_gic_data = { .gicd_base = PLAT_ARM_GICD_BASE, .gicr_base = PLAT_ARM_GICR_BASE, @@ -44,7 +64,7 @@ const gicv3_driver_data_t arm_gic_data = { .g1s_interrupt_array = g1s_interrupt_array, .rdistif_num = PLATFORM_CORE_COUNT, .rdistif_base_addrs = rdistif_base_addrs, - .mpidr_to_core_pos = plat_arm_calc_core_pos + .mpidr_to_core_pos = arm_gicv3_mpidr_hash }; void plat_arm_gic_driver_init(void) diff --git a/plat/common/aarch32/platform_mp_stack.S b/plat/common/aarch32/platform_mp_stack.S index e43047e551979037693fa1496f1213d0e7de244d..6c3d08de359dcbd53a042e478603d136ef743f56 100644 --- a/plat/common/aarch32/platform_mp_stack.S +++ b/plat/common/aarch32/platform_mp_stack.S @@ -19,9 +19,9 @@ * ----------------------------------------------------- */ func plat_get_my_stack - mov r3, lr + push {r4, lr} get_my_mp_stack platform_normal_stacks, PLATFORM_STACK_SIZE - bx r3 + pop {r4, pc} endfunc plat_get_my_stack /* ----------------------------------------------------- @@ -32,10 +32,10 @@ endfunc plat_get_my_stack * ----------------------------------------------------- */ func plat_set_my_stack - mov r3, lr + mov r4, lr get_my_mp_stack platform_normal_stacks, PLATFORM_STACK_SIZE mov sp, r0 - bx r3 + bx r4 endfunc plat_set_my_stack /* -----------------------------------------------------