189c58a50SJagdish Gediya /* 289c58a50SJagdish Gediya * Copyright (c) 2024, ARM Limited and Contributors. All rights reserved. 389c58a50SJagdish Gediya * 489c58a50SJagdish Gediya * SPDX-License-Identifier: BSD-3-Clause 589c58a50SJagdish Gediya */ 689c58a50SJagdish Gediya 789c58a50SJagdish Gediya #include <errno.h> 889c58a50SJagdish Gediya 989c58a50SJagdish Gediya #include <common/debug.h> 1089c58a50SJagdish Gediya #include <plat/arm/common/plat_arm.h> 1189c58a50SJagdish Gediya #include <platform_def.h> 1289c58a50SJagdish Gediya 1389c58a50SJagdish Gediya #define NI_CHILD_NODE_COUNT 4 1489c58a50SJagdish Gediya #define NI_CHILD_POINTERS_START 8 1589c58a50SJagdish Gediya 1689c58a50SJagdish Gediya #define NI_PMU_SECURE_CTRL 0x100 1789c58a50SJagdish Gediya #define NI_PMU_SECURE_EVENT_OBSERVATION 0x108 1889c58a50SJagdish Gediya #define NI_PMU_DEBUG_ENABLE 0x110 1989c58a50SJagdish Gediya #define NI_COMP_NUM_SUBFEATURES 0x100 2089c58a50SJagdish Gediya #define NI_COMP_SUBFEATURE_TYPE_START 0x108 2189c58a50SJagdish Gediya #define NI_COMP_SUBFEATURE_SECURE_CTRL_START 0x308 2289c58a50SJagdish Gediya 2389c58a50SJagdish Gediya #define SECURE_OVERRIDE_DEFAULT BIT(0) 2489c58a50SJagdish Gediya #define SECURE_EVENT_ENABLE BIT(2) 2589c58a50SJagdish Gediya #define NA_EVENT_ENABLE BIT(3) 2689c58a50SJagdish Gediya #define PMU_ENABLE BIT(0) 2789c58a50SJagdish Gediya 2889c58a50SJagdish Gediya #define NI_NODE_MASK 0x0000ffff 2989c58a50SJagdish Gediya #define NI_NODE_TYPE(node_info) (node_info & NI_NODE_MASK) 3089c58a50SJagdish Gediya #define NI_CHILD_POINTER(i) (NI_CHILD_POINTERS_START + (i * 4)) 3189c58a50SJagdish Gediya #define NI_COMP_SUBFEATURE_TYPE(i) (NI_COMP_SUBFEATURE_TYPE_START + (i * 8)) 3289c58a50SJagdish Gediya #define NI_COMP_SUBFEATURE_SECURE_CTRL(i) (NI_COMP_SUBFEATURE_SECURE_CTRL_START + (i * 8)) 3389c58a50SJagdish Gediya 3489c58a50SJagdish Gediya #define NI_PERIPHERAL_ID0 0xfe0 3589c58a50SJagdish Gediya #define NI_PIDR0_PART_MASK 0xff 3689c58a50SJagdish Gediya #define NI_PERIPHERAL_ID1 0xfe4 3789c58a50SJagdish Gediya #define NI_PIDR1_PART_MASK 0xf 3889c58a50SJagdish Gediya #define NI_PIDR1_PART_SHIFT 8 3989c58a50SJagdish Gediya 4089c58a50SJagdish Gediya enum ni_part { 4189c58a50SJagdish Gediya NI_700 = 0x43b, 4289c58a50SJagdish Gediya NI_710AE = 0x43d, 4389c58a50SJagdish Gediya NI_TOWER = 0x43f, 4489c58a50SJagdish Gediya }; 4589c58a50SJagdish Gediya 4689c58a50SJagdish Gediya enum ni_node_type { 4789c58a50SJagdish Gediya NI_INVALID_NODE = 0, 4889c58a50SJagdish Gediya NI_VOLTAGE_DOMAIN = 1, 4989c58a50SJagdish Gediya NI_POWER_DOMAIN = 2, 5089c58a50SJagdish Gediya NI_CLOCK_DOMAIN = 3, 5189c58a50SJagdish Gediya NI_ASNI = 4, 5289c58a50SJagdish Gediya NI_AMNI = 5, 5389c58a50SJagdish Gediya NI_PMU = 6, 5489c58a50SJagdish Gediya NI_HSNI = 7, 5589c58a50SJagdish Gediya NI_HMNI = 8, 5689c58a50SJagdish Gediya NI_PMNI = 9, 5789c58a50SJagdish Gediya NI_CMNI = 14, 5889c58a50SJagdish Gediya NI_CFGNI = 15 5989c58a50SJagdish Gediya }; 6089c58a50SJagdish Gediya 6189c58a50SJagdish Gediya enum ni_subfeature_type { 6289c58a50SJagdish Gediya NI_SUBFEATURE_APU = 0, 6389c58a50SJagdish Gediya NI_SUBFEATURE_ADDR_MAP = 1, 6489c58a50SJagdish Gediya NI_SUBFEATURE_FCU = 2, 6589c58a50SJagdish Gediya NI_SUBFEATURE_IDM = 3 6689c58a50SJagdish Gediya }; 6789c58a50SJagdish Gediya 6889c58a50SJagdish Gediya static void ni_enable_pmu(uintptr_t pmu_addr) 6989c58a50SJagdish Gediya { 7089c58a50SJagdish Gediya mmio_setbits_32(pmu_addr + NI_PMU_DEBUG_ENABLE, PMU_ENABLE); 7189c58a50SJagdish Gediya } 7289c58a50SJagdish Gediya 7389c58a50SJagdish Gediya static void ni_enable_fcu_ns_access(uintptr_t comp_addr) 7489c58a50SJagdish Gediya { 7589c58a50SJagdish Gediya uint32_t subfeature_type; 7689c58a50SJagdish Gediya uint32_t subfeature_count; 7789c58a50SJagdish Gediya uint32_t subfeature_secure_ctrl; 7889c58a50SJagdish Gediya 7989c58a50SJagdish Gediya subfeature_count = mmio_read_32(comp_addr + NI_COMP_NUM_SUBFEATURES); 8089c58a50SJagdish Gediya for (uint32_t i = 0U; i < subfeature_count; i++) { 8189c58a50SJagdish Gediya subfeature_type = 8289c58a50SJagdish Gediya NI_NODE_TYPE(mmio_read_32(comp_addr + NI_COMP_SUBFEATURE_TYPE(i))); 8389c58a50SJagdish Gediya if (subfeature_type == NI_SUBFEATURE_FCU) { 8489c58a50SJagdish Gediya subfeature_secure_ctrl = comp_addr + NI_COMP_SUBFEATURE_SECURE_CTRL(i); 8589c58a50SJagdish Gediya mmio_setbits_32(subfeature_secure_ctrl, SECURE_OVERRIDE_DEFAULT); 8689c58a50SJagdish Gediya } 8789c58a50SJagdish Gediya } 8889c58a50SJagdish Gediya } 8989c58a50SJagdish Gediya 9089c58a50SJagdish Gediya static void ni_enable_pmu_ns_access(uintptr_t comp_addr) 9189c58a50SJagdish Gediya { 9289c58a50SJagdish Gediya mmio_setbits_32(comp_addr + NI_PMU_SECURE_CTRL, SECURE_OVERRIDE_DEFAULT); 9389c58a50SJagdish Gediya mmio_setbits_32(comp_addr + NI_PMU_SECURE_EVENT_OBSERVATION, 9489c58a50SJagdish Gediya SECURE_EVENT_ENABLE | NA_EVENT_ENABLE); 9589c58a50SJagdish Gediya } 9689c58a50SJagdish Gediya 9789c58a50SJagdish Gediya static void ni_setup_component(uintptr_t comp_addr) 9889c58a50SJagdish Gediya { 9989c58a50SJagdish Gediya uint32_t node_info; 10089c58a50SJagdish Gediya 10189c58a50SJagdish Gediya node_info = mmio_read_32(comp_addr); 10289c58a50SJagdish Gediya 10389c58a50SJagdish Gediya switch (NI_NODE_TYPE(node_info)) { 10489c58a50SJagdish Gediya case NI_ASNI: 10589c58a50SJagdish Gediya case NI_AMNI: 10689c58a50SJagdish Gediya case NI_HSNI: 10789c58a50SJagdish Gediya case NI_HMNI: 10889c58a50SJagdish Gediya case NI_PMNI: 10989c58a50SJagdish Gediya ni_enable_fcu_ns_access(comp_addr); 11089c58a50SJagdish Gediya break; 11189c58a50SJagdish Gediya case NI_PMU: 11289c58a50SJagdish Gediya ni_enable_pmu_ns_access(comp_addr); 11389c58a50SJagdish Gediya ni_enable_pmu(comp_addr); 11489c58a50SJagdish Gediya break; 11589c58a50SJagdish Gediya default: 11689c58a50SJagdish Gediya return; 11789c58a50SJagdish Gediya } 11889c58a50SJagdish Gediya } 11989c58a50SJagdish Gediya 12089c58a50SJagdish Gediya int plat_arm_ni_setup(uintptr_t global_cfg) 12189c58a50SJagdish Gediya { 12289c58a50SJagdish Gediya uintptr_t vd_addr; 12389c58a50SJagdish Gediya uintptr_t pd_addr; 12489c58a50SJagdish Gediya uintptr_t cd_addr; 12589c58a50SJagdish Gediya uintptr_t comp_addr; 12689c58a50SJagdish Gediya uint32_t vd_count; 12789c58a50SJagdish Gediya uint32_t pd_count; 12889c58a50SJagdish Gediya uint32_t cd_count; 12989c58a50SJagdish Gediya uint32_t comp_count; 13089c58a50SJagdish Gediya uint32_t part; 13189c58a50SJagdish Gediya uint32_t reg; 13289c58a50SJagdish Gediya 13389c58a50SJagdish Gediya reg = mmio_read_32(global_cfg + NI_PERIPHERAL_ID0); 13489c58a50SJagdish Gediya part = reg & NI_PIDR0_PART_MASK; 13589c58a50SJagdish Gediya reg = mmio_read_32(global_cfg + NI_PERIPHERAL_ID1); 13689c58a50SJagdish Gediya part |= ((reg & NI_PIDR1_PART_MASK) << NI_PIDR1_PART_SHIFT); 13789c58a50SJagdish Gediya 13889c58a50SJagdish Gediya if (part != NI_TOWER) { 13989c58a50SJagdish Gediya ERROR("0x%x is not supported\n", part); 14089c58a50SJagdish Gediya return -EINVAL; 14189c58a50SJagdish Gediya } 14289c58a50SJagdish Gediya 14389c58a50SJagdish Gediya vd_count = mmio_read_32(global_cfg + NI_CHILD_NODE_COUNT); 14489c58a50SJagdish Gediya 14589c58a50SJagdish Gediya for (uint32_t i = 0U; i < vd_count; i++) { 14689c58a50SJagdish Gediya vd_addr = global_cfg + mmio_read_32(global_cfg + NI_CHILD_POINTER(i)); 147*d87a8562SJagdish Gediya 148*d87a8562SJagdish Gediya VERBOSE("Voltage domain %u at 0x%lx node info: 0x%x\n", 149*d87a8562SJagdish Gediya i, vd_addr, mmio_read_32(vd_addr)); 150*d87a8562SJagdish Gediya 15189c58a50SJagdish Gediya pd_count = mmio_read_32(vd_addr + NI_CHILD_NODE_COUNT); 15289c58a50SJagdish Gediya 15389c58a50SJagdish Gediya for (uint32_t j = 0U; j < pd_count; j++) { 15489c58a50SJagdish Gediya pd_addr = global_cfg + mmio_read_32(vd_addr + NI_CHILD_POINTER(j)); 15589c58a50SJagdish Gediya cd_count = mmio_read_32(pd_addr + NI_CHILD_NODE_COUNT); 15689c58a50SJagdish Gediya 157*d87a8562SJagdish Gediya VERBOSE("Power domain %u at 0x%lx node info: 0x%x\n", 158*d87a8562SJagdish Gediya j, pd_addr, mmio_read_32(pd_addr)); 159*d87a8562SJagdish Gediya 16089c58a50SJagdish Gediya for (uint32_t k = 0U; k < cd_count; k++) { 16189c58a50SJagdish Gediya cd_addr = global_cfg + mmio_read_32(pd_addr + NI_CHILD_POINTER(k)); 16289c58a50SJagdish Gediya comp_count = mmio_read_32(cd_addr + NI_CHILD_NODE_COUNT); 16389c58a50SJagdish Gediya 164*d87a8562SJagdish Gediya VERBOSE("Clock domain %u at 0x%lx node info: 0x%x\n", 165*d87a8562SJagdish Gediya k, cd_addr, mmio_read_32(cd_addr)); 166*d87a8562SJagdish Gediya 16789c58a50SJagdish Gediya for (uint32_t l = 0U; l < comp_count; l++) { 16889c58a50SJagdish Gediya comp_addr = global_cfg + 16989c58a50SJagdish Gediya mmio_read_32(cd_addr + NI_CHILD_POINTER(l)); 170*d87a8562SJagdish Gediya 171*d87a8562SJagdish Gediya VERBOSE("Component %u at 0x%lx node info: 0x%x\n", 172*d87a8562SJagdish Gediya l, comp_addr, mmio_read_32(comp_addr)); 173*d87a8562SJagdish Gediya 17489c58a50SJagdish Gediya ni_setup_component(comp_addr); 17589c58a50SJagdish Gediya } 17689c58a50SJagdish Gediya } 17789c58a50SJagdish Gediya } 17889c58a50SJagdish Gediya } 17989c58a50SJagdish Gediya 18089c58a50SJagdish Gediya return 0; 18189c58a50SJagdish Gediya } 182