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