summaryrefslogtreecommitdiffstats
path: root/plat/brcm/board/stingray/src/paxc.c
blob: 44af4b010b45db45b97fd18fc9bb490df42132da (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
/*
 * Copyright (c) 2017 - 2020, Broadcom
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <common/debug.h>
#include <lib/mmio.h>

#include <iommu.h>
#include <platform_def.h>
#include <sr_utils.h>

#define PAXC_BASE                  0x60400000
#define PAXC_AXI_CFG_PF            0x10
#define PAXC_AXI_CFG_PF_OFFSET(pf) (PAXC_AXI_CFG_PF + (pf) * 4)
#define PAXC_ARPROT_PF_CFG         0x40
#define PAXC_AWPROT_PF_CFG         0x44

#define PAXC_ARQOS_PF_CFG          0x48
#define PAXC_ARQOS_VAL             0xaaaaaaaa

#define PAXC_AWQOS_PF_CFG          0x4c
#define PAXC_AWQOS_VAL             0xeeeeeeee

#define PAXC_CFG_IND_ADDR_OFFSET   0x1f0
#define PAXC_CFG_IND_ADDR_MASK     0xffc
#define PAXC_CFG_IND_DATA_OFFSET   0x1f4

/* offsets for PAXC root complex configuration space registers */

#define PAXC_CFG_ID_OFFSET           0x434
#define PAXC_RC_VENDOR_ID            0x14e4
#define PAXC_RC_VENDOR_ID_SHIFT      16

#define PAXC_RC_DEVICE_ID            0xd750

#define PAXC_CFG_LINK_CAP_OFFSET     0x4dc
#define PAXC_RC_LINK_CAP_SPD_SHIFT   0
#define PAXC_RC_LINK_CAP_SPD_MASK    (0xf << PAXC_RC_LINK_CAP_SPD_SHIFT)
#define PAXC_RC_LINK_CAP_SPD         3
#define PAXC_RC_LINK_CAP_WIDTH_SHIFT 4
#define PAXC_RC_LINK_CAP_WIDTH_MASK  (0x1f << PAXC_RC_LINK_CAP_WIDTH_SHIFT)
#define PAXC_RC_LINK_CAP_WIDTH       16

/* offsets for MHB registers */

#define MHB_BASE                   0x60401000
#define MHB_MEM_PWR_STATUS_PAXC    (MHB_BASE + 0x1c0)
#define MHB_PWR_ARR_POWERON        0x8
#define MHB_PWR_ARR_POWEROK        0x4
#define MHB_PWR_POWERON            0x2
#define MHB_PWR_POWEROK            0x1
#define MHB_PWR_STATUS_MASK        (MHB_PWR_ARR_POWERON | \
				    MHB_PWR_ARR_POWEROK | \
				    MHB_PWR_POWERON | \
				    MHB_PWR_POWEROK)

/* max number of PFs from Nitro that PAXC sees */
#define MAX_NR_NITRO_PF            8

#ifdef EMULATION_SETUP
static void paxc_reg_dump(void)
{
}
#else
/* total number of PAXC registers */
#define NR_PAXC_REGS               53
static void paxc_reg_dump(void)
{
	uint32_t idx, offset = 0;

	VERBOSE("PAXC register dump start\n");
	for (idx = 0; idx < NR_PAXC_REGS; idx++, offset += 4)
		VERBOSE("offset: 0x%x val: 0x%x\n", offset,
			mmio_read_32(PAXC_BASE + offset));
	VERBOSE("PAXC register dump end\n");
}
#endif /* EMULATION_SETUP */

#ifdef EMULATION_SETUP
static void mhb_reg_dump(void)
{
}
#else
#define NR_MHB_REGS                227
static void mhb_reg_dump(void)
{
	uint32_t idx, offset = 0;

	VERBOSE("MHB register dump start\n");
	for (idx = 0; idx < NR_MHB_REGS; idx++, offset += 4)
		VERBOSE("offset: 0x%x val: 0x%x\n", offset,
			mmio_read_32(MHB_BASE + offset));
	VERBOSE("MHB register dump end\n");
}
#endif /* EMULATION_SETUP */

