GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
+259
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <sspm_reg.h>
|
||||
#include <mtk_mcdi.h>
|
||||
|
||||
static inline uint32_t mcdi_mbox_read(uint32_t id)
|
||||
{
|
||||
return mmio_read_32(SSPM_MBOX_3_BASE + (id << 2));
|
||||
}
|
||||
|
||||
static inline void mcdi_mbox_write(uint32_t id, uint32_t val)
|
||||
{
|
||||
mmio_write_32(SSPM_MBOX_3_BASE + (id << 2), val);
|
||||
}
|
||||
|
||||
void sspm_set_bootaddr(uint32_t bootaddr)
|
||||
{
|
||||
mcdi_mbox_write(MCDI_MBOX_BOOTADDR, bootaddr);
|
||||
}
|
||||
|
||||
void sspm_cluster_pwr_off_notify(uint32_t cluster)
|
||||
{
|
||||
mcdi_mbox_write(MCDI_MBOX_CLUSTER_0_ATF_ACTION_DONE + cluster, 1);
|
||||
}
|
||||
|
||||
void sspm_cluster_pwr_on_notify(uint32_t cluster)
|
||||
{
|
||||
mcdi_mbox_write(MCDI_MBOX_CLUSTER_0_ATF_ACTION_DONE + cluster, 0);
|
||||
}
|
||||
|
||||
void sspm_standbywfi_irq_enable(uint32_t cpu_idx)
|
||||
{
|
||||
mmio_write_32(SSPM_CFGREG_ACAO_INT_SET, STANDBYWFI_EN(cpu_idx));
|
||||
}
|
||||
|
||||
uint32_t mcdi_avail_cpu_mask_read(void)
|
||||
{
|
||||
return mcdi_mbox_read(MCDI_MBOX_AVAIL_CPU_MASK);
|
||||
}
|
||||
|
||||
uint32_t mcdi_avail_cpu_mask_write(uint32_t mask)
|
||||
{
|
||||
mcdi_mbox_write(MCDI_MBOX_AVAIL_CPU_MASK, mask);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
uint32_t mcdi_avail_cpu_mask_set(uint32_t mask)
|
||||
{
|
||||
uint32_t m;
|
||||
|
||||
m = mcdi_mbox_read(MCDI_MBOX_AVAIL_CPU_MASK);
|
||||
m |= mask;
|
||||
mcdi_mbox_write(MCDI_MBOX_AVAIL_CPU_MASK, m);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
uint32_t mcdi_avail_cpu_mask_clr(uint32_t mask)
|
||||
{
|
||||
uint32_t m;
|
||||
|
||||
m = mcdi_mbox_read(MCDI_MBOX_AVAIL_CPU_MASK);
|
||||
m &= ~mask;
|
||||
mcdi_mbox_write(MCDI_MBOX_AVAIL_CPU_MASK, m);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
uint32_t mcdi_cpu_cluster_pwr_stat_read(void)
|
||||
{
|
||||
return mcdi_mbox_read(MCDI_MBOX_CPU_CLUSTER_PWR_STAT);
|
||||
}
|
||||
|
||||
#define PAUSE_BIT 1
|
||||
#define CLUSTER_OFF_OFS 20
|
||||
#define CPU_OFF_OFS 24
|
||||
#define CLUSTER_ON_OFS 4
|
||||
#define CPU_ON_OFS 8
|
||||
|
||||
static uint32_t target_mask(int cluster, int cpu_idx, bool on)
|
||||
{
|
||||
uint32_t t = 0;
|
||||
|
||||
if (on) {
|
||||
if (cluster >= 0)
|
||||
t |= BIT(cluster + CLUSTER_ON_OFS);
|
||||
|
||||
if (cpu_idx >= 0)
|
||||
t |= BIT(cpu_idx + CPU_ON_OFS);
|
||||
} else {
|
||||
if (cluster >= 0)
|
||||
t |= BIT(cluster + CLUSTER_OFF_OFS);
|
||||
|
||||
if (cpu_idx >= 0)
|
||||
t |= BIT(cpu_idx + CPU_OFF_OFS);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void mcdi_pause_clr(int cluster, int cpu_idx, bool on)
|
||||
{
|
||||
uint32_t tgt = target_mask(cluster, cpu_idx, on);
|
||||
uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION);
|
||||
|
||||
m &= ~tgt;
|
||||
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
|
||||
}
|
||||
|
||||
void mcdi_pause_set(int cluster, int cpu_idx, bool on)
|
||||
{
|
||||
uint32_t tgt = target_mask(cluster, cpu_idx, on);
|
||||
uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION);
|
||||
uint32_t tgtn = target_mask(-1, cpu_idx, !on);
|
||||
|
||||
/* request on and off at the same time to ensure it can be paused */
|
||||
m |= tgt | tgtn;
|
||||
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
|
||||
|
||||
/* wait pause_ack */
|
||||
while (!mcdi_mbox_read(MCDI_MBOX_PAUSE_ACK))
|
||||
;
|
||||
|
||||
/* clear non-requested operation */
|
||||
m &= ~tgtn;
|
||||
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
|
||||
}
|
||||
|
||||
void mcdi_pause(void)
|
||||
{
|
||||
uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) | BIT(PAUSE_BIT);
|
||||
|
||||
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
|
||||
|
||||
/* wait pause_ack */
|
||||
while (!mcdi_mbox_read(MCDI_MBOX_PAUSE_ACK))
|
||||
;
|
||||
}
|
||||
|
||||
void mcdi_unpause(void)
|
||||
{
|
||||
uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) & ~BIT(PAUSE_BIT);
|
||||
|
||||
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
|
||||
}
|
||||
|
||||
void mcdi_hotplug_wait_ack(int cluster, int cpu_idx, bool on)
|
||||
{
|
||||
uint32_t tgt = target_mask(cluster, cpu_idx, on);
|
||||
uint32_t ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
|
||||
|
||||
/* wait until ack */
|
||||
while (!(ack & tgt))
|
||||
ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
|
||||
}
|
||||
|
||||
void mcdi_hotplug_clr(int cluster, int cpu_idx, bool on)
|
||||
{
|
||||
uint32_t tgt = target_mask(cluster, cpu_idx, on);
|
||||
uint32_t tgt_cpu = target_mask(-1, cpu_idx, on);
|
||||
uint32_t cmd = mcdi_mbox_read(MCDI_MBOX_HP_CMD);
|
||||
uint32_t ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
|
||||
|
||||
if (!(cmd & tgt))
|
||||
return;
|
||||
|
||||
/* wait until ack */
|
||||
while (!(ack & tgt_cpu))
|
||||
ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
|
||||
|
||||
cmd &= ~tgt;
|
||||
mcdi_mbox_write(MCDI_MBOX_HP_CMD, cmd);
|
||||
}
|
||||
|
||||
void mcdi_hotplug_set(int cluster, int cpu_idx, bool on)
|
||||
{
|
||||
uint32_t tgt = target_mask(cluster, cpu_idx, on);
|
||||
uint32_t tgt_cpu = target_mask(-1, cpu_idx, on);
|
||||
uint32_t cmd = mcdi_mbox_read(MCDI_MBOX_HP_CMD);
|
||||
uint32_t ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
|
||||
|
||||
if ((cmd & tgt) == tgt)
|
||||
return;
|
||||
|
||||
/* wait until ack clear */
|
||||
while (ack & tgt_cpu)
|
||||
ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
|
||||
|
||||
cmd |= tgt;
|
||||
mcdi_mbox_write(MCDI_MBOX_HP_CMD, cmd);
|
||||
}
|
||||
|
||||
bool check_mcdi_ctl_stat(void)
|
||||
{
|
||||
uint32_t clk_regs[] = {0x100010ac, 0x100010c8};
|
||||
uint32_t clk_mask[] = {0x00028000, 0x00000018};
|
||||
uint32_t tgt = target_mask(0, 0, true);
|
||||
uint32_t m;
|
||||
int i;
|
||||
|
||||
/* check clk status */
|
||||
for (i = 0; i < ARRAY_SIZE(clk_regs); i++) {
|
||||
if (mmio_read_32(clk_regs[i]) & clk_mask[i]) {
|
||||
WARN("mcdi: clk check fail.\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* check mcdi cmd handling */
|
||||
m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) | BIT(PAUSE_BIT);
|
||||
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
|
||||
|
||||
i = 500;
|
||||
while (!mcdi_mbox_read(MCDI_MBOX_PAUSE_ACK) && --i > 0)
|
||||
udelay(10);
|
||||
|
||||
m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) & ~BIT(PAUSE_BIT);
|
||||
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
|
||||
|
||||
if (i == 0) {
|
||||
WARN("mcdi: pause_action fail.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check mcdi cmd handling */
|
||||
if (mcdi_mbox_read(MCDI_MBOX_HP_CMD) ||
|
||||
mcdi_mbox_read(MCDI_MBOX_HP_ACK)) {
|
||||
WARN("mcdi: hp_cmd fail.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
mcdi_mbox_write(MCDI_MBOX_HP_CMD, tgt);
|
||||
|
||||
i = 500;
|
||||
while ((mcdi_mbox_read(MCDI_MBOX_HP_ACK) & tgt) != tgt && --i > 0)
|
||||
udelay(10);
|
||||
|
||||
mcdi_mbox_write(MCDI_MBOX_HP_CMD, 0);
|
||||
|
||||
if (i == 0) {
|
||||
WARN("mcdi: hp_ack fail.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void mcdi_init(void)
|
||||
{
|
||||
mcdi_avail_cpu_mask_write(0x01); /* cpu0 default on */
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __MTK_MCDI_H__
|
||||
#define __MTK_MCDI_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
void sspm_set_bootaddr(uint32_t bootaddr);
|
||||
void sspm_standbywfi_irq_enable(uint32_t cpu_idx);
|
||||
void sspm_cluster_pwr_off_notify(uint32_t cluster);
|
||||
void sspm_cluster_pwr_on_notify(uint32_t cluster);
|
||||
|
||||
uint32_t mcdi_avail_cpu_mask_read(void);
|
||||
uint32_t mcdi_avail_cpu_mask_write(uint32_t mask);
|
||||
uint32_t mcdi_avail_cpu_mask_set(uint32_t mask);
|
||||
uint32_t mcdi_avail_cpu_mask_clr(uint32_t mask);
|
||||
uint32_t mcdi_cpu_cluster_pwr_stat_read(void);
|
||||
|
||||
void mcdi_pause(void);
|
||||
void mcdi_unpause(void);
|
||||
void mcdi_pause_set(int cluster, int cpu_idx, bool on);
|
||||
void mcdi_pause_clr(int cluster, int cpu_idx, bool on);
|
||||
void mcdi_hotplug_set(int cluster, int cpu_idx, bool on);
|
||||
void mcdi_hotplug_clr(int cluster, int cpu_idx, bool on);
|
||||
void mcdi_hotplug_wait_ack(int cluster, int cpu_idx, bool on);
|
||||
|
||||
bool check_mcdi_ctl_stat(void);
|
||||
void mcdi_init(void);
|
||||
|
||||
#endif /* __MTK_MCDI_H__ */
|
||||
Reference in New Issue
Block a user