Commit 0c2ffb04 authored by Jacky Bai's avatar Jacky Bai

plat: imx8m: use SGI8 for DDR DVFS

using INTR_TYPE_EL3 SGI8 for DDR DVFS IPI interrupts.
Signed-off-by: default avatarJacky Bai <ping.bai@nxp.com>
parent 0a0edb20
......@@ -11,6 +11,7 @@
#include <spinlock.h>
#include <smccc.h>
#include <imx_sip.h>
#include <interrupt_mgmt.h>
static struct dram_info dram_info;
......@@ -18,11 +19,8 @@ static struct dram_info dram_info;
spinlock_t dfs_lock;
/* IRQ used for DDR DVFS */
#if defined(PLAT_IMX8M)
static uint32_t irqs_used [] = {102, 109, 110, 111};
/* ocram used to dram timing */
static uint8_t dram_timing_saved[13 * 1024] __aligned(8);
#else
static uint32_t irqs_used[] = {74, 75, 76, 77};
#endif
static volatile uint32_t wfe_done;
static volatile bool wait_ddrc_hwffc_done = true;
......@@ -157,6 +155,35 @@ static bool is_bypass_mode_enabled(struct dram_timing_info *info)
return true;
}
/* EL3 SGI-8 handler */
static uint64_t waiting_dvfs(uint32_t id, uint32_t flags,
void *handle, void *cookie)
{
uint64_t mpidr = read_mpidr_el1();
unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
uint32_t irq;
irq = plat_ic_acknowledge_interrupt();
if (irq < 1022U) {
plat_ic_end_of_interrupt(irq);
}
/* set the WFE done status */
spin_lock(&dfs_lock);
wfe_done |= (1 << cpu_id * 8);
dsb();
spin_unlock(&dfs_lock);
while (1) {
/* ddr frequency change done */
wfe();
if (!wait_ddrc_hwffc_done)
break;
}
return 0;
}
void dram_info_init(unsigned long dram_timing_base)
{
uint32_t current_fsp, ddr_type, ddrc_mstr;
......@@ -198,6 +225,17 @@ void dram_info_init(unsigned long dram_timing_base)
dcsw_op_all(DCCSW);
ddr4_swffc(&dram_info, 0x0);
}
/* register the SGI handler for DVFS */
uint64_t flags = 0;
uint64_t rc;
set_interrupt_rm_flag(flags, NON_SECURE);
set_interrupt_rm_flag(flags, SECURE);
rc = register_interrupt_type_handler(INTR_TYPE_EL3, waiting_dvfs, flags);
if(rc)
panic();
}
void dram_enter_retention(void)
......@@ -236,9 +274,8 @@ int dram_dvfs_handler(uint32_t smc_fid,
while (1) {
/* ddr frequency change done */
wfe();
if (!wait_ddrc_hwffc_done) {
if (!wait_ddrc_hwffc_done)
break;
}
}
} else if (x1 == IMX_SIP_DDR_DVFS_GET_FREQ_COUNT) {
int i;
......@@ -254,21 +291,18 @@ int dram_dvfs_handler(uint32_t smc_fid,
} else if (x1 < 4) {
wait_ddrc_hwffc_done = true;
dsb();
/* trigger the IRQ */
for (int i = 0; i < 4; i++) {
int irq = irqs_used[i] % 32;
if (cpu_id != i && (online_cores & (0x1 << (i * 8)))) {
mmio_write_32(0x38800204 + (irqs_used[i] / 32) * 4, (1 << irq));
}
}
/* trigger the SGI to info other cores */
for (int i = 0; i < PLATFORM_CORE_COUNT; i++)
if (cpu_id != i && (online_cores & (0x1 << (i * 8))))
plat_ic_raise_el3_sgi(0x8, i);
/* make sure all the core in WFE */
online_cores &= ~(0x1 << (cpu_id * 8));
#if defined(PLAT_IMX8M)
for (int i = 0; i < 4; i++) {
if (i != cpu_id && online_cores & (1 << (i * 8))) {
if (i != cpu_id && online_cores & (1 << (i * 8)))
imx_gpc_core_wake(1 << i);
}
}
#endif
while (1) {
......
......@@ -16,9 +16,7 @@
uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
static const interrupt_prop_t g01s_interrupt_props[] = {
INTR_PROP_DESC(6, GIC_HIGHEST_SEC_PRIORITY,
INTR_GROUP1S, GIC_INTR_CFG_LEVEL),
INTR_PROP_DESC(7, GIC_HIGHEST_SEC_PRIORITY,
INTR_PROP_DESC(8, GIC_HIGHEST_SEC_PRIORITY,
INTR_GROUP0, GIC_INTR_CFG_LEVEL),
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment