diff --git a/fdts/tc-base.dtsi b/fdts/tc-base.dtsi index 2e03be2eb..fc6fe78b1 100644 --- a/fdts/tc-base.dtsi +++ b/fdts/tc-base.dtsi @@ -265,9 +265,22 @@ method = "smc"; }; - cpu-pmu { - compatible = "arm,armv8-pmuv3"; - interrupts = ; + cpu-pmu-little { + compatible = LIT_CPU_PMU_COMPATIBLE; + interrupts = ; + status = "okay"; + }; + + cpu-pmu-mid { + compatible = MID_CPU_PMU_COMPATIBLE; + interrupts = ; + status = "okay"; + }; + + cpu-pmu-big { + compatible = BIG_CPU_PMU_COMPATIBLE; + interrupts = ; + status = "okay"; }; sram: sram@6000000 { @@ -290,7 +303,7 @@ clocks = <&soc_refclk>; clock-names = "apb_pclk"; #mbox-cells = ; - interrupts = ; + interrupts = ; interrupt-names = MHU_RX_INT_NAME; }; @@ -332,21 +345,33 @@ gic: interrupt-controller@GIC_CTRL_ADDR { compatible = "arm,gic-v3"; #address-cells = <2>; - #interrupt-cells = <3>; + #interrupt-cells = <4>; #size-cells = <2>; ranges; interrupt-controller; reg = <0x0 0x30000000 0 0x10000>, /* GICD */ <0x0 0x30080000 0 GIC_GICR_OFFSET>; /* GICR */ - interrupts = ; + interrupts = ; }; timer { compatible = "arm,armv8-timer"; - interrupts = , - , - , - ; + interrupts = , + , + , + ; + }; + + spe-pmu-mid { + compatible = "arm,statistical-profiling-extension-v1"; + interrupts = ; + status = "disabled"; + }; + + spe-pmu-big { + compatible = "arm,statistical-profiling-extension-v1"; + interrupts = ; + status = "disabled"; }; soc_refclk: refclk { @@ -374,7 +399,7 @@ os_uart: serial@2a400000 { compatible = "arm,pl011", "arm,primecell"; reg = <0x0 0x2A400000 0x0 UART_OFFSET>; - interrupts = ; + interrupts = ; clocks = <&soc_uartclk>, <&soc_refclk>; clock-names = "uartclk", "apb_pclk"; status = "okay"; @@ -414,7 +439,7 @@ ethernet: ethernet@18000000 { reg = <0x0 0x18000000 0x0 0x10000>; - interrupts = ; + interrupts = ; reg-io-width = <2>; smsc,irq-push-pull; @@ -446,8 +471,8 @@ mmci: mmci@1c050000 { compatible = "arm,pl180", "arm,primecell"; reg = <0x0 0x001c050000 0x0 0x1000>; - interrupts = , - ; + interrupts = , + ; wp-gpios = <&sysreg 1 0>; bus-width = <4>; max-frequency = <25000000>; @@ -471,9 +496,9 @@ gpu: gpu@2d000000 { compatible = "arm,mali-midgard"; reg = <0x0 0x2d000000 0x0 0x200000>; - interrupts = , - , - ; + interrupts = , + , + ; interrupt-names = "JOB", "MMU", "GPU"; clocks = <&gpu_core_clk>; clock-names = "shadercores"; @@ -507,10 +532,10 @@ smmu_600: smmu@2ce00000 { compatible = "arm,smmu-v3"; reg = <0 0x2ce00000 0 0x20000>; - interrupts = , - , - , - ; + interrupts = , + , + , + ; interrupt-names = "eventq", "priq", "cmdq-sync", "gerror"; #iommu-cells = <1>; status = "disabled"; @@ -520,9 +545,9 @@ #iommu-cells = <1>; compatible = "arm,smmu-v3"; reg = <0x0 0x3f000000 0x0 0x5000000>; - interrupts = , - , - ; + interrupts = , + , + ; interrupt-names = "eventq", "cmdq-sync", "gerror"; dma-coherent; status = "disabled"; @@ -532,9 +557,9 @@ #iommu-cells = <1>; compatible = "arm,smmu-v3"; reg = ; - interrupts = , - , - ; + interrupts = , + , + ; interrupt-names = "eventq", "cmdq-sync", "gerror"; dma-coherent; status = "disabled"; @@ -545,7 +570,7 @@ #size-cells = <0>; compatible = "arm,mali-d71"; reg = ; - interrupts = ; + interrupts = ; interrupt-names = "DPU"; DPU_CLK_ATTR1; @@ -630,7 +655,7 @@ trbe { compatible = "arm,trace-buffer-extension"; - interrupts = ; + interrupts = ; }; trusty { diff --git a/fdts/tc-fvp.dtsi b/fdts/tc-fvp.dtsi index 9f3a9ac48..1e14f0bcb 100644 --- a/fdts/tc-fvp.dtsi +++ b/fdts/tc-fvp.dtsi @@ -54,7 +54,7 @@ rtc@1c170000 { compatible = "arm,pl031", "arm,primecell"; reg = <0x0 0x1C170000 0x0 0x1000>; - interrupts = ; + interrupts = ; clocks = <&soc_refclk>; clock-names = "apb_pclk"; }; @@ -62,7 +62,7 @@ kmi@1c060000 { compatible = "arm,pl050", "arm,primecell"; reg = <0x0 0x001c060000 0x0 0x1000>; - interrupts = ; + interrupts = ; clocks = <&bp_clock24mhz>, <&bp_clock24mhz>; clock-names = "KMIREFCLK", "apb_pclk"; }; @@ -70,7 +70,7 @@ kmi@1c070000 { compatible = "arm,pl050", "arm,primecell"; reg = <0x0 0x001c070000 0x0 0x1000>; - interrupts = ; + interrupts = ; clocks = <&bp_clock24mhz>, <&bp_clock24mhz>; clock-names = "KMIREFCLK", "apb_pclk"; }; @@ -79,6 +79,6 @@ compatible = "virtio,mmio"; reg = <0x0 0x1c130000 0x0 0x200>; /* spec lists this wrong */ - interrupts = ; + interrupts = ; }; }; diff --git a/fdts/tc2.dts b/fdts/tc2.dts index 4946acaae..ae37ce3ff 100644 --- a/fdts/tc2.dts +++ b/fdts/tc2.dts @@ -31,6 +31,10 @@ #define MHU_RX_INT_NUM 317 #define MHU_RX_INT_NAME "mhu_rx" +#define LIT_CPU_PMU_COMPATIBLE "arm,cortex-a520-pmu" +#define MID_CPU_PMU_COMPATIBLE "arm,cortex-a720-pmu" +#define BIG_CPU_PMU_COMPATIBLE "arm,cortex-x4-pmu" + #define MPAM_ADDR 0x1 0x00010000 /* 0x1_0001_0000 */ #define UARTCLK_FREQ 5000000 @@ -193,22 +197,10 @@ }; #endif /* TARGET_FLAVOUR_FPGA */ - cpu-pmu { -#if TARGET_FLAVOUR_FPGA - interrupt-affinity = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>, - <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>, - <&CPU8>, <&CPU9>, <&CPU10>, <&CPU11>, - <&CPU12>, <&CPU13>; -#else - interrupt-affinity = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>, - <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>; -#endif - }; - cmn-pmu { compatible = "arm,ci-700"; reg = <0x0 0x50000000 0x0 0x10000000>; - interrupts = ; + interrupts = ; }; mbox_db_rx: mhu@MHU_RX_ADDR { @@ -237,6 +229,36 @@ }; }; + gic: interrupt-controller@GIC_CTRL_ADDR { + ppi-partitions { + ppi_partition_little: interrupt-partition-0 { + affinity = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>; + }; + +#if TARGET_FLAVOUR_FVP + ppi_partition_mid: interrupt-partition-1 { + affinity = <&CPU4>, <&CPU5>, <&CPU6>; + }; + + ppi_partition_big: interrupt-partition-2 { + affinity = <&CPU7>; + }; +#elif TARGET_FLAVOUR_FPGA + ppi_partition_mid: interrupt-partition-1 { + affinity = <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>, <&CPU8>; + }; + + ppi_partition_big: interrupt-partition-2 { + affinity = <&CPU9>, <&CPU10>, <&CPU11>, <&CPU12>, <&CPU13>; + }; +#endif + }; + }; + + spe-pmu-big { + status = "okay"; + }; + smmu_700: iommu@3f000000 { status = "okay"; }; diff --git a/fdts/tc3.dts b/fdts/tc3.dts index 71b3cb18a..58c8edca0 100644 --- a/fdts/tc3.dts +++ b/fdts/tc3.dts @@ -25,6 +25,10 @@ #define MHU_RX_INT_NUM 300 #define MHU_RX_INT_NAME "combined-mbx" +#define LIT_CPU_PMU_COMPATIBLE "arm,cortex-a520-pmu" +#define MID_CPU_PMU_COMPATIBLE "arm,cortex-a725-pmu" +#define BIG_CPU_PMU_COMPATIBLE "arm,cortex-x925-pmu" + #define MPAM_ADDR 0x0 0x5f010000 /* 0x5f01_0000 */ #define UARTCLK_FREQ 3750000 @@ -67,11 +71,6 @@ }; }; - cpu-pmu { - interrupt-affinity = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>, - <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>; - }; - cs-pmu@0 { compatible = "arm,coresight-pmu"; reg = <0x0 MCN_PMU_ADDR(0) 0x0 0xffc>; @@ -92,11 +91,24 @@ reg = <0x0 MCN_PMU_ADDR(3) 0x0 0xffc>; }; + spe-pmu-mid { + status = "okay"; + }; + + spe-pmu-big { + status = "okay"; + }; + dsu-pmu { compatible = "arm,dsu-pmu"; cpus = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>, <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>; }; + ni-pmu { + compatible = "arm,ni-tower"; + reg = <0x0 0x4f000000 0x0 0x4000000>; + }; + sram: sram@6000000 { cpu_scp_scmi_p2a: scp-shmem@80 { compatible = "arm,scmi-shmem"; @@ -111,6 +123,22 @@ }; }; + gic: interrupt-controller@GIC_CTRL_ADDR { + ppi-partitions { + ppi_partition_little: interrupt-partition-0 { + affinity = <&CPU0>, <&CPU1>; + }; + + ppi_partition_mid: interrupt-partition-1 { + affinity = <&CPU2>, <&CPU3>, <&CPU4>, <&CPU5>; + }; + + ppi_partition_big: interrupt-partition-2 { + affinity = <&CPU6>, <&CPU7>; + }; + }; + }; + #if TARGET_FLAVOUR_FVP smmu_700: iommu@3f000000 { status = "okay"; diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index 3ea29eb14..83a5cd21f 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -362,6 +362,7 @@ void plat_arm_interconnect_enter_coherency(void); void plat_arm_interconnect_exit_coherency(void); void plat_arm_program_trusted_mailbox(uintptr_t address); bool plat_arm_bl1_fwu_needed(void); +int plat_arm_ni_setup(uintptr_t global_cfg); __dead2 void plat_arm_error_handler(int err); __dead2 void plat_arm_system_reset(void); diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk index 78b694577..fb7050081 100644 --- a/plat/arm/board/tc/platform.mk +++ b/plat/arm/board/tc/platform.mk @@ -121,7 +121,8 @@ TC_CPU_SOURCES += lib/cpus/aarch64/cortex_a520.S \ lib/cpus/aarch64/cortex_x925.S endif -INTERCONNECT_SOURCES := ${TC_BASE}/tc_interconnect.c +INTERCONNECT_SOURCES := ${TC_BASE}/tc_interconnect.c \ + plat/arm/common/arm_ni.c PLAT_BL_COMMON_SOURCES += ${TC_BASE}/tc_plat.c \ ${TC_BASE}/include/tc_helpers.S diff --git a/plat/arm/board/tc/tc_bl31_setup.c b/plat/arm/board/tc/tc_bl31_setup.c index 7d1bc9c93..53404dfcc 100644 --- a/plat/arm/board/tc/tc_bl31_setup.c +++ b/plat/arm/board/tc/tc_bl31_setup.c @@ -110,6 +110,7 @@ void bl31_platform_setup(void) #if TARGET_PLATFORM == 3 enable_ns_mcn_pmu(); set_mcn_slc_alloc_mode(); + plat_arm_ni_setup(NCI_BASE_ADDR); #endif } diff --git a/plat/arm/common/arm_ni.c b/plat/arm/common/arm_ni.c new file mode 100644 index 000000000..b3ad8b386 --- /dev/null +++ b/plat/arm/common/arm_ni.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2024, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#define NI_CHILD_NODE_COUNT 4 +#define NI_CHILD_POINTERS_START 8 + +#define NI_PMU_SECURE_CTRL 0x100 +#define NI_PMU_SECURE_EVENT_OBSERVATION 0x108 +#define NI_PMU_DEBUG_ENABLE 0x110 +#define NI_COMP_NUM_SUBFEATURES 0x100 +#define NI_COMP_SUBFEATURE_TYPE_START 0x108 +#define NI_COMP_SUBFEATURE_SECURE_CTRL_START 0x308 + +#define SECURE_OVERRIDE_DEFAULT BIT(0) +#define SECURE_EVENT_ENABLE BIT(2) +#define NA_EVENT_ENABLE BIT(3) +#define PMU_ENABLE BIT(0) + +#define NI_NODE_MASK 0x0000ffff +#define NI_NODE_TYPE(node_info) (node_info & NI_NODE_MASK) +#define NI_CHILD_POINTER(i) (NI_CHILD_POINTERS_START + (i * 4)) +#define NI_COMP_SUBFEATURE_TYPE(i) (NI_COMP_SUBFEATURE_TYPE_START + (i * 8)) +#define NI_COMP_SUBFEATURE_SECURE_CTRL(i) (NI_COMP_SUBFEATURE_SECURE_CTRL_START + (i * 8)) + +#define NI_PERIPHERAL_ID0 0xfe0 +#define NI_PIDR0_PART_MASK 0xff +#define NI_PERIPHERAL_ID1 0xfe4 +#define NI_PIDR1_PART_MASK 0xf +#define NI_PIDR1_PART_SHIFT 8 + +enum ni_part { + NI_700 = 0x43b, + NI_710AE = 0x43d, + NI_TOWER = 0x43f, +}; + +enum ni_node_type { + NI_INVALID_NODE = 0, + NI_VOLTAGE_DOMAIN = 1, + NI_POWER_DOMAIN = 2, + NI_CLOCK_DOMAIN = 3, + NI_ASNI = 4, + NI_AMNI = 5, + NI_PMU = 6, + NI_HSNI = 7, + NI_HMNI = 8, + NI_PMNI = 9, + NI_CMNI = 14, + NI_CFGNI = 15 +}; + +enum ni_subfeature_type { + NI_SUBFEATURE_APU = 0, + NI_SUBFEATURE_ADDR_MAP = 1, + NI_SUBFEATURE_FCU = 2, + NI_SUBFEATURE_IDM = 3 +}; + +static void ni_enable_pmu(uintptr_t pmu_addr) +{ + mmio_setbits_32(pmu_addr + NI_PMU_DEBUG_ENABLE, PMU_ENABLE); +} + +static void ni_enable_fcu_ns_access(uintptr_t comp_addr) +{ + uint32_t subfeature_type; + uint32_t subfeature_count; + uint32_t subfeature_secure_ctrl; + + subfeature_count = mmio_read_32(comp_addr + NI_COMP_NUM_SUBFEATURES); + for (uint32_t i = 0U; i < subfeature_count; i++) { + subfeature_type = + NI_NODE_TYPE(mmio_read_32(comp_addr + NI_COMP_SUBFEATURE_TYPE(i))); + if (subfeature_type == NI_SUBFEATURE_FCU) { + subfeature_secure_ctrl = comp_addr + NI_COMP_SUBFEATURE_SECURE_CTRL(i); + mmio_setbits_32(subfeature_secure_ctrl, SECURE_OVERRIDE_DEFAULT); + } + } +} + +static void ni_enable_pmu_ns_access(uintptr_t comp_addr) +{ + mmio_setbits_32(comp_addr + NI_PMU_SECURE_CTRL, SECURE_OVERRIDE_DEFAULT); + mmio_setbits_32(comp_addr + NI_PMU_SECURE_EVENT_OBSERVATION, + SECURE_EVENT_ENABLE | NA_EVENT_ENABLE); +} + +static void ni_setup_component(uintptr_t comp_addr) +{ + uint32_t node_info; + + node_info = mmio_read_32(comp_addr); + + switch (NI_NODE_TYPE(node_info)) { + case NI_ASNI: + case NI_AMNI: + case NI_HSNI: + case NI_HMNI: + case NI_PMNI: + ni_enable_fcu_ns_access(comp_addr); + break; + case NI_PMU: + ni_enable_pmu_ns_access(comp_addr); + ni_enable_pmu(comp_addr); + break; + default: + return; + } +} + +int plat_arm_ni_setup(uintptr_t global_cfg) +{ + uintptr_t vd_addr; + uintptr_t pd_addr; + uintptr_t cd_addr; + uintptr_t comp_addr; + uint32_t vd_count; + uint32_t pd_count; + uint32_t cd_count; + uint32_t comp_count; + uint32_t part; + uint32_t reg; + + reg = mmio_read_32(global_cfg + NI_PERIPHERAL_ID0); + part = reg & NI_PIDR0_PART_MASK; + reg = mmio_read_32(global_cfg + NI_PERIPHERAL_ID1); + part |= ((reg & NI_PIDR1_PART_MASK) << NI_PIDR1_PART_SHIFT); + + if (part != NI_TOWER) { + ERROR("0x%x is not supported\n", part); + return -EINVAL; + } + + vd_count = mmio_read_32(global_cfg + NI_CHILD_NODE_COUNT); + + for (uint32_t i = 0U; i < vd_count; i++) { + vd_addr = global_cfg + mmio_read_32(global_cfg + NI_CHILD_POINTER(i)); + pd_count = mmio_read_32(vd_addr + NI_CHILD_NODE_COUNT); + + for (uint32_t j = 0U; j < pd_count; j++) { + pd_addr = global_cfg + mmio_read_32(vd_addr + NI_CHILD_POINTER(j)); + cd_count = mmio_read_32(pd_addr + NI_CHILD_NODE_COUNT); + + for (uint32_t k = 0U; k < cd_count; k++) { + cd_addr = global_cfg + mmio_read_32(pd_addr + NI_CHILD_POINTER(k)); + comp_count = mmio_read_32(cd_addr + NI_CHILD_NODE_COUNT); + + for (uint32_t l = 0U; l < comp_count; l++) { + comp_addr = global_cfg + + mmio_read_32(cd_addr + NI_CHILD_POINTER(l)); + ni_setup_component(comp_addr); + } + } + } + } + + return 0; +}