Skip to content

Commit

Permalink
lk2nd: smp: add msm8994 cpu boot support
Browse files Browse the repository at this point in the history
Signed-off-by: Eugene Lepshy <[email protected]>
  • Loading branch information
fekz115 committed May 12, 2023
1 parent 02ef037 commit 1b4db14
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 0 deletions.
20 changes: 20 additions & 0 deletions lk2nd/smp/cpu-boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,23 @@ static uint32_t read_phandle_reg(const void *dtb, int node, const char *prop)
return read_phandle_reg_indexed(dtb, node, prop, 0);
}

#if CPU_BOOT_CORTEX_A_MSM8994
bool boot_msm8994_cpu(const void *dtb, int acc, int node) {
node = lkfdt_lookup_phandle(dtb, node, "next-level-cache");
if (node < 0) {
dprintf(CRITICAL, "Cannot find CPU next-level-cache: %d\n", node);
return false;
}
uint32_t l2ccc_base = read_phandle_reg(dtb, node, "power-domain");
node = lkfdt_lookup_phandle(dtb, node, "power-domain");
uint32_t vctl_base_0 = read_phandle_reg_indexed(dtb, node, "qcom,vctl-node", 0);
uint32_t vctl_base_1 = read_phandle_reg_indexed(dtb, node, "qcom,vctl-node", 1);
uint32_t vctl_val = read_phandle_value(dtb, node, "qcom,vctl-val");
cpu_boot_cortex_a_msm8994(acc, l2ccc_base, vctl_base_0, vctl_base_1, vctl_val);
return true;
}
#endif

