diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 17:43:51 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 17:43:51 +0000 |
commit | be58c81aff4cd4c0ccf43dbd7998da4a6a08c03b (patch) | |
tree | 779c248fb61c83f65d1f0dc867f2053d76b4e03a /plat/hisilicon/hikey960/drivers | |
parent | Initial commit. (diff) | |
download | arm-trusted-firmware-be58c81aff4cd4c0ccf43dbd7998da4a6a08c03b.tar.xz arm-trusted-firmware-be58c81aff4cd4c0ccf43dbd7998da4a6a08c03b.zip |
Adding upstream version 2.10.0+dfsg.upstream/2.10.0+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'plat/hisilicon/hikey960/drivers')
-rw-r--r-- | plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c | 206 | ||||
-rw-r--r-- | plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c | 417 | ||||
-rw-r--r-- | plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h | 57 |
3 files changed, 680 insertions, 0 deletions
diff --git a/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c b/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c new file mode 100644 index 0000000..a6a4949 --- /dev/null +++ b/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <common/debug.h> +#include <lib/mmio.h> +#include <plat/common/platform.h> + +#include <hi3660.h> +#include <hisi_ipc.h> +#include "../../hikey960_private.h" + +#define IPC_MBX_SOURCE_REG(m) (IPC_BASE + ((m) << 6)) +#define IPC_MBX_DSET_REG(m) (IPC_BASE + ((m) << 6) + 0x04) +#define IPC_MBX_DCLEAR_REG(m) (IPC_BASE + ((m) << 6) + 0x08) +#define IPC_MBX_DSTATUS_REG(m) (IPC_BASE + ((m) << 6) + 0x0C) +#define IPC_MBX_MODE_REG(m) (IPC_BASE + ((m) << 6) + 0x10) +#define IPC_MBX_IMASK_REG(m) (IPC_BASE + ((m) << 6) + 0x14) +#define IPC_MBX_ICLR_REG(m) (IPC_BASE + ((m) << 6) + 0x18) +#define IPC_MBX_SEND_REG(m) (IPC_BASE + ((m) << 6) + 0x1C) +#define IPC_MBX_DATA_REG(m, d) (IPC_BASE + ((m) << 6) + 0x20 + \ + ((d) * 4)) +#define IPC_CPU_IMST_REG(m) (IPC_BASE + ((m) << 3)) +#define IPC_LOCK_REG (IPC_BASE + 0xA00) +#define IPC_ACK_BIT_SHIFT (1 << 7) +#define IPC_UNLOCK_VALUE (0x1ACCE551) + +/********************************************************* + *bit[31:24]:0~AP + *bit[23:16]:0x1~A15, 0x2~A7 + *bit[15:8]:0~ON, 1~OFF + *bit[7:0]:0x3 cpu power mode + *********************************************************/ +#define IPC_CMD_TYPE(src_obj, cluster_obj, is_off, mode) \ + ((src_obj << 24) | (((cluster_obj) + 1) << 16) | (is_off << 8) | (mode)) + +/********************************************************* + *bit[15:8]:0~no idle, 1~idle + *bit[7:0]:cpux + *********************************************************/ + +#define IPC_CMD_PARA(is_idle, cpu) \ + ((is_idle << 8) | (cpu)) + +#define IPC_STATE_IDLE 0x10 + +enum src_id { + SRC_IDLE = 0, + SRC_A15 = 1 << 0, + SRC_A7 = 1 << 1, + SRC_IOM3 = 1 << 2, + SRC_LPM3 = 1 << 3 +}; + +/*lpm3's mailboxs are 13~17*/ +enum lpm3_mbox_id { + LPM3_MBX0 = 13, + LPM3_MBX1, + LPM3_MBX2, + LPM3_MBX3, + LPM3_MBX4, +}; + +static void cpu_relax(void) +{ + volatile int i; + + for (i = 0; i < 10; i++) + nop(); +} + +static inline void +hisi_ipc_clear_ack(enum src_id source, enum lpm3_mbox_id mbox) +{ + unsigned int int_status = 0; + + do { + int_status = mmio_read_32(IPC_MBX_MODE_REG(mbox)); + int_status &= 0xF0; + cpu_relax(); + } while (int_status != IPC_ACK_BIT_SHIFT); + + mmio_write_32(IPC_MBX_ICLR_REG(mbox), source); +} + +static void +hisi_ipc_send_cmd_with_ack(enum src_id source, enum lpm3_mbox_id mbox, + unsigned int cmdtype, unsigned int cmdpara) +{ + unsigned int regval; + unsigned int mask; + unsigned int state; + + mmio_write_32(IPC_LOCK_REG, IPC_UNLOCK_VALUE); + /* wait for idle and occupy */ + do { + state = mmio_read_32(IPC_MBX_MODE_REG(mbox)); + if (state == IPC_STATE_IDLE) { + mmio_write_32(IPC_MBX_SOURCE_REG(mbox), source); + regval = mmio_read_32(IPC_MBX_SOURCE_REG(mbox)); + if (regval == source) + break; + } + cpu_relax(); + + } while (1); + + /* auto answer */ + mmio_write_32(IPC_MBX_MODE_REG(mbox), 0x1); + + mask = (~((int)source | SRC_LPM3) & 0x3F); + /* mask the other cpus */ + mmio_write_32(IPC_MBX_IMASK_REG(mbox), mask); + /* set data */ + mmio_write_32(IPC_MBX_DATA_REG(mbox, 0), cmdtype); + mmio_write_32(IPC_MBX_DATA_REG(mbox, 1), cmdpara); + /* send cmd */ + mmio_write_32(IPC_MBX_SEND_REG(mbox), source); + /* wait ack and clear */ + hisi_ipc_clear_ack(source, mbox); + + /* release mailbox */ + mmio_write_32(IPC_MBX_SOURCE_REG(mbox), source); +} + +void hisi_ipc_pm_on_off(unsigned int core, unsigned int cluster, + enum pm_mode mode) +{ + unsigned int cmdtype = 0; + unsigned int cmdpara = 0; + enum src_id source = SRC_IDLE; + enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core); + + cmdtype = IPC_CMD_TYPE(0, cluster, mode, 0x3); + cmdpara = IPC_CMD_PARA(0, core); + source = cluster ? SRC_A7 : SRC_A15; + hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara); +} + +void hisi_ipc_pm_suspend(unsigned int core, unsigned int cluster, + unsigned int affinity_level) +{ + unsigned int cmdtype = 0; + unsigned int cmdpara = 0; + enum src_id source = SRC_IDLE; + enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core); + + if (affinity_level == 0x3) + cmdtype = IPC_CMD_TYPE(0, -1, 0x1, 0x3 + affinity_level); + else + cmdtype = IPC_CMD_TYPE(0, cluster, 0x1, 0x3 + affinity_level); + + cmdpara = IPC_CMD_PARA(1, core); + source = cluster ? SRC_A7 : SRC_A15; + hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara); +} + +void hisi_ipc_psci_system_off(unsigned int core, unsigned int cluster) +{ + unsigned int cmdtype = 0; + unsigned int cmdpara = 0; + enum src_id source = SRC_IDLE; + enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core); + + cmdtype = IPC_CMD_TYPE(0, (0x10 - 1), 0x1, 0x0); + cmdpara = IPC_CMD_PARA(0, 0); + source = cluster ? SRC_A7 : SRC_A15; + hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara); +} + +void hisi_ipc_psci_system_reset(unsigned int core, unsigned int cluster, + unsigned int cmd_id) +{ + unsigned int cmdtype = 0; + unsigned int cmdpara = 0; + enum src_id source = SRC_IDLE; + enum lpm3_mbox_id mailbox = (enum lpm3_mbox_id)(LPM3_MBX0 + core); + + cmdtype = IPC_CMD_TYPE(0, (0x10 - 1), 0x0, 0x0); + cmdpara = cmd_id; + source = cluster ? SRC_A7 : SRC_A15; + hisi_ipc_send_cmd_with_ack(source, mailbox, cmdtype, cmdpara); +} + +int hisi_ipc_init(void) +{ + int ret = 0; + enum lpm3_mbox_id i = LPM3_MBX0; + + mmio_write_32(IPC_LOCK_REG, IPC_UNLOCK_VALUE); + for (i = LPM3_MBX0; i <= LPM3_MBX4; i++) { + mmio_write_32(IPC_MBX_MODE_REG(i), 1); + mmio_write_32(IPC_MBX_IMASK_REG(i), + ((int)SRC_IOM3 | (int)SRC_A15 | (int)SRC_A7)); + mmio_write_32(IPC_MBX_ICLR_REG(i), SRC_A7); + } + + return ret; +} diff --git a/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c new file mode 100644 index 0000000..91d8033 --- /dev/null +++ b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <platform_def.h> + +#include <arch_helpers.h> +#include <lib/mmio.h> +#include <plat/common/platform.h> + +#include <../hikey960_def.h> +#include <hisi_ipc.h> +#include "hisi_pwrc.h" + + +/* resource lock api */ +#define RES0_LOCK_BASE (SOC_PCTRL_RESOURCE0_LOCK_ADDR(PCTRL_BASE)) +#define RES1_LOCK_BASE (SOC_PCTRL_RESOURCE1_LOCK_ADDR(PCTRL_BASE)) +#define RES2_LOCK_BASE (SOC_PCTRL_RESOURCE2_LOCK_ADDR(PCTRL_BASE)) + +#define LOCK_BIT (0x1 << 28) +#define LOCK_ID_MASK (0x7u << 29) +#define CPUIDLE_LOCK_ID(core) (0x6 - (core)) +#define LOCK_UNLOCK_OFFSET 0x4 +#define LOCK_STAT_OFFSET 0x8 + +#define CLUSTER0_CPUS_ONLINE_MASK (0xF << 16) +#define CLUSTER1_CPUS_ONLINE_MASK (0xF << 20) + +/* cpu hotplug flag api */ +#define SCTRL_BASE (SOC_ACPU_SCTRL_BASE_ADDR) +#define REG_SCBAKDATA3_OFFSET (SOC_SCTRL_SCBAKDATA3_ADDR(SCTRL_BASE)) +#define REG_SCBAKDATA8_OFFSET (SOC_SCTRL_SCBAKDATA8_ADDR(SCTRL_BASE)) +#define REG_SCBAKDATA9_OFFSET (SOC_SCTRL_SCBAKDATA9_ADDR(SCTRL_BASE)) + +#define CPUIDLE_FLAG_REG(cluster) \ + ((cluster == 0) ? REG_SCBAKDATA8_OFFSET : \ + REG_SCBAKDATA9_OFFSET) +#define CLUSTER_IDLE_BIT BIT(8) +#define CLUSTER_IDLE_MASK (CLUSTER_IDLE_BIT | 0x0F) + +#define AP_SUSPEND_FLAG (1 << 16) + +#define CLUSTER_PWDN_IDLE (0<<28) +#define CLUSTER_PWDN_HOTPLUG (1<<28) +#define CLUSTER_PWDN_SR (2<<28) + +#define CLUSTER0_PDC_OFFSET 0x260 +#define CLUSTER1_PDC_OFFSET 0x300 + +#define PDC_EN_OFFSET 0x0 +#define PDC_COREPWRINTEN_OFFSET 0x4 +#define PDC_COREPWRINTSTAT_OFFSET 0x8 +#define PDC_COREGICMASK_OFFSET 0xc +#define PDC_COREPOWERUP_OFFSET 0x10 +#define PDC_COREPOWERDN_OFFSET 0x14 +#define PDC_COREPOWERSTAT_OFFSET 0x18 + +#define PDC_COREPWRSTAT_MASK (0XFFFF) + +enum pdc_gic_mask { + PDC_MASK_GIC_WAKE_IRQ, + PDC_UNMASK_GIC_WAKE_IRQ +}; + +enum pdc_finish_int_mask { + PDC_DISABLE_FINISH_INT, + PDC_ENABLE_FINISH_INT +}; + +static void hisi_resource_lock(unsigned int lockid, unsigned int offset) +{ + unsigned int lock_id = (lockid << 29); + unsigned int lock_val = lock_id | LOCK_BIT; + unsigned int lock_state; + + do { + mmio_write_32(offset, lock_val); + lock_state = mmio_read_32(LOCK_STAT_OFFSET + (uintptr_t)offset); + } while ((lock_state & LOCK_ID_MASK) != lock_id); +} + +static void hisi_resource_unlock(unsigned int lockid, unsigned int offset) +{ + unsigned int lock_val = (lockid << 29) | LOCK_BIT; + + mmio_write_32((LOCK_UNLOCK_OFFSET + (uintptr_t)offset), lock_val); +} + + +static void hisi_cpuhotplug_lock(unsigned int cluster, unsigned int core) +{ + unsigned int lock_id; + + lock_id = (cluster << 2) + core; + + hisi_resource_lock(lock_id, RES2_LOCK_BASE); +} + +static void hisi_cpuhotplug_unlock(unsigned int cluster, unsigned int core) +{ + unsigned int lock_id; + + lock_id = (cluster << 2) + core; + + hisi_resource_unlock(lock_id, RES2_LOCK_BASE); +} + +/* get the resource lock */ +void hisi_cpuidle_lock(unsigned int cluster, unsigned int core) +{ + unsigned int offset = (cluster == 0 ? RES0_LOCK_BASE : RES1_LOCK_BASE); + + hisi_resource_lock(CPUIDLE_LOCK_ID(core), offset); +} + +/* release the resource lock */ +void hisi_cpuidle_unlock(unsigned int cluster, unsigned int core) +{ + unsigned int offset = (cluster == 0 ? RES0_LOCK_BASE : RES1_LOCK_BASE); + + hisi_resource_unlock(CPUIDLE_LOCK_ID(core), offset); +} + +unsigned int hisi_get_cpuidle_flag(unsigned int cluster) +{ + unsigned int val; + + val = mmio_read_32(CPUIDLE_FLAG_REG(cluster)); + val &= 0xF; + + return val; +} + +void hisi_set_cpuidle_flag(unsigned int cluster, unsigned int core) +{ + mmio_setbits_32(CPUIDLE_FLAG_REG(cluster), BIT(core)); +} + +void hisi_clear_cpuidle_flag(unsigned int cluster, unsigned int core) +{ + mmio_clrbits_32(CPUIDLE_FLAG_REG(cluster), BIT(core)); + +} + +int hisi_test_ap_suspend_flag(void) +{ + unsigned int val1; + unsigned int val2; + + val1 = mmio_read_32(CPUIDLE_FLAG_REG(0)); + val1 &= AP_SUSPEND_FLAG; + + val2 = mmio_read_32(CPUIDLE_FLAG_REG(1)); + val2 &= AP_SUSPEND_FLAG; + + val1 |= val2; + return (val1 != 0); +} + +void hisi_set_cluster_pwdn_flag(unsigned int cluster, + unsigned int core, unsigned int value) +{ + unsigned int val; + + hisi_cpuhotplug_lock(cluster, core); + + val = mmio_read_32(REG_SCBAKDATA3_OFFSET); + val &= ~(0x3U << ((2 * cluster) + 28)); + val |= (value << (2 * cluster)); + mmio_write_32(REG_SCBAKDATA3_OFFSET, val); + + hisi_cpuhotplug_unlock(cluster, core); +} + +unsigned int hisi_get_cpu_boot_flag(unsigned int cluster, unsigned int core) +{ + unsigned int val; + + hisi_cpuhotplug_lock(cluster, core); + val = mmio_read_32(REG_SCBAKDATA3_OFFSET); + val = val >> (16 + (cluster << 2)); + val &= 0xF; + hisi_cpuhotplug_unlock(cluster, core); + + return val; +} + +unsigned int hisi_test_cpu_down(unsigned int cluster, unsigned int core) +{ + unsigned int val; + + hisi_cpuhotplug_lock(cluster, core); + val = mmio_read_32(REG_SCBAKDATA3_OFFSET); + val = val >> (16 + (cluster << 2)); + val &= 0xF; + hisi_cpuhotplug_unlock(cluster, core); + + if (val) + return 0; + else + return 1; +} + +void hisi_set_cpu_boot_flag(unsigned int cluster, unsigned int core) +{ + unsigned int flag = BIT((cluster<<2) + core + 16); + + hisi_cpuhotplug_lock(cluster, core); + + mmio_setbits_32(REG_SCBAKDATA3_OFFSET, flag); + + hisi_cpuhotplug_unlock(cluster, core); +} + +void hisi_clear_cpu_boot_flag(unsigned int cluster, unsigned int core) +{ + unsigned int flag = BIT((cluster<<2) + core + 16); + + hisi_cpuhotplug_lock(cluster, core); + + mmio_clrbits_32(REG_SCBAKDATA3_OFFSET, flag); + + hisi_cpuhotplug_unlock(cluster, core); +} + +int cluster_is_powered_on(unsigned int cluster) +{ + unsigned int val = mmio_read_32(REG_SCBAKDATA3_OFFSET); + int ret; + + if (cluster == 0) + ret = val & CLUSTER0_CPUS_ONLINE_MASK; + else + ret = val & CLUSTER1_CPUS_ONLINE_MASK; + + return !!ret; +} + +static void *hisi_get_pdc_addr(unsigned int cluster) +{ + void *pdc_base_addr; + uintptr_t addr; + + if (cluster == 0) + addr = SOC_CRGPERIPH_A53_PDCEN_ADDR(CRG_BASE); + else + addr = SOC_CRGPERIPH_MAIA_PDCEN_ADDR(CRG_BASE); + pdc_base_addr = (void *)addr; + + return pdc_base_addr; +} + +static unsigned int hisi_get_pdc_stat(unsigned int cluster) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + unsigned int val; + + val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREPOWERSTAT_OFFSET); + + return val; +} + +static int check_hotplug(unsigned int cluster, unsigned int boot_flag) +{ + unsigned int mask = 0xF; + + if (hisi_test_ap_suspend_flag() || + ((boot_flag & mask) == mask)) + return 0; + + return 1; +} + +int hisi_test_pwrdn_allcores(unsigned int cluster, unsigned int core) +{ + unsigned int mask = 0xf << (core * 4); + unsigned int pdc_stat = hisi_get_pdc_stat(cluster); + unsigned int boot_flag = hisi_get_cpu_boot_flag(cluster, core); + unsigned int cpuidle_flag = hisi_get_cpuidle_flag(cluster); + + mask = (PDC_COREPWRSTAT_MASK & (~mask)); + pdc_stat &= mask; + + if ((boot_flag ^ cpuidle_flag) || pdc_stat || + check_hotplug(cluster, boot_flag)) + return 0; + else + return 1; +} + +void hisi_disable_pdc(unsigned int cluster) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + mmio_write_32((uintptr_t)pdc_base_addr, 0x0); +} + +void hisi_enable_pdc(unsigned int cluster) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + mmio_write_32((uintptr_t)pdc_base_addr, 0x1); +} + +void hisi_pdc_set_intmask(void *pdc_base_addr, + unsigned int core, + enum pdc_finish_int_mask intmask) +{ + unsigned int val; + + val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET); + if (intmask == PDC_ENABLE_FINISH_INT) + val |= BIT(core); + else + val &= ~BIT(core); + + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET, val); +} + +static inline void hisi_pdc_set_gicmask(void *pdc_base_addr, + unsigned int core, + enum pdc_gic_mask gicmask) +{ + unsigned int val; + + val = mmio_read_32((uintptr_t)pdc_base_addr + PDC_COREGICMASK_OFFSET); + if (gicmask == PDC_MASK_GIC_WAKE_IRQ) + val |= BIT(core); + else + val &= ~BIT(core); + + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREGICMASK_OFFSET, val); +} + +void hisi_pdc_mask_cluster_wakeirq(unsigned int cluster) +{ + int i; + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + for (i = 0; i < 4; i++) + hisi_pdc_set_gicmask(pdc_base_addr, i, PDC_MASK_GIC_WAKE_IRQ); +} + +static void hisi_pdc_powerup_core(unsigned int cluster, unsigned int core, + enum pdc_gic_mask gicmask, + enum pdc_finish_int_mask intmask) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERUP_OFFSET, + BIT(core)); +} + +static void hisi_pdc_powerdn_core(unsigned int cluster, unsigned int core, + enum pdc_gic_mask gicmask, + enum pdc_finish_int_mask intmask) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET, + BIT(core)); +} + +void hisi_powerup_core(unsigned int cluster, unsigned int core) +{ + hisi_pdc_powerup_core(cluster, core, PDC_MASK_GIC_WAKE_IRQ, + PDC_DISABLE_FINISH_INT); +} + +void hisi_powerdn_core(unsigned int cluster, unsigned int core) +{ + hisi_pdc_powerdn_core(cluster, core, PDC_MASK_GIC_WAKE_IRQ, + PDC_DISABLE_FINISH_INT); +} + +void hisi_powerup_cluster(unsigned int cluster, unsigned int core) +{ + hisi_ipc_pm_on_off(core, cluster, PM_ON); +} + +void hisi_powerdn_cluster(unsigned int cluster, unsigned int core) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + hisi_set_cluster_pwdn_flag(cluster, core, CLUSTER_PWDN_HOTPLUG); + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET, + (0x10001 << core)); + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET, + BIT(core)); +} + +void hisi_enter_core_idle(unsigned int cluster, unsigned int core) +{ + hisi_pdc_powerdn_core(cluster, core, PDC_UNMASK_GIC_WAKE_IRQ, + PDC_DISABLE_FINISH_INT); +} + +void hisi_enter_cluster_idle(unsigned int cluster, unsigned int core) +{ + void *pdc_base_addr = hisi_get_pdc_addr(cluster); + + hisi_set_cluster_pwdn_flag(cluster, core, CLUSTER_PWDN_IDLE); + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPWRINTEN_OFFSET, + (0x10001 << core)); + mmio_write_32((uintptr_t)pdc_base_addr + PDC_COREPOWERDN_OFFSET, + BIT(core)); +} + +void hisi_enter_ap_suspend(unsigned int cluster, unsigned int core) +{ + hisi_ipc_pm_suspend(core, cluster, 0x3); +} diff --git a/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h new file mode 100644 index 0000000..e0cb381 --- /dev/null +++ b/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HISI_PWRC_H +#define HISI_PWRC_H + +#include <hi3660.h> +#include <hi3660_crg.h> + +#define PCTRL_BASE (PCTRL_REG_BASE) +#define CRG_BASE (CRG_REG_BASE) + +#define SOC_CRGPERIPH_A53_PDCEN_ADDR(base) ((base) + (0x260)) +#define SOC_CRGPERIPH_MAIA_PDCEN_ADDR(base) ((base) + (0x300)) + +#define SOC_PCTRL_RESOURCE0_LOCK_ADDR(base) ((base) + (0x400)) +#define SOC_PCTRL_RESOURCE0_UNLOCK_ADDR(base) ((base) + (0x404)) +#define SOC_PCTRL_RESOURCE0_LOCK_ST_ADDR(base) ((base) + (0x408)) +#define SOC_PCTRL_RESOURCE1_LOCK_ADDR(base) ((base) + (0x40C)) +#define SOC_PCTRL_RESOURCE1_UNLOCK_ADDR(base) ((base) + (0x410)) +#define SOC_PCTRL_RESOURCE1_LOCK_ST_ADDR(base) ((base) + (0x414)) +#define SOC_PCTRL_RESOURCE2_LOCK_ADDR(base) ((base) + (0x418)) + +#define SOC_SCTRL_SCBAKDATA3_ADDR(base) ((base) + (0x418)) +#define SOC_SCTRL_SCBAKDATA8_ADDR(base) ((base) + (0x42C)) +#define SOC_SCTRL_SCBAKDATA9_ADDR(base) ((base) + (0x430)) + +#define SOC_ACPU_SCTRL_BASE_ADDR (0xFFF0A000) + +void hisi_cpuidle_lock(unsigned int cluster, unsigned int core); +void hisi_cpuidle_unlock(unsigned int cluster, unsigned int core); +void hisi_set_cpuidle_flag(unsigned int cluster, unsigned int core); +void hisi_clear_cpuidle_flag(unsigned int cluster, unsigned int core); +void hisi_set_cpu_boot_flag(unsigned int cluster, unsigned int core); +void hisi_clear_cpu_boot_flag(unsigned int cluster, unsigned int core); +int cluster_is_powered_on(unsigned int cluster); +void hisi_enter_core_idle(unsigned int cluster, unsigned int core); +void hisi_enter_cluster_idle(unsigned int cluster, unsigned int core); +int hisi_test_ap_suspend_flag(void); +void hisi_enter_ap_suspend(unsigned int cluster, unsigned int core); + + +/* pdc api */ +void hisi_pdc_mask_cluster_wakeirq(unsigned int cluster); +int hisi_test_pwrdn_allcores(unsigned int cluster, unsigned int core); +void hisi_disable_pdc(unsigned int cluster); +void hisi_enable_pdc(unsigned int cluster); +void hisi_powerup_core(unsigned int cluster, unsigned int core); +void hisi_powerdn_core(unsigned int cluster, unsigned int core); +void hisi_powerup_cluster(unsigned int cluster, unsigned int core); +void hisi_powerdn_cluster(unsigned int cluster, unsigned int core); +unsigned int hisi_test_cpu_down(unsigned int cluster, unsigned int core); + +#endif /* HISI_PWRC_H */ |