123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- /*
- * Copyright 2020-2024 NXP
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <assert.h>
- #include <errno.h>
- #include <stdbool.h>
- #include <common/debug.h>
- #include <lib/mmio.h>
- #include <plat/common/platform.h>
- #include <platform_def.h>
- #include "xrdc_config.h"
- #define XRDC_ADDR 0x292f0000
- #define MRC_OFFSET 0x2000
- #define MRC_STEP 0x200
- #define XRDC_MGR_PAC_ID U(0)
- #define XRDC_MGR_PAC_SLOT U(47)
- enum xrdc_comp_type {
- MDA_TYPE = (1 << 16),
- MRC_TYPE = (2 << 16),
- PAC_TYPE = (3 << 16),
- MSC_TYPE = (4 << 16),
- };
- enum xrdc_pd_type {
- XRDC_AD_PD,
- XRDC_HIFI_PD,
- XRDC_AV_PD,
- };
- #define XRDC_TYPE_MASK (0x7 << 16)
- #define XRDC_ID_MASK 0xFFFF
- #define XRDC_ID(id) ((id) & XRDC_ID_MASK)
- typedef bool (*xrdc_check_func)(enum xrdc_comp_type type, uint16_t id);
- /* Access below XRDC needs enable PS 8
- * and HIFI clocks and release HIFI firstly
- */
- uint32_t hifi_xrdc_list[] = {
- (MDA_TYPE | XRDC_ID(9)),
- (MRC_TYPE | XRDC_ID(7)),
- (MRC_TYPE | XRDC_ID(9)),
- (MRC_TYPE | XRDC_ID(11)),
- };
- /* Access below XRDC needs enable PS 16 firstly */
- uint32_t av_periph_xrdc_list[] = {
- (MDA_TYPE | XRDC_ID(10)),
- (MDA_TYPE | XRDC_ID(11)),
- (MDA_TYPE | XRDC_ID(12)),
- (MDA_TYPE | XRDC_ID(13)),
- (MDA_TYPE | XRDC_ID(14)),
- (MDA_TYPE | XRDC_ID(15)),
- (MDA_TYPE | XRDC_ID(16)),
- (PAC_TYPE | XRDC_ID(2)),
- (MRC_TYPE | XRDC_ID(6)),
- (MRC_TYPE | XRDC_ID(8)),
- (MRC_TYPE | XRDC_ID(10)),
- (MSC_TYPE | XRDC_ID(1)),
- (MSC_TYPE | XRDC_ID(2)),
- };
- uint32_t imx8ulp_pac_slots[] = {
- 61, 23, 53
- };
- uint32_t imx8ulp_msc_slots[] = {
- 2, 1, 7
- };
- static int xrdc_config_mrc_w0_w1(uint32_t mrc_con, uint32_t region, uint32_t w0, uint32_t size)
- {
- uint32_t w0_addr, w1_addr;
- w0_addr = XRDC_ADDR + MRC_OFFSET + mrc_con * 0x200 + region * 0x20;
- w1_addr = w0_addr + 4;
- if ((size % 32) != 0) {
- return -EINVAL;
- }
- mmio_write_32(w0_addr, w0 & ~0x1f);
- mmio_write_32(w1_addr, w0 + size - 1);
- return 0;
- }
- static int xrdc_config_mrc_w2(uint32_t mrc_con, uint32_t region, uint32_t dxsel_all)
- {
- uint32_t w2_addr;
- w2_addr = XRDC_ADDR + MRC_OFFSET + mrc_con * 0x200 + region * 0x20 + 0x8;
- mmio_write_32(w2_addr, dxsel_all);
- return 0;
- }
- static int xrdc_config_mrc_w3_w4(uint32_t mrc_con, uint32_t region, uint32_t w3, uint32_t w4)
- {
- uint32_t w3_addr = XRDC_ADDR + MRC_OFFSET + mrc_con * 0x200 + region * 0x20 + 0xC;
- uint32_t w4_addr = w3_addr + 4;
- mmio_write_32(w3_addr, w3);
- mmio_write_32(w4_addr, w4);
- return 0;
- }
- static int xrdc_config_pac(uint32_t pac, uint32_t index, uint32_t dxacp)
- {
- uint32_t w0_addr;
- uint32_t val;
- if (pac > 2U) {
- return -EINVAL;
- }
- /* Skip the PAC slot for XRDC MGR, use Sentinel configuration */
- if (pac == XRDC_MGR_PAC_ID && index == XRDC_MGR_PAC_SLOT) {
- return 0;
- }
- w0_addr = XRDC_ADDR + 0x1000 + 0x400 * pac + 0x8 * index;
- mmio_write_32(w0_addr, dxacp);
- val = mmio_read_32(w0_addr + 4);
- mmio_write_32(w0_addr + 4, val | BIT_32(31));
- return 0;
- }
- static int xrdc_config_msc(uint32_t msc, uint32_t index, uint32_t dxacp)
- {
- uint32_t w0_addr;
- uint32_t val;
- if (msc > 2) {
- return -EINVAL;
- }
- w0_addr = XRDC_ADDR + 0x4000 + 0x400 * msc + 0x8 * index;
- mmio_write_32(w0_addr, dxacp);
- val = mmio_read_32(w0_addr + 4);
- mmio_write_32(w0_addr + 4, val | BIT_32(31));
- return 0;
- }
- static int xrdc_config_mda(uint32_t mda_con, uint32_t dom, enum xrdc_mda_sa sa)
- {
- uint32_t w0_addr;
- uint32_t val;
- w0_addr = XRDC_ADDR + 0x800 + mda_con * 0x20;
- val = mmio_read_32(w0_addr);
- if (val & BIT_32(29)) {
- mmio_write_32(w0_addr, (val & (~0xFF)) | dom |
- BIT_32(31) | 0x20 | ((sa & 0x3) << 6));
- } else {
- mmio_write_32(w0_addr, dom | BIT_32(31));
- mmio_write_32(w0_addr + 0x4, dom | BIT_32(31));
- }
- return 0;
- }
- static bool xrdc_check_pd(enum xrdc_comp_type type,
- uint16_t id, enum xrdc_pd_type pd)
- {
- unsigned int i, size;
- uint32_t item = type | XRDC_ID(id);
- uint32_t *list;
- if (pd == XRDC_HIFI_PD) {
- size = ARRAY_SIZE(hifi_xrdc_list);
- list = hifi_xrdc_list;
- } else if (pd == XRDC_AV_PD) {
- size = ARRAY_SIZE(av_periph_xrdc_list);
- list = av_periph_xrdc_list;
- } else {
- return false;
- }
- for (i = 0U; i < size; i++) {
- if (item == list[i]) {
- return true;
- }
- }
- return false;
- }
- static bool xrdc_check_lpav(enum xrdc_comp_type type, uint16_t id)
- {
- return xrdc_check_pd(type, id, XRDC_AV_PD);
- }
- static bool xrdc_check_hifi(enum xrdc_comp_type type, uint16_t id)
- {
- return xrdc_check_pd(type, id, XRDC_HIFI_PD);
- }
- static bool xrdc_check_ad(enum xrdc_comp_type type, uint16_t id)
- {
- return (!xrdc_check_pd(type, id, XRDC_HIFI_PD) &&
- !xrdc_check_pd(type, id, XRDC_AV_PD));
- }
- static int xrdc_apply_config(xrdc_check_func check_func)
- {
- unsigned int i, j;
- uint32_t val;
- for (i = 0U; i < ARRAY_SIZE(imx8ulp_mda); i++) {
- if (check_func(MDA_TYPE, imx8ulp_mda[i].mda_id)) {
- xrdc_config_mda(imx8ulp_mda[i].mda_id,
- imx8ulp_mda[i].did, imx8ulp_mda[i].sa);
- }
- }
- for (i = 0U; i < ARRAY_SIZE(imx8ulp_mrc); i++) {
- if (check_func(MRC_TYPE, imx8ulp_mrc[i].mrc_id)) {
- xrdc_config_mrc_w0_w1(imx8ulp_mrc[i].mrc_id,
- imx8ulp_mrc[i].region_id,
- imx8ulp_mrc[i].region_start,
- imx8ulp_mrc[i].region_size);
- val = 0;
- for (j = 0U; j < DID_MAX; j++) {
- val |= imx8ulp_mrc[i].dsel[j] << (3 * j);
- }
- xrdc_config_mrc_w2(imx8ulp_mrc[i].mrc_id, imx8ulp_mrc[i].region_id, val);
- xrdc_config_mrc_w3_w4(imx8ulp_mrc[i].mrc_id, imx8ulp_mrc[i].region_id,
- 0, imx8ulp_mrc[i].accset[0] | (imx8ulp_mrc[i].accset[1] << 16) | BIT_32(31));
- }
- }
- for (i = 0U; i < ARRAY_SIZE(imx8ulp_pdac); i++) {
- if (check_func(PAC_TYPE, imx8ulp_pdac[i].pac_msc_id)) {
- val = 0;
- for (j = 0U; j < DID_MAX; j++) {
- val |= imx8ulp_pdac[i].dsel[j] << (3 * j);
- }
- if (imx8ulp_pdac[i].slot_id == PAC_SLOT_ALL) {
- /* Apply to all slots*/
- for (j = 0U; j < imx8ulp_pac_slots[imx8ulp_pdac[i].pac_msc_id]; j++) {
- xrdc_config_pac(imx8ulp_pdac[i].pac_msc_id, j, val);
- }
- } else {
- if (imx8ulp_pdac[i].slot_id >= imx8ulp_pac_slots[imx8ulp_pdac[i].pac_msc_id]) {
- return -EINVAL;
- }
- xrdc_config_pac(imx8ulp_pdac[i].pac_msc_id, imx8ulp_pdac[i].slot_id, val);
- }
- }
- }
- for (i = 0U; i < ARRAY_SIZE(imx8ulp_msc); i++) {
- if (check_func(MSC_TYPE, imx8ulp_msc[i].pac_msc_id)) {
- val = 0;
- for (j = 0U; j < DID_MAX; j++) {
- val |= imx8ulp_msc[i].dsel[j] << (3 * j);
- }
- if (imx8ulp_msc[i].slot_id == MSC_SLOT_ALL) {
- /* Apply to all slots*/
- for (j = 0U; j < imx8ulp_msc_slots[imx8ulp_msc[i].pac_msc_id]; j++) {
- xrdc_config_msc(imx8ulp_msc[i].pac_msc_id, j, val);
- }
- } else {
- if (imx8ulp_msc[i].slot_id >= imx8ulp_msc_slots[imx8ulp_msc[i].pac_msc_id]) {
- return -EINVAL;
- }
- xrdc_config_msc(imx8ulp_msc[i].pac_msc_id, imx8ulp_msc[i].slot_id, val);
- }
- }
- }
- return 0;
- }
- int xrdc_apply_lpav_config(void)
- {
- /* Configure PAC2 to allow to access PCC5 */
- xrdc_config_pac(2, 39, 0xe00000);
- /* Enable the eDMA2 MP clock for MDA16 access */
- mmio_write_32(IMX_PCC5_BASE + 0x0, 0xc0000000);
- return xrdc_apply_config(xrdc_check_lpav);
- }
- int xrdc_apply_hifi_config(void)
- {
- return xrdc_apply_config(xrdc_check_hifi);
- }
- int xrdc_apply_apd_config(void)
- {
- return xrdc_apply_config(xrdc_check_ad);
- }
- void xrdc_enable(void)
- {
- mmio_write_32(XRDC_ADDR, BIT(14) | BIT(15) | BIT(0));
- }
|