bool cpu_boot(const void *dtb, int node, uint32_t mpidr)
{
uint32_t acc, extra_reg __UNUSED;
Expand All @@ -182,6 +199,9 @@ bool cpu_boot(const void *dtb, int node, uint32_t mpidr)
*/
extra_reg = read_phandle_reg(dtb, node, "clocks");
cpu_boot_cortex_a(acc, extra_reg);
#elif CPU_BOOT_CORTEX_A_MSM8994
if(!boot_msm8994_cpu(dtb, acc, node))
return false;
#elif CPU_BOOT_KPSSV1
extra_reg = read_phandle_reg(dtb, node, "qcom,saw");
if (!extra_reg)
Expand Down
28 changes: 28 additions & 0 deletions lk2nd/smp/cpu-boot.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,35 @@
int cpu_boot_set_addr(uintptr_t addr, bool arm64);

bool cpu_boot(const void *dtb, int node, uint32_t mpidr);

/**
* @brief This function boot cpus for msm8994/2 if firmware doesn't
* support pcsi
*
* @note cpu node must contain `next-level-cache`
* @note cache node must contain `power-domain`
* @note power-domain node must contain `qcom,vctl-node`
* and might contain `qcom,vctl-val`
*
* @return true if core successfully booted
*/
bool boot_msm8994_cpu(const void *dtb, int acc, int node);
void cpu_boot_cortex_a(uint32_t base, uint32_t apcs_base);

/**
* @brief This function enables core with the address stored in `base`
*
* As l2 cache for first(boot) cluster enabled by lk1st,
* this function skips it and work only for second cluster
*
* @param base value of current cpu reg
* @param l2ccc_base value of l2 clock controller reg
* @param vctl_base_0 first `qcom,vctl-node` reg address
* @param vctl_base_1 second `qcom,vctl-node` reg address
* @param vctl_val The value to be set on the rail
*/
void cpu_boot_cortex_a_msm8994(uint32_t base, uint32_t l2ccc_base,
uint32_t vctl_base_0, uint32_t vctl_base_1, uint32_t vctl_val);
void cpu_boot_kpssv1(uint32_t reg, uint32_t saw_reg);
void cpu_boot_kpssv2(uint32_t reg, uint32_t l2_saw_base);

Expand Down
180 changes: 180 additions & 0 deletions lk2nd/smp/gpl/cortex-a-msm8994.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2023, Eugene Lepshy <[email protected]> */

#include <arch/defines.h>
#include <bits.h>
#include <debug.h>
#include <kernel/thread.h>
#include <platform/timer.h>
#include <reg.h>

#include "../cpu-boot.h"

#define CPU_PWR_CTL 0x4
#define APC_PWR_GATE_CTL 0x14

#define L1_RST_DIS 0x284

#define L2_VREG_CTL 0x1c
#define L2_PWR_CTL 0x14
#define L2_PWR_CTL_OVERRIDE 0xc
#define L2_PWR_STATUS_L2_HS_STS_MSM8994 (BIT(9) | BIT(28))

/**
* @brief delay for voltage to settle on the core
*/
#define REGULATOR_SETUP_VOLTAGE_TIMEOUT 2000

/**
* @brief Power on cpu rail before turning on core
* @param vctl_base_0 first `qcom,vctl-node` reg address
* @param vctl_base_1 second `qcom,vctl-node` reg address
* @param vctl_val The value to be set on the rail
*/
static void msm_spm_turn_on_cpu_rail(uint32_t vctl_base_0, uint32_t vctl_base_1,
unsigned int vctl_val)
{
if (vctl_base_1) {
/*
* Program Q2S to disable SPM legacy mode and ignore Q2S
* channel requests.
* bit[1] = qchannel_ignore = 1
* bit[2] = spm_legacy_mode = 0
*/
writel(0x2, vctl_base_1);
dsb();
}

/* Set the CPU supply regulator voltage */
vctl_val = (vctl_val & 0xFF);
writel(vctl_val, vctl_base_0 + L2_VREG_CTL);
dsb();
udelay(REGULATOR_SETUP_VOLTAGE_TIMEOUT);

/* Enable the CPU supply regulator*/
vctl_val = 0x30080;
writel(vctl_val, vctl_base_0 + L2_VREG_CTL);
dsb();
udelay(REGULATOR_SETUP_VOLTAGE_TIMEOUT);
}

/**
* @brief This function used to enable l2 cache
*
* As l2 cache for first(boot) cluster enabled by lk1st,
* this function skips it and work only for second cluster
*
* @param l2ccc_base value of l2 clock controller reg
* @param vctl_base_0 first `qcom,vctl-node` reg address
* @param vctl_base_1 second `qcom,vctl-node` reg address
* @param vctl_val The value to be set on the rail
* @note Function has a check if cache at `l2ccc_base` already enabled
*/
static void power_on_l2_cache_msm8994(uint32_t l2ccc_base, uint32_t vctl_base_0,
uint32_t vctl_base_1, uint32_t vctl_val) {
/* Skip if cluster L2 is already powered on */
if (readl(l2ccc_base + L2_PWR_CTL) & L2_PWR_STATUS_L2_HS_STS_MSM8994)
return;

msm_spm_turn_on_cpu_rail(vctl_base_0, vctl_base_1, vctl_val);

dprintf(INFO, "Powering on L2 cache @ %#08x\n", l2ccc_base);

enter_critical_section();

/* Enable L1 invalidation by h/w */
writel(0x00000000, l2ccc_base + L1_RST_DIS);
dsb();

/* Assert PRESETDBGn */
writel(0x00400000 , l2ccc_base + L2_PWR_CTL_OVERRIDE);
dsb();

/* Close L2/SCU Logic GDHS and power up the cache */
writel(0x00029716 , l2ccc_base + L2_PWR_CTL);
dsb();
udelay(8);

/* De-assert L2/SCU memory Clamp */
writel(0x00023716 , l2ccc_base + L2_PWR_CTL);
dsb();

/* Wakeup L2/SCU RAMs by deasserting sleep signals */
writel(0x0002371E , l2ccc_base + L2_PWR_CTL);
dsb();
udelay(8);

/* Un-gate clock and wait for sequential waking up
* of L2 rams with a delay of 2*X0 cycles
*/
writel(0x0002371C , l2ccc_base + L2_PWR_CTL);
dsb();
udelay(4);

/* De-assert L2/SCU logic clamp */
writel(0x0002361C , l2ccc_base + L2_PWR_CTL);
dsb();
udelay(2);

/* De-assert L2/SCU logic reset */
writel(0x00022218 , l2ccc_base + L2_PWR_CTL);
dsb();
udelay(4);

/* Turn on the PMIC_APC */
writel(0x10022218 , l2ccc_base + L2_PWR_CTL);
dsb();

/* De-assert PRESETDBGn */
writel(0x00000000 , l2ccc_base + L2_PWR_CTL_OVERRIDE);
dsb();
exit_critical_section();
}

void cpu_boot_cortex_a_msm8994(uint32_t base, uint32_t l2ccc_base,
uint32_t vctl_base_0, uint32_t vctl_base_1, uint32_t vctl_val)
{
if (l2ccc_base)
power_on_l2_cache_msm8994(l2ccc_base, vctl_base_0, vctl_base_1, vctl_val);

enter_critical_section();

/* Assert head switch enable few */
writel(0x00000001, base + APC_PWR_GATE_CTL);
dsb();
udelay(1);

/* Assert head switch enable rest */
writel(0x00000003, base + APC_PWR_GATE_CTL);
dsb();
udelay(1);

/* De-assert coremem clamp. This is asserted by default */
writel(0x00000079, base + CPU_PWR_CTL);
dsb();
udelay(2);

/* Close coremem array gdhs */
writel(0x0000007D, base + CPU_PWR_CTL);
dsb();
udelay(2);

/* De-assert clamp */
writel(0x0000003D, base + CPU_PWR_CTL);
dsb();

/* De-assert clamp */
writel(0x0000003C, base + CPU_PWR_CTL);
dsb();
udelay(1);

/* De-assert core0 reset */
writel(0x0000000C, base + CPU_PWR_CTL);
dsb();

/* Assert PWRDUP */
writel(0x0000008C, base + CPU_PWR_CTL);
dsb();

exit_critical_section();
}
3 changes: 3 additions & 0 deletions lk2nd/smp/rules.mk
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ OBJS += $(patsubst %.c,%.o, $(wildcard $(LOCAL_DIR)/clock-$(PLATFORM).c))
ifneq ($(filter msm8226 msm8610 msm8909 msm8916, $(PLATFORM)),)
CPU_BOOT_OBJ := $(LOCAL_DIR)/cortex-a.o
DEFINES += CPU_BOOT_CORTEX_A=1
else ifneq ($(filter msm8994, $(PLATFORM)),)
CPU_BOOT_OBJ := $(if $(BUILD_GPL), $(LOCAL_DIR)/gpl/cortex-a-msm8994.o)
DEFINES += CPU_BOOT_CORTEX_A_MSM8994=1
else ifneq ($(filter apq8084 msm8974, $(PLATFORM)),)
CPU_BOOT_OBJ := $(if $(BUILD_GPL), $(LOCAL_DIR)/gpl/krait.o)
DEFINES += CPU_BOOT_KPSSV2=1
Expand Down

0 comments on commit 1b4db14

Please sign in to comment.