static void paxc_rc_cfg_write(uint32_t where, uint32_t val)
{
	mmio_write_32(PAXC_BASE + PAXC_CFG_IND_ADDR_OFFSET,
		      where & PAXC_CFG_IND_ADDR_MASK);
	mmio_write_32(PAXC_BASE + PAXC_CFG_IND_DATA_OFFSET, val);
}

static uint32_t paxc_rc_cfg_read(uint32_t where)
{
	mmio_write_32(PAXC_BASE + PAXC_CFG_IND_ADDR_OFFSET,
		      where & PAXC_CFG_IND_ADDR_MASK);
	return mmio_read_32(PAXC_BASE + PAXC_CFG_IND_DATA_OFFSET);
}

/*
 * Function to program PAXC root complex link capability register
 */
static void paxc_cfg_link_cap(void)
{
	uint32_t val;

	val = paxc_rc_cfg_read(PAXC_CFG_LINK_CAP_OFFSET);
	val &= ~(PAXC_RC_LINK_CAP_SPD_MASK | PAXC_RC_LINK_CAP_WIDTH_MASK);
	val |= (PAXC_RC_LINK_CAP_SPD << PAXC_RC_LINK_CAP_SPD_SHIFT) |
		(PAXC_RC_LINK_CAP_WIDTH << PAXC_RC_LINK_CAP_WIDTH_SHIFT);
	paxc_rc_cfg_write(PAXC_CFG_LINK_CAP_OFFSET, val);
}

/*
 * Function to program PAXC root complex vendor ID and device ID
 */
static void paxc_cfg_id(void)
{
	uint32_t val;

	val = (PAXC_RC_VENDOR_ID << PAXC_RC_VENDOR_ID_SHIFT) |
		PAXC_RC_DEVICE_ID;
	paxc_rc_cfg_write(PAXC_CFG_ID_OFFSET, val);
}

void paxc_init(void)
{
	unsigned int pf_index;
	unsigned int val;

	val = mmio_read_32(MHB_MEM_PWR_STATUS_PAXC);
	if ((val & MHB_PWR_STATUS_MASK) != MHB_PWR_STATUS_MASK) {
		INFO("PAXC not powered\n");
		return;
	}

	paxc_cfg_id();
	paxc_cfg_link_cap();

	paxc_reg_dump();
	mhb_reg_dump();

#ifdef USE_DDR
	/*
	 * Set AWCACHE and ARCACHE to 0xff (Cacheable write-back,
	 * allocate on both reads and writes) per
	 * recommendation from the ASIC team
	 */
	val = 0xff;
#else
	/* disable IO cache if non-DDR memory is used, e.g., external SRAM */
	val = 0x0;
#endif
	for (pf_index = 0; pf_index < MAX_NR_NITRO_PF; pf_index++)
		mmio_write_32(PAXC_BASE + PAXC_AXI_CFG_PF_OFFSET(pf_index),
			      val);

	/*
	 * Set ARPROT and AWPROT to enable non-secure access from
	 * PAXC to all PFs, PF0 to PF7
	 */
	mmio_write_32(PAXC_BASE + PAXC_ARPROT_PF_CFG, 0x22222222);
	mmio_write_32(PAXC_BASE + PAXC_AWPROT_PF_CFG, 0x22222222);

	mmio_write_32(PAXC_BASE + PAXC_ARQOS_PF_CFG, PAXC_ARQOS_VAL);
	mmio_write_32(PAXC_BASE + PAXC_AWQOS_PF_CFG, PAXC_AWQOS_VAL);

	INFO("PAXC init done\n");
}

/*
 * These defines do not match the regfile but they are renamed in a way such
 * that they are much more readible
 */

#define MHB_NIC_SECURITY_BASE  0x60500000
#define MHB_NIC_PAXC_AXI_NS    0x0008
#define MHB_NIC_IDM_NS         0x000c
#define MHB_NIC_MHB_APB_NS     0x0010
#define MHB_NIC_NITRO_AXI_NS   0x0014
#define MHB_NIC_PCIE_AXI_NS    0x0018
#define MHB_NIC_PAXC_APB_NS    0x001c
#define MHB_NIC_EP_APB_NS      0x0020

