blob: d022e4ca939aa103a7e3f12bdf5d25de8f1ceb84 [file] [log] [blame]
Jacky Bai7ec94512023-09-21 14:01:37 +08001/*
2 * Copyright 2020-2024 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <errno.h>
9#include <stdbool.h>
10
11#include <common/debug.h>
12#include <lib/mmio.h>
13#include <plat/common/platform.h>
14#include <platform_def.h>
15
16#include "xrdc_config.h"
17
18#define XRDC_ADDR 0x292f0000
19#define MRC_OFFSET 0x2000
20#define MRC_STEP 0x200
21
22#define XRDC_MGR_PAC_ID U(0)
23#define XRDC_MGR_PAC_SLOT U(47)
24
25enum xrdc_comp_type {
26 MDA_TYPE = (1 << 16),
27 MRC_TYPE = (2 << 16),
28 PAC_TYPE = (3 << 16),
29 MSC_TYPE = (4 << 16),
30};
31
32enum xrdc_pd_type {
33 XRDC_AD_PD,
34 XRDC_HIFI_PD,
35 XRDC_AV_PD,
36};
37
38#define XRDC_TYPE_MASK (0x7 << 16)
39#define XRDC_ID_MASK 0xFFFF
40#define XRDC_ID(id) ((id) & XRDC_ID_MASK)
41
42typedef bool (*xrdc_check_func)(enum xrdc_comp_type type, uint16_t id);
43
44/* Access below XRDC needs enable PS 8
45 * and HIFI clocks and release HIFI firstly
46 */
47uint32_t hifi_xrdc_list[] = {
48 (MDA_TYPE | XRDC_ID(9)),
49 (MRC_TYPE | XRDC_ID(7)),
50 (MRC_TYPE | XRDC_ID(9)),
51 (MRC_TYPE | XRDC_ID(11)),
52};
53
54/* Access below XRDC needs enable PS 16 firstly */
55uint32_t av_periph_xrdc_list[] = {
56 (MDA_TYPE | XRDC_ID(10)),
57 (MDA_TYPE | XRDC_ID(11)),
58 (MDA_TYPE | XRDC_ID(12)),
59 (MDA_TYPE | XRDC_ID(13)),
60 (MDA_TYPE | XRDC_ID(14)),
61 (MDA_TYPE | XRDC_ID(15)),
62 (MDA_TYPE | XRDC_ID(16)),
63
64 (PAC_TYPE | XRDC_ID(2)),
65
66 (MRC_TYPE | XRDC_ID(6)),
67 (MRC_TYPE | XRDC_ID(8)),
68 (MRC_TYPE | XRDC_ID(10)),
69
70 (MSC_TYPE | XRDC_ID(1)),
71 (MSC_TYPE | XRDC_ID(2)),
72};
73
74uint32_t imx8ulp_pac_slots[] = {
75 61, 23, 53
76};
77
78uint32_t imx8ulp_msc_slots[] = {
79 2, 1, 7
80};
81
82static int xrdc_config_mrc_w0_w1(uint32_t mrc_con, uint32_t region, uint32_t w0, uint32_t size)
83{
84
85 uint32_t w0_addr, w1_addr;
86
87 w0_addr = XRDC_ADDR + MRC_OFFSET + mrc_con * 0x200 + region * 0x20;
88 w1_addr = w0_addr + 4;
89
90 if ((size % 32) != 0) {
91 return -EINVAL;
92 }
93
94 mmio_write_32(w0_addr, w0 & ~0x1f);
95 mmio_write_32(w1_addr, w0 + size - 1);
96
97 return 0;
98}
99
100static int xrdc_config_mrc_w2(uint32_t mrc_con, uint32_t region, uint32_t dxsel_all)
101{
102 uint32_t w2_addr;
103
104 w2_addr = XRDC_ADDR + MRC_OFFSET + mrc_con * 0x200 + region * 0x20 + 0x8;
105
106 mmio_write_32(w2_addr, dxsel_all);
107
108 return 0;
109}
110
111static int xrdc_config_mrc_w3_w4(uint32_t mrc_con, uint32_t region, uint32_t w3, uint32_t w4)
112{
113 uint32_t w3_addr = XRDC_ADDR + MRC_OFFSET + mrc_con * 0x200 + region * 0x20 + 0xC;
114 uint32_t w4_addr = w3_addr + 4;
115
116 mmio_write_32(w3_addr, w3);
117 mmio_write_32(w4_addr, w4);
118
119 return 0;
120}
121
122static int xrdc_config_pac(uint32_t pac, uint32_t index, uint32_t dxacp)
123{
124 uint32_t w0_addr;
125 uint32_t val;
126
127 if (pac > 2U) {
128 return -EINVAL;
129 }
130
131 /* Skip the PAC slot for XRDC MGR, use Sentinel configuration */
132 if (pac == XRDC_MGR_PAC_ID && index == XRDC_MGR_PAC_SLOT) {
133 return 0;
134 }
135
136 w0_addr = XRDC_ADDR + 0x1000 + 0x400 * pac + 0x8 * index;
137
138 mmio_write_32(w0_addr, dxacp);
139
140 val = mmio_read_32(w0_addr + 4);
141 mmio_write_32(w0_addr + 4, val | BIT_32(31));
142
143 return 0;
144}
145
146static int xrdc_config_msc(uint32_t msc, uint32_t index, uint32_t dxacp)
147{
148 uint32_t w0_addr;
149 uint32_t val;
150
151 if (msc > 2) {
152 return -EINVAL;
153 }
154
155 w0_addr = XRDC_ADDR + 0x4000 + 0x400 * msc + 0x8 * index;
156
157 mmio_write_32(w0_addr, dxacp);
158
159 val = mmio_read_32(w0_addr + 4);
160 mmio_write_32(w0_addr + 4, val | BIT_32(31));
161
162 return 0;
163}
164
165static int xrdc_config_mda(uint32_t mda_con, uint32_t dom, enum xrdc_mda_sa sa)
166{
167 uint32_t w0_addr;
168 uint32_t val;
169
170 w0_addr = XRDC_ADDR + 0x800 + mda_con * 0x20;
171
172 val = mmio_read_32(w0_addr);
173
174 if (val & BIT_32(29)) {
175 mmio_write_32(w0_addr, (val & (~0xFF)) | dom |
176 BIT_32(31) | 0x20 | ((sa & 0x3) << 6));
177 } else {
178 mmio_write_32(w0_addr, dom | BIT_32(31));
179 mmio_write_32(w0_addr + 0x4, dom | BIT_32(31));
180 }
181
182 return 0;
183}
184
185static bool xrdc_check_pd(enum xrdc_comp_type type,
186 uint16_t id, enum xrdc_pd_type pd)
187{
188 unsigned int i, size;
189 uint32_t item = type | XRDC_ID(id);
190 uint32_t *list;
191
192 if (pd == XRDC_HIFI_PD) {
193 size = ARRAY_SIZE(hifi_xrdc_list);
194 list = hifi_xrdc_list;
195 } else if (pd == XRDC_AV_PD) {
196 size = ARRAY_SIZE(av_periph_xrdc_list);
197 list = av_periph_xrdc_list;
198 } else {
199 return false;
200 }
201
202 for (i = 0U; i < size; i++) {
203 if (item == list[i]) {
204 return true;
205 }
206 }
207
208 return false;
209}
210
211static bool xrdc_check_lpav(enum xrdc_comp_type type, uint16_t id)
212{
213 return xrdc_check_pd(type, id, XRDC_AV_PD);
214}
215
216static bool xrdc_check_hifi(enum xrdc_comp_type type, uint16_t id)
217{
218 return xrdc_check_pd(type, id, XRDC_HIFI_PD);
219}
220
221static bool xrdc_check_ad(enum xrdc_comp_type type, uint16_t id)
222{
223 return (!xrdc_check_pd(type, id, XRDC_HIFI_PD) &&
224 !xrdc_check_pd(type, id, XRDC_AV_PD));
225}
226
227static int xrdc_apply_config(xrdc_check_func check_func)
228{
229 unsigned int i, j;
230 uint32_t val;
231
232 for (i = 0U; i < ARRAY_SIZE(imx8ulp_mda); i++) {
233 if (check_func(MDA_TYPE, imx8ulp_mda[i].mda_id)) {
234 xrdc_config_mda(imx8ulp_mda[i].mda_id,
235 imx8ulp_mda[i].did, imx8ulp_mda[i].sa);
236 }
237 }
238
239 for (i = 0U; i < ARRAY_SIZE(imx8ulp_mrc); i++) {
240 if (check_func(MRC_TYPE, imx8ulp_mrc[i].mrc_id)) {
241 xrdc_config_mrc_w0_w1(imx8ulp_mrc[i].mrc_id,
242 imx8ulp_mrc[i].region_id,
243 imx8ulp_mrc[i].region_start,
244 imx8ulp_mrc[i].region_size);
245
246 val = 0;
247 for (j = 0U; j < DID_MAX; j++) {
248 val |= imx8ulp_mrc[i].dsel[j] << (3 * j);
249 }
250
251 xrdc_config_mrc_w2(imx8ulp_mrc[i].mrc_id, imx8ulp_mrc[i].region_id, val);
252 xrdc_config_mrc_w3_w4(imx8ulp_mrc[i].mrc_id, imx8ulp_mrc[i].region_id,
253 0, imx8ulp_mrc[i].accset[0] | (imx8ulp_mrc[i].accset[1] << 16) | BIT_32(31));
254 }
255 }
256
257 for (i = 0U; i < ARRAY_SIZE(imx8ulp_pdac); i++) {
258 if (check_func(PAC_TYPE, imx8ulp_pdac[i].pac_msc_id)) {
259 val = 0;
260 for (j = 0U; j < DID_MAX; j++) {
261 val |= imx8ulp_pdac[i].dsel[j] << (3 * j);
262 }
263
264 if (imx8ulp_pdac[i].slot_id == PAC_SLOT_ALL) {
265 /* Apply to all slots*/
266 for (j = 0U; j < imx8ulp_pac_slots[imx8ulp_pdac[i].pac_msc_id]; j++) {
267 xrdc_config_pac(imx8ulp_pdac[i].pac_msc_id, j, val);
268 }
269 } else {
270 if (imx8ulp_pdac[i].slot_id >= imx8ulp_pac_slots[imx8ulp_pdac[i].pac_msc_id]) {
271 return -EINVAL;
272 }
273
274 xrdc_config_pac(imx8ulp_pdac[i].pac_msc_id, imx8ulp_pdac[i].slot_id, val);
275 }
276 }
277 }
278
279 for (i = 0U; i < ARRAY_SIZE(imx8ulp_msc); i++) {
280 if (check_func(MSC_TYPE, imx8ulp_msc[i].pac_msc_id)) {
281 val = 0;
282 for (j = 0U; j < DID_MAX; j++) {
283 val |= imx8ulp_msc[i].dsel[j] << (3 * j);
284 }
285
286 if (imx8ulp_msc[i].slot_id == MSC_SLOT_ALL) {
287 /* Apply to all slots*/
288 for (j = 0U; j < imx8ulp_msc_slots[imx8ulp_msc[i].pac_msc_id]; j++) {
289 xrdc_config_msc(imx8ulp_msc[i].pac_msc_id, j, val);
290 }
291 } else {
292 if (imx8ulp_msc[i].slot_id >= imx8ulp_msc_slots[imx8ulp_msc[i].pac_msc_id]) {
293 return -EINVAL;
294 }
295
296 xrdc_config_msc(imx8ulp_msc[i].pac_msc_id, imx8ulp_msc[i].slot_id, val);
297 }
298 }
299 }
300
301 return 0;
302}
303
304int xrdc_apply_lpav_config(void)
305{
Ye Lid3724c12022-11-21 11:20:35 +0800306 /* Configure PAC2 to allow to access PCC5 */
307 xrdc_config_pac(2, 39, 0xe00000);
308
Jacky Bai7ec94512023-09-21 14:01:37 +0800309 /* Enable the eDMA2 MP clock for MDA16 access */
310 mmio_write_32(IMX_PCC5_BASE + 0x0, 0xc0000000);
311 return xrdc_apply_config(xrdc_check_lpav);
312}
313
314int xrdc_apply_hifi_config(void)
315{
316 return xrdc_apply_config(xrdc_check_hifi);
317}
318
319int xrdc_apply_apd_config(void)
320{
321 return xrdc_apply_config(xrdc_check_ad);
322}
323
324void xrdc_enable(void)
325{
326 mmio_write_32(XRDC_ADDR, BIT(14) | BIT(15) | BIT(0));
327}