Skip to content
Closed
5 changes: 5 additions & 0 deletions core/arch/arm/plat-qcom/hoya/kodiak/target_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,9 @@
#define IRIS_BASE UL(0x0aa00000)
#define IRIS_SIZE ULL(0x00200000)

#define PAS_ID_QDSP6 1
#define PAS_ID_WPSS 6
#define PAS_ID_VENUS 9
#define PAS_ID_TURING 18

#endif /* TARGET_CONFIG_H */
12 changes: 12 additions & 0 deletions core/arch/arm/plat-qcom/hoya/lemans/target.mk
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
CFG_DRIVERS_CLK ?= y
CFG_DRIVERS_QCOM_CLK ?= y

CFG_QCOM_TLMM ?= y

CFG_QCOM_QFPROM_FUSEPROV ?= $(if $(filter y,$(CFG_INSECURE)),n,y)

_qcom_fuseprov_deps = $(if $(filter y,$(CFG_QCOM_QFPROM_FUSEPROV)),y,n)
CFG_QCOM_CMD_DB ?= $(_qcom_fuseprov_deps)
CFG_QCOM_RPMH_CLIENT ?= $(_qcom_fuseprov_deps)
CFG_QCOM_QFPROM ?= $(_qcom_fuseprov_deps)

CFG_QCOM_PAS_PTA ?= y

ifeq ($(CFG_QCOM_PAS_PTA),y)
# PAS subsystems map their controller windows at runtime from the reserved VA
# pool (never released). The six DSP windows total ~146.5 MB; the 60 MB default
# fits only one, so reserve 256 MB with headroom.
CFG_RESERVED_VASPACE_SIZE ?= (256 * 1024 * 1024)
CFG_IN_TREE_EARLY_TAS += qcom_pas/cff7d191-7ca0-4784-af13-48223b9a4fbe
endif
80 changes: 80 additions & 0 deletions core/arch/arm/plat-qcom/hoya/lemans/target_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,84 @@

#define GENI_UART_REG_BASE UL(0xa8c000)

/* TLMM — from msmhwiobase.h and GPIOLemans.c */
#define TLMM_BASE UL(0x0f000000)
#define TLMM_BASE_SIZE UL(0x01000000)

#ifdef CFG_QCOM_TLMM
#ifndef __ASSEMBLER__
#include <drivers/qcom/tlmm/tlmm.h>
extern const struct tlmm_desc tlmm_soc_desc;
#endif
#endif

#define TURING_0_BASE UL(0x24000000)
#define TURING_0_SIZE UL(0x03000000)

#define TURING_1_BASE UL(0x28000000)
#define TURING_1_SIZE UL(0x03000000)

/*
* GP-DSP0 / GP-DSP1 (TURINGGDSP / TURINGGDSP1) subsystems. The window covers
* every GP-DSP sub-block the PTA and clock driver touch (GDSP_CC 0x808000, PUB
* 0xc00000, PLL 0xc40000, CORE_CC 0xc48000).
*/
#define TURING_GDSP_0_BASE UL(0x20000000)
#define TURING_GDSP_0_SIZE UL(0x01000000)

#define TURING_GDSP_1_BASE UL(0x21000000)
#define TURING_GDSP_1_SIZE UL(0x01000000)

/*
* LPASS / ADSP (QDSP6 v68/v69) subsystem window, covering every sub-block the
* PTA and clock driver touch (PUB, PLL, CORE_CC, AON_CC, MCC, TOP_CC).
*/
#define LPASS_BASE UL(0x02c00000)
#define LPASS_SIZE ULL(0x01080000)

/*
* IRIS video-codec subsystem. The window covers the VCODEC_IRIS_WRAPPER_TOP
* (IRIS+0xb0000) and WRAPPER_TZ (IRIS+0xc0000) blocks the bring-up path
* touches.
*/
#define IRIS_BASE UL(0x0aa00000)
#define IRIS_SIZE ULL(0x00200000)