#define MHB_NIC_PAXC_APB_S_IDM_SHIFT     5
#define MHB_NIC_EP_APB_S_IDM_SHIFT       4
#define MHB_NIC_MHB_APB_S_IDM_SHIFT      3
#define MHB_NIC_PAXC_AXI_S_IDM_SHIFT     2
#define MHB_NIC_PCIE_AXI_S_IDM_SHIFT     1
#define MHB_NIC_NITRO_AXI_S_IDM_SHIFT    0

#define NIC400_NITRO_TOP_NIC_SECURITY_BASE 0x60d00000

#define NITRO_NIC_SECURITY_3_SHIFT       0x14
#define NITRO_NIC_SECURITY_4_SHIFT       0x18
#define NITRO_NIC_SECURITY_5_SHIFT       0x1c
#define NITRO_NIC_SECURITY_6_SHIFT       0x20

void paxc_mhb_ns_init(void)
{
	unsigned int val;
	uintptr_t mhb_nic_gpv = MHB_NIC_SECURITY_BASE;
#ifndef NITRO_SECURE_ACCESS
	uintptr_t nic400_nitro_gpv = NIC400_NITRO_TOP_NIC_SECURITY_BASE;
#endif /* NITRO_SECURE_ACCESS */

	/* set PAXC AXI to allow non-secure access */
	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PAXC_AXI_NS);
	val |= 0x1;
	mmio_write_32(mhb_nic_gpv + MHB_NIC_PAXC_AXI_NS, val);

	/* set various MHB IDM interfaces to allow non-secure access */
	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_IDM_NS);
	val |= (0x1 << MHB_NIC_PAXC_APB_S_IDM_SHIFT);
	val |= (0x1 << MHB_NIC_EP_APB_S_IDM_SHIFT);
	val |= (0x1 << MHB_NIC_MHB_APB_S_IDM_SHIFT);
	val |= (0x1 << MHB_NIC_PAXC_AXI_S_IDM_SHIFT);
	val |= (0x1 << MHB_NIC_PCIE_AXI_S_IDM_SHIFT);
	val |= (0x1 << MHB_NIC_NITRO_AXI_S_IDM_SHIFT);
	mmio_write_32(mhb_nic_gpv + MHB_NIC_IDM_NS, val);

	/* set MHB APB to allow non-secure access  */
	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_MHB_APB_NS);
	val |= 0x1;
	mmio_write_32(mhb_nic_gpv + MHB_NIC_MHB_APB_NS, val);

	/* set Nitro AXI to allow non-secure access  */
	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_NITRO_AXI_NS);
	val |= 0x1;
	mmio_write_32(mhb_nic_gpv + MHB_NIC_NITRO_AXI_NS, val);

	/* set PCIe AXI to allow non-secure access  */
	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PCIE_AXI_NS);
	val |= 0x1;
	mmio_write_32(mhb_nic_gpv + MHB_NIC_PCIE_AXI_NS, val);

	/* set PAXC APB to allow non-secure access  */
	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_PAXC_APB_NS);
	val |= 0x1;
	mmio_write_32(mhb_nic_gpv + MHB_NIC_PAXC_APB_NS, val);

	/* set EP APB to allow non-secure access  */
	val = mmio_read_32(mhb_nic_gpv + MHB_NIC_EP_APB_NS);
	val |= 0x1;
	mmio_write_32(mhb_nic_gpv + MHB_NIC_EP_APB_NS, val);

#ifndef NITRO_SECURE_ACCESS
	/* Set NIC400 to allow non-secure access */
	mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_3_SHIFT, 0x1);
	mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_4_SHIFT, 0x1);
	mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_5_SHIFT, 0x1);
	mmio_setbits_32(nic400_nitro_gpv + NITRO_NIC_SECURITY_6_SHIFT, 0x1);
#endif /* NITRO_SECURE_ACCESS */
}