xref: /rk3399_ARM-atf/plat/arm/common/arm_ni.c (revision 001f22cdd46929c354fec41514295bfd7397409d)
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 
ni_enable_pmu(uintptr_t pmu_addr)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 
ni_enable_fcu_ns_access(uintptr_t comp_addr)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 
ni_enable_pmu_ns_access(uintptr_t comp_addr)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 
ni_setup_component(uintptr_t comp_addr)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 
plat_arm_ni_setup(uintptr_t global_cfg)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