#define PAS_ID_TURING 18
#define PAS_ID_TURING1 30
#define PAS_ID_QDSP6 1
#define PAS_ID_IRIS 9
#define PAS_ID_GPDSP0 39
#define PAS_ID_GPDSP1 40

/* CDSP0 content-protection shared channel (secure DDR); no CDSP1 equivalent. */
#define CDSP_SECCHANNEL_BASE UL(0xdb1dc000)
#define CDSP_SECCHANNEL_SIZE UL(0x2000)

/*
* Global register blocks for the Turing/NSP reset sequence, under AOSS_BASE
* (0x0b000000). TCSR_MUTEX_BASE/SIZE is already defined in arch_config.h.
*/
#define AOSS_CC_BASE UL(0x0c2a8000)
#define AOSS_CC_SIZE UL(0x00050000)

#define RPMH_PDC_GLOBAL_BASE UL(0x0b5e0000)
#define RPMH_PDC_GLOBAL_SIZE UL(0x00002000)

#define RPMH_PDC_COMPUTE_BASE UL(0x0b2c0000)
#define RPMH_PDC_COMPUTE_SIZE UL(0x00002000)

#define RPMH_PDC_NSP_BASE UL(0x0b2f0000)
#define RPMH_PDC_NSP_SIZE UL(0x00002000)

/*
* RPMH PDC blocks for the GP-DSP subsystem reset sequence. These live under
* AOSS_BASE (0x0b000000), at offsets 0x240000 / 0x2d0000.
*/
#define RPMH_PDC_GPDSP0_BASE UL(0x0b240000)
#define RPMH_PDC_GPDSP0_SIZE UL(0x00002000)

#define RPMH_PDC_GPDSP1_BASE UL(0x0b2d0000)
#define RPMH_PDC_GPDSP1_SIZE UL(0x00002000)

#endif /* TARGET_CONFIG_H */
31 changes: 31 additions & 0 deletions core/arch/arm/plat-qcom/hoya/lemans/tlmm_soc_data.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: BSD-2-Clause
/*
* LeMans TLMM hardware descriptor.
*
* Values sourced from GPIOLemans.c (HALgpioBlockDescType):
* nBaseAddr = 0x0f000000 (TLMM_BASE)
* nPinRegWidth = 0x1000
* nNumTiles = 1
* aTiles[0] = 0x100000
* nMaxPinNumber = 148 (num_gpios = 149)
* has_egpio = true
* has_strong_pull = false
*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/

#include <platform_config.h>
#include <drivers/qcom/tlmm/tlmm.h>
#include <util.h>

const struct tlmm_desc tlmm_soc_desc = {
.base = TLMM_BASE,
.size = TLMM_BASE_SIZE,
.pin_reg_width = 0x1000,
.num_tiles = 1,
.tile_offsets = { 0x100000, 0, 0, 0, 0 },
.num_gpios = 149,
.has_egpio = true,
.has_strong_pull = false,
.lp_cfg_mask = GENMASK_32(12, 0),
};
1 change: 1 addition & 0 deletions core/arch/arm/plat-qcom/sub.mk
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ global-incdirs-y += .
global-incdirs-y += $(QCOM_ARCH_FAMILY)
global-incdirs-y += $(QCOM_ARCH_FAMILY)/$(PLATFORM_FLAVOR)
srcs-y += main.c
srcs-$(CFG_QCOM_TLMM) += $(QCOM_ARCH_FAMILY)/$(PLATFORM_FLAVOR)/tlmm_soc_data.c

$(eval $(call cfg-depends-all,CFG_QCOM_QFPROM_FUSEPROV,CFG_QCOM_QFPROM))
subdirs-$(CFG_QCOM_QFPROM_FUSEPROV) += provision
108 changes: 108 additions & 0 deletions core/drivers/clk/qcom/clock-qcom.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,41 @@ register_phys_mem(MEM_AREA_IO_NSEC, GCC_BASE, GCC_SIZE);
#define CBCR_HW_CTL_ENABLE_BIT BIT(1)
#define CBCR_BRANCH_OFF_BIT BIT(31)

/* Lucid-EVO PLL register offsets, relative to the PLL register block base. */
#define PLL_MODE 0x0
#define PLL_OPMODE 0x4
#define PLL_L_VAL 0x10
#define PLL_ALPHA_VAL 0x14
#define PLL_USER_CTL 0x18
#define PLL_USER_CTL_U 0x1c
#define PLL_CONFIG_CTL 0x20
#define PLL_CONFIG_CTL_U 0x24
#define PLL_CONFIG_CTL_U1 0x28

