1 /*
2  * Copyright (C) 2018 Marvell International Ltd.
3  *
4  * SPDX-License-Identifier:     BSD-3-Clause
5  * https://spdx.org/licenses
6  */
7 
8 #include <arch_helpers.h>
9 #include <common/debug.h>
10 #include <drivers/marvell/cache_llc.h>
11 #include <lib/mmio.h>
12 #include <plat/common/platform.h>
13 
14 #define CCU_HTC_ASET			(MVEBU_CCU_BASE(MVEBU_AP0) + 0x264)
15 #define MVEBU_IO_AFFINITY		(0xF00)
16 #define MVEBU_SF_REG			(MVEBU_REGS_BASE + 0x40)
17 #define MVEBU_SF_EN			BIT(8)
18 #define MVEBU_DFX_REG(cluster_id)	(MVEBU_REGS_BASE + 0x6F82A0 + \
19 					(cluster_id) * 0x4)
20 #define MVEBU_DFX_CLK_EN_POS		0x3
21 #define MVEBU_DFX_CL0_CLK_OFFS		16
22 #define MVEBU_DFX_CL0_CLK_MASK		(0xF << MVEBU_DFX_CL0_CLK_OFFS)
23 #define MVEBU_DFX_CL1_CLK_OFFS		8
24 #define MVEBU_DFX_CL1_CLK_MASK		(0xF << MVEBU_DFX_CL1_CLK_OFFS)
25 
26 #ifdef MVEBU_SOC_AP807
plat_enable_snoop_filter(void)27 static void plat_enable_snoop_filter(void)
28 {
29 	int cpu_id = plat_my_core_pos();
30 
31 	/* Snoop filter needs to be enabled once per cluster */
32 	if (cpu_id % 2)
33 		return;
34 
35 	mmio_setbits_32(MVEBU_SF_REG, MVEBU_SF_EN);
36 }
37 #endif
38 
39 #ifndef MVEBU_SOC_AP807
plat_config_dfx_clock(void)40 static void plat_config_dfx_clock(void)
41 {
42 	int cluster_id = plat_my_core_pos();
43 	uint32_t val;
44 
45 	/* DFX clock needs to be configured once per cluster */
46 	if ((cluster_id % PLAT_MAX_CPUS_PER_CLUSTER) != 0) {
47 		return;
48 	}
49 
50 	val = mmio_read_32(MVEBU_DFX_REG(cluster_id / PLAT_MAX_CPUS_PER_CLUSTER));
51 	if (cluster_id == 0) {
52 		val &= ~MVEBU_DFX_CL0_CLK_MASK;
53 		val |= (MVEBU_DFX_CLK_EN_POS << MVEBU_DFX_CL0_CLK_OFFS);
54 	} else {
55 		val &= ~MVEBU_DFX_CL1_CLK_MASK;
56 		val |= (MVEBU_DFX_CLK_EN_POS << MVEBU_DFX_CL1_CLK_OFFS);
57 	}
58 	mmio_write_32(MVEBU_DFX_REG(cluster_id / PLAT_MAX_CPUS_PER_CLUSTER), val);
59 }
60 #endif
61 
plat_enable_affinity(void)62 static void plat_enable_affinity(void)
63 {
64 	int cluster_id;
65 	int affinity;
66 
67 	/* set CPU Affinity */
68 	cluster_id = plat_my_core_pos() / PLAT_MARVELL_CLUSTER_CORE_COUNT;
69 	affinity = (MVEBU_IO_AFFINITY | (1 << cluster_id));
70 	mmio_write_32(CCU_HTC_ASET, affinity);
71 
72 	/* set barier */
73 	isb();
74 }
75 
marvell_psci_arch_init(int die_index)76 void marvell_psci_arch_init(int die_index)
77 {
78 #if LLC_ENABLE
79 	/* check if LLC is in exclusive mode
80 	 * as L2 is configured to UniqueClean eviction
81 	 * (in a8k reset handler)
82 	 */
83 	if (llc_is_exclusive(0) == 0)
84 		ERROR("LLC should be configured to exclusice mode\n");
85 #endif
86 
87 	/* Enable Affinity */
88 	plat_enable_affinity();
89 
90 #ifdef MVEBU_SOC_AP807
91 	plat_enable_snoop_filter();
92 #else
93 	plat_config_dfx_clock();
94 #endif
95 }
96