mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-16 01:24:27 +00:00

After resume from APD power down, XRDC is initialized by S400 but the PAC2 and MSC0-2 are not configured, so only DBD owner can access the resources. We have to move GPIO restore after TFA XRDC reinit and configure PDAC for PCC5 before enabling eDMA2 MP clock Signed-off-by: Ye Li <ye.li@nxp.com> Signed-off-by: Jacky Bai <ping.bai@nxp.com> Change-Id: I82748de080151b0bdf1cace092b7892a1e402a27
327 lines
7.1 KiB
C
327 lines
7.1 KiB
C
/*
|
|
* 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));
|
|
}
|