/* PLL_MODE fields */
#define PLL_MODE_OUTCTRL BIT(0)
#define PLL_MODE_RESET_N BIT(2)
#define PLL_MODE_LOCK_DET BIT(31)

/* PLL_OPMODE values */
#define PLL_OPMODE_RUN 0x1

/* PLL_L_VAL fields */
#define PLL_L_VAL_L_MASK 0x0000ffff
#define PLL_L_VAL_CAL_L_SHIFT 16
#define PLL_L_VAL_CAL_L_MASK 0xffff0000

/* PLL_USER_CTL fields */
#define PLL_USER_CTL_PLLOUT_MAIN_EN BIT(0)
#define PLL_USER_CTL_PRE_DIV_SHIFT 22
#define PLL_USER_CTL_PRE_DIV_MASK 0x01c00000
#define PLL_USER_CTL_POST_DIV_ODD_MASK 0x0003c000
#define PLL_USER_CTL_POST_DIV_EVEN_MASK 0x00003c00
#define PLL_USER_CTL_FRAC_FORMAT_SEL BIT(28)

/* PLL_USER_CTL_U fields */
#define PLL_USER_CTL_U_FINE_LOCK_DET BIT(0)

static inline bool cbcr_branch_on(uint32_t val)
{
return !(val & CBCR_BRANCH_OFF_BIT);
Expand All @@ -26,6 +61,14 @@ TEE_Result qcom_clock_enable_cbc(vaddr_t cbcr)

io_setbits32(cbcr, CBCR_BRANCH_ENABLE_BIT);

/*
* In hardware clock-control mode (HW_CTL set) CLK_OFF is driven by HW,
* not the software CLK_ENABLE write, so skip the poll to avoid
* spinning.
*/
if (io_read32(cbcr) & CBCR_HW_CTL_ENABLE_BIT)
return TEE_SUCCESS;

REG_POLL_TIMEOUT(cbcr, 10 * 1000, 10, &ret, cbcr_branch_on);

if (ret < 0)
Expand All @@ -34,6 +77,68 @@ TEE_Result qcom_clock_enable_cbc(vaddr_t cbcr)
return TEE_SUCCESS;
}

static inline bool pll_locked(uint32_t val)
{
return val & PLL_MODE_LOCK_DET;
}

