xref: /rk3399_ARM-atf/drivers/arm/cci/cci.c (revision 82cb2c1ad9897473743f08437d0a3995bed561b9)
1 /*
2  * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <arch.h>
8 #include <assert.h>
9 #include <cci.h>
10 #include <debug.h>
11 #include <mmio.h>
12 #include <stdint.h>
13 
14 static uintptr_t g_cci_base;
15 static unsigned int g_max_master_id;
16 static const int *g_cci_slave_if_map;
17 
18 #if ENABLE_ASSERTIONS
19 static int validate_cci_map(const int *map)
20 {
21 	unsigned int valid_cci_map = 0;
22 	int slave_if_id;
23 	int i;
24 
25 	/* Validate the map */
26 	for (i = 0; i <= g_max_master_id; i++) {
27 		slave_if_id = map[i];
28 
29 		if (slave_if_id < 0)
30 			continue;
31 
32 		if (slave_if_id >= CCI_SLAVE_INTERFACE_COUNT) {
33 			ERROR("Slave interface ID is invalid\n");
34 			return 0;
35 		}
36 
37 		if (valid_cci_map & (1 << slave_if_id)) {
38 			ERROR("Multiple masters are assigned same slave interface ID\n");
39 			return 0;
40 		}
41 		valid_cci_map |= 1 << slave_if_id;
42 	}
43 
44 	if (!valid_cci_map) {
45 		ERROR("No master is assigned a valid slave interface\n");
46 		return 0;
47 	}
48 
49 	return 1;
50 }
51 #endif /* ENABLE_ASSERTIONS */
52 
53 void cci_init(uintptr_t cci_base,
54 		const int *map,
55 		unsigned int num_cci_masters)
56 {
57 	assert(map);
58 	assert(cci_base);
59 
60 	g_cci_base = cci_base;
61 
62 	/*
63 	 * Master Id's are assigned from zero, So in an array of size n
64 	 * the max master id is (n - 1).
65 	 */
66 	g_max_master_id = num_cci_masters - 1;
67 
68 	assert(validate_cci_map(map));
69 	g_cci_slave_if_map = map;
70 }
71 
72 void cci_enable_snoop_dvm_reqs(unsigned int master_id)
73 {
74 	int slave_if_id;
75 
76 	assert(g_cci_base);
77 	assert(master_id <= g_max_master_id);
78 
79 	slave_if_id = g_cci_slave_if_map[master_id];
80 	assert((slave_if_id < CCI_SLAVE_INTERFACE_COUNT) && (slave_if_id >= 0));
81 
82 	/*
83 	 * Enable Snoops and DVM messages, no need for Read/Modify/Write as
84 	 * rest of bits are write ignore
85 	 */
86 	mmio_write_32(g_cci_base +
87 		      SLAVE_IFACE_OFFSET(slave_if_id) +
88 		      SNOOP_CTRL_REG, DVM_EN_BIT | SNOOP_EN_BIT);
89 
90 	/* Wait for the dust to settle down */
91 	while (mmio_read_32(g_cci_base + STATUS_REG) & CHANGE_PENDING_BIT)
92 		;
93 }
94 
95 void cci_disable_snoop_dvm_reqs(unsigned int master_id)
96 {
97 	int slave_if_id;
98 
99 	assert(g_cci_base);
100 	assert(master_id <= g_max_master_id);
101 
102 	slave_if_id = g_cci_slave_if_map[master_id];
103 	assert((slave_if_id < CCI_SLAVE_INTERFACE_COUNT) && (slave_if_id >= 0));
104 
105 	/*
106 	 * Disable Snoops and DVM messages, no need for Read/Modify/Write as
107 	 * rest of bits are write ignore.
108 	 */
109 	mmio_write_32(g_cci_base +
110 		      SLAVE_IFACE_OFFSET(slave_if_id) +
111 		      SNOOP_CTRL_REG, ~(DVM_EN_BIT | SNOOP_EN_BIT));
112 
113 	/* Wait for the dust to settle down */
114 	while (mmio_read_32(g_cci_base + STATUS_REG) & CHANGE_PENDING_BIT)
115 		;
116 }
117 
118