TEE_Result qcom_lucidevo_pll_enable(vaddr_t pll_base,
const struct qcom_lucidevo_pll_config *cfg)
{
uint32_t user_val = 0;
int ret = 0;

/* Reg settings: program the static PLL trim/config registers. */
io_write32(pll_base + PLL_CONFIG_CTL, cfg->config_ctl);
io_write32(pll_base + PLL_CONFIG_CTL_U, cfg->config_ctl_u);
io_write32(pll_base + PLL_CONFIG_CTL_U1, cfg->config_ctl_u1);
io_write32(pll_base + PLL_USER_CTL, cfg->user_ctl);
io_write32(pll_base + PLL_USER_CTL_U, cfg->user_ctl_u);

/* ConfigPLL: program L value and fractional value. */
io_mask32(pll_base + PLL_L_VAL, cfg->l_val, PLL_L_VAL_L_MASK);
io_write32(pll_base + PLL_ALPHA_VAL, cfg->alpha_val);

/* Select fractional format and program the pre-/post-div ratios. */
user_val = io_read32(pll_base + PLL_USER_CTL);
if (cfg->frac_mode_mn)
user_val |= PLL_USER_CTL_FRAC_FORMAT_SEL;
else
user_val &= ~PLL_USER_CTL_FRAC_FORMAT_SEL;

user_val &= ~(PLL_USER_CTL_PRE_DIV_MASK |
PLL_USER_CTL_POST_DIV_ODD_MASK |
PLL_USER_CTL_POST_DIV_EVEN_MASK);
if (cfg->pre_div >= 1 && cfg->pre_div <= 8)
user_val |= SHIFT_U32(cfg->pre_div - 1,
PLL_USER_CTL_PRE_DIV_SHIFT) &
PLL_USER_CTL_PRE_DIV_MASK;
io_write32(pll_base + PLL_USER_CTL, user_val);

/* Always use fine-grained lock detection. */
io_setbits32(pll_base + PLL_USER_CTL_U, PLL_USER_CTL_U_FINE_LOCK_DET);

/* SetCalConfig: program the calibration L value. */
io_mask32(pll_base + PLL_L_VAL,
SHIFT_U32(cfg->cal_l_val, PLL_L_VAL_CAL_L_SHIFT),
PLL_L_VAL_CAL_L_MASK);

/* Enable: select RUN opmode and take the PLL out of reset. */
io_write32(pll_base + PLL_OPMODE, PLL_OPMODE_RUN);
io_setbits32(pll_base + PLL_MODE, PLL_MODE_RESET_N);

/* Wait for the PLL to lock. */
REG_POLL_TIMEOUT(pll_base + PLL_MODE, 10 * 1000, 10, &ret, pll_locked);
if (ret < 0)
return TEE_ERROR_TIMEOUT;

/* Enable PLL outputs and the main output. */
io_setbits32(pll_base + PLL_MODE, PLL_MODE_OUTCTRL);
io_setbits32(pll_base + PLL_USER_CTL, PLL_USER_CTL_PLLOUT_MAIN_EN);

return TEE_SUCCESS;
}

TEE_Result qcom_clock_set_rate(vaddr_t cfg_rcgr, vaddr_t cmd_rcgr,
uint32_t cfg_value)
{
Expand All @@ -53,8 +158,11 @@ TEE_Result qcom_clock_enable(enum qcom_clk_group group)
{
switch (group) {
case QCOM_CLKS_TURING:
case QCOM_CLKS_TURING1:
case QCOM_CLKS_LPASS:
case QCOM_CLKS_WPSS:
case QCOM_CLKS_GPDSP0:
case QCOM_CLKS_GPDSP1:
return qcom_clock_enable_pas(group);
default:
EMSG("Unsupported clock group %d\n", group);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

#include <drivers/clk.h>
#include <drivers/clk_qcom.h>

#ifdef CFG_QCOM_PAS_PTA
#include <io.h>
#include <malloc.h>
#include <mm/core_memprot.h>
Expand Down Expand Up @@ -122,6 +120,18 @@ static int lpass_gdsc_enable(void)
return qcom_clock_enable_cbc(gdsc_base + TOP_CC_LPI_Q6_AXIM_HS_CLK);
}

TEE_Result qcom_clock_enable_pas_processor(enum qcom_clk_group group __unused)
{
/* The DSP core is released entirely within the PTA fw_start path. */
return TEE_SUCCESS;
}

TEE_Result qcom_clock_pas_reset(enum qcom_clk_group group __unused)
{
/* The PTA fw_start path brings the DSP up from a known state. */
return TEE_SUCCESS;
}

TEE_Result qcom_clock_enable_pas(enum qcom_clk_group group)
{
struct io_pa_va base = { .pa = GCC_BASE };
Expand Down Expand Up @@ -167,10 +177,3 @@ TEE_Result qcom_clock_enable_pas(enum qcom_clk_group group)
EMSG("Timeout trying to enable clock group %d\n", group);
return TEE_ERROR_TIMEOUT;
}

#else
TEE_Result qcom_clock_enable_pas(enum qcom_clk_group group __unused)
{
return TEE_ERROR_NOT_SUPPORTED;
}
#endif /* ! CFG_QCOM_PAS_PTA */
Loading