mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-24 05:54:08 +00:00
Merge changes from topic "nxp-clk/add_ddr_clk" into integration
* changes: fix(nxp-clk): function parameter should not be modified feat(nxp-clk): enable the DDR clock feat(nxp-clk): add objects needed for DDR clock feat(nxp-clk): setup the DDR PLL feat(nxp-clk): add MC_ME utilities feat(nxp-clk): add partition reset utilities feat(nxp-clk): add partitions objects
This commit is contained in:
commit
01c80c1956
11 changed files with 554 additions and 20 deletions
|
@ -13,6 +13,11 @@
|
|||
#define ARM_DFS_BASE_ADDR (0x40054000UL)
|
||||
#define CGM0_BASE_ADDR (0x40030000UL)
|
||||
#define CGM1_BASE_ADDR (0x40034000UL)
|
||||
#define DDRPLL_BASE_ADDR (0x40044000UL)
|
||||
#define MC_ME_BASE_ADDR (0x40088000UL)
|
||||
#define MC_RGM_BASE_ADDR (0x40078000UL)
|
||||
#define RDC_BASE_ADDR (0x40080000UL)
|
||||
#define MC_CGM5_BASE_ADDR (0x40068000UL)
|
||||
|
||||
/* FXOSC */
|
||||
#define FXOSC_CTRL(FXOSC) ((FXOSC) + 0x0UL)
|
||||
|
|
16
drivers/nxp/clk/s32cc/include/s32cc-mc-me.h
Normal file
16
drivers/nxp/clk/s32cc/include/s32cc-mc-me.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
/*
|
||||
* Copyright 2020-2021, 2023-2024 NXP
|
||||
*/
|
||||
#ifndef S32CC_MC_ME_H
|
||||
#define S32CC_MC_ME_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
int mc_me_enable_partition(uintptr_t mc_me, uintptr_t mc_rgm, uintptr_t rdc,
|
||||
uint32_t part);
|
||||
void mc_me_enable_part_cofb(uintptr_t mc_me, uint32_t partition_n, uint32_t block,
|
||||
bool check_status);
|
||||
|
||||
#endif /* S32CC_MC_ME_H */
|
|
@ -8,5 +8,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
void mc_rgm_periph_reset(uintptr_t rgm, uint32_t part, uint32_t value);
|
||||
void mc_rgm_release_part(uintptr_t rgm, uint32_t part);
|
||||
void mc_rgm_wait_part_deassert(uintptr_t rgm, uint32_t part);
|
||||
|
||||
#endif /* MC_RGM_H */
|
||||
|
|
173
drivers/nxp/clk/s32cc/mc_me.c
Normal file
173
drivers/nxp/clk/s32cc/mc_me.c
Normal file
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* Copyright 2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/utils_def.h>
|
||||
#include <s32cc-mc-me.h>
|
||||
#include <s32cc-mc-rgm.h>
|
||||
|
||||
#define MC_ME_MAX_PARTITIONS (4U)
|
||||
|
||||
#define MC_ME_CTL_KEY(MC_ME) ((MC_ME) + 0x0UL)
|
||||
#define MC_ME_CTL_KEY_KEY (0x5AF0U)
|
||||
#define MC_ME_CTL_KEY_INVERTEDKEY (0xA50FU)
|
||||
|
||||
#define MC_ME_PRTN_N(MC_ME, PART) ((MC_ME) + 0x100UL + ((PART) * 0x200UL))
|
||||
#define MC_ME_PRTN_N_PCONF(MC_ME, PART) (MC_ME_PRTN_N(MC_ME, PART))
|
||||
#define MC_ME_PRTN_N_PCE BIT_32(0)
|
||||
#define MC_ME_PRTN_N_OSSE BIT_32(2)
|
||||
#define MC_ME_PRTN_N_PUPD(MC_ME, PART) (MC_ME_PRTN_N(MC_ME, PART) + 0x4UL)
|
||||
#define MC_ME_PRTN_N_PCUD BIT_32(0)
|
||||
#define MC_ME_PRTN_N_OSSUD BIT_32(2)
|
||||
#define MC_ME_PRTN_N_STAT(MC_ME, PART) (MC_ME_PRTN_N(MC_ME, PART) + 0x8UL)
|
||||
#define MC_ME_PRTN_N_PCS BIT_32(0)
|
||||
#define MC_ME_PRTN_N_COFB0_STAT(MC_ME, PART) \
|
||||
(MC_ME_PRTN_N(MC_ME, PART) + 0x10UL)
|
||||
#define MC_ME_PRTN_N_COFB0_CLKEN(MC_ME, PART) \
|
||||
(MC_ME_PRTN_N(MC_ME, PART) + 0x30UL)
|
||||
#define MC_ME_PRTN_N_REQ(PART) BIT_32(PART)
|
||||
|
||||
#define RDC_RD_CTRL(RDC, PART) ((RDC) + ((PART) * 0x4UL))
|
||||
#define RDC_CTRL_UNLOCK BIT_32(31)
|
||||
#define RDC_RD_INTERCONNECT_DISABLE BIT_32(3)
|
||||
|
||||
#define RDC_RD_N_STATUS(RDC, PART) ((RDC) + ((PART) * 0x4UL) + 0x80UL)
|
||||
#define RDC_RD_INTERCONNECT_DISABLE_STAT \
|
||||
BIT_32(4)
|
||||
|
||||
static bool is_interconnect_disabled(uintptr_t rdc, uint32_t part)
|
||||
{
|
||||
return ((mmio_read_32(RDC_RD_N_STATUS(rdc, part)) &
|
||||
RDC_RD_INTERCONNECT_DISABLE_STAT) != 0U);
|
||||
}
|
||||
|
||||
static void enable_interconnect(uintptr_t rdc, uint32_t part)
|
||||
{
|
||||
/* Unlock RDC register write */
|
||||
mmio_setbits_32(RDC_RD_CTRL(rdc, part), RDC_CTRL_UNLOCK);
|
||||
|
||||
/* Clear corresponding RDC_RD_INTERCONNECT bit */
|
||||
mmio_clrbits_32(RDC_RD_CTRL(rdc, part), RDC_RD_INTERCONNECT_DISABLE);
|
||||
|
||||
/* Wait until the interface gets enabled */
|
||||
while (is_interconnect_disabled(rdc, part)) {
|
||||
}
|
||||
|
||||
/* Lock RDC register write */
|
||||
mmio_clrbits_32(RDC_RD_CTRL(rdc, part), RDC_CTRL_UNLOCK);
|
||||
}
|
||||
|
||||
static int mc_me_check_partition_nb_valid(uint32_t part)
|
||||
{
|
||||
if (part >= MC_ME_MAX_PARTITIONS) {
|
||||
ERROR("Invalid partition %" PRIu32 "\n", part);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void part_pconf_write_pce(uintptr_t mc_me, uint32_t pce_bit,
|
||||
uint32_t part)
|
||||
{
|
||||
mmio_clrsetbits_32(MC_ME_PRTN_N_PCONF(mc_me, part), MC_ME_PRTN_N_PCE,
|
||||
pce_bit & MC_ME_PRTN_N_PCE);
|
||||
}
|
||||
|
||||
static void mc_me_apply_hw_changes(uintptr_t mc_me)
|
||||
{
|
||||
mmio_write_32(MC_ME_CTL_KEY(mc_me), MC_ME_CTL_KEY_KEY);
|
||||
mmio_write_32(MC_ME_CTL_KEY(mc_me), MC_ME_CTL_KEY_INVERTEDKEY);
|
||||
}
|
||||
|
||||
static void part_pupd_update_and_wait(uintptr_t mc_me, uint32_t part,
|
||||
uint32_t mask)
|
||||
{
|
||||
uint32_t pconf, stat;
|
||||
|
||||
mmio_setbits_32(MC_ME_PRTN_N_PUPD(mc_me, part), mask);
|
||||
|
||||
mc_me_apply_hw_changes(mc_me);
|
||||
|
||||
/* wait for the updates to apply */
|
||||
pconf = mmio_read_32(MC_ME_PRTN_N_PCONF(mc_me, part));
|
||||
do {
|
||||
stat = mmio_read_32(MC_ME_PRTN_N_STAT(mc_me, part));
|
||||
} while ((stat & mask) != (pconf & mask));
|
||||
}
|
||||
|
||||
static void part_pconf_write_osse(uintptr_t mc_me, uint32_t osse_bit,
|
||||
uint32_t part)
|
||||
{
|
||||
mmio_clrsetbits_32(MC_ME_PRTN_N_PCONF(mc_me, part), MC_ME_PRTN_N_OSSE,
|
||||
(osse_bit & MC_ME_PRTN_N_OSSE));
|
||||
}
|
||||
|
||||
int mc_me_enable_partition(uintptr_t mc_me, uintptr_t mc_rgm, uintptr_t rdc,
|
||||
uint32_t part)
|
||||
{
|
||||
uint32_t part_stat;
|
||||
int ret;
|
||||
|
||||
/* Partition 0 is already enabled by BootROM */
|
||||
if (part == 0U) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = mc_me_check_partition_nb_valid(part);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enable a partition only if it's disabled */
|
||||
part_stat = mmio_read_32(MC_ME_PRTN_N_STAT(mc_me, part));
|
||||
if ((MC_ME_PRTN_N_PCS & part_stat) != 0U) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
part_pconf_write_pce(mc_me, MC_ME_PRTN_N_PCE, part);
|
||||
part_pupd_update_and_wait(mc_me, part, MC_ME_PRTN_N_PCUD);
|
||||
|
||||
enable_interconnect(rdc, part);
|
||||
|
||||
/* Release partition reset */
|
||||
mc_rgm_release_part(mc_rgm, part);
|
||||
|
||||
/* Clear OSSE bit */
|
||||
part_pconf_write_osse(mc_me, 0, part);
|
||||
|
||||
part_pupd_update_and_wait(mc_me, part, MC_ME_PRTN_N_OSSUD);
|
||||
|
||||
mc_rgm_wait_part_deassert(mc_rgm, part);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mc_me_enable_part_cofb(uintptr_t mc_me, uint32_t partition_n, uint32_t block,
|
||||
bool check_status)
|
||||
{
|
||||
uint32_t block_mask = MC_ME_PRTN_N_REQ(block);
|
||||
uintptr_t cofb_stat_addr;
|
||||
|
||||
mmio_setbits_32(MC_ME_PRTN_N_COFB0_CLKEN(mc_me, partition_n),
|
||||
block_mask);
|
||||
|
||||
mmio_setbits_32(MC_ME_PRTN_N_PCONF(mc_me, partition_n),
|
||||
MC_ME_PRTN_N_PCE);
|
||||
|
||||
part_pupd_update_and_wait(mc_me, partition_n, MC_ME_PRTN_N_PCUD);
|
||||
|
||||
cofb_stat_addr = MC_ME_PRTN_N_COFB0_STAT(mc_me, partition_n);
|
||||
if (check_status) {
|
||||
while ((mmio_read_32(cofb_stat_addr) & block_mask) == 0U) {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,7 +7,10 @@
|
|||
#include <lib/utils_def.h>
|
||||
#include <s32cc-mc-rgm.h>
|
||||
|
||||
#define MC_RGM_PRST(MC_RGM, PER) ((MC_RGM) + 0x40UL + ((PER) * 0x8UL))
|
||||
#define MC_RGM_PRST(RGM, PER) ((RGM) + 0x40UL + ((PER) * 0x8UL))
|
||||
#define MC_RGM_PRST_PERIPH_N_RST(PER) BIT_32(PER)
|
||||
#define MC_RGM_PSTAT(RGM, PER) ((RGM) + 0x140UL + ((PER) * 0x8UL))
|
||||
#define MC_RGM_PSTAT_PERIPH(PER) BIT_32(PER)
|
||||
|
||||
/* ERR051700
|
||||
* Releasing more than one Software Resettable Domain (SRD)
|
||||
|
@ -63,3 +66,19 @@ void mc_rgm_periph_reset(uintptr_t rgm, uint32_t part, uint32_t value)
|
|||
mmio_write_32(MC_RGM_PRST(rgm, part), value);
|
||||
}
|
||||
#endif /* ERRATA_S32_051700 */
|
||||
|
||||
void mc_rgm_release_part(uintptr_t rgm, uint32_t part)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
reg = mmio_read_32(MC_RGM_PRST(rgm, part));
|
||||
reg &= ~MC_RGM_PRST_PERIPH_N_RST(0);
|
||||
mc_rgm_periph_reset(rgm, part, reg);
|
||||
}
|
||||
|
||||
void mc_rgm_wait_part_deassert(uintptr_t rgm, uint32_t part)
|
||||
{
|
||||
while ((mmio_read_32(MC_RGM_PSTAT(rgm, part)) &
|
||||
MC_RGM_PSTAT_PERIPH(0)) != 0U) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ PLAT_INCLUDES += \
|
|||
|
||||
CLK_SOURCES := \
|
||||
${PLAT_DRIVERS_PATH}/clk/s32cc/mc_rgm.c \
|
||||
${PLAT_DRIVERS_PATH}/clk/s32cc/mc_me.c \
|
||||
${PLAT_DRIVERS_PATH}/clk/s32cc/s32cc_clk_drv.c \
|
||||
${PLAT_DRIVERS_PATH}/clk/s32cc/s32cc_clk_modules.c \
|
||||
${PLAT_DRIVERS_PATH}/clk/s32cc/s32cc_clk_utils.c \
|
||||
|
|
|
@ -4,15 +4,14 @@
|
|||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <errno.h>
|
||||
|
||||
#include <s32cc-clk-regs.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/clk.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <s32cc-clk-ids.h>
|
||||
#include <s32cc-clk-modules.h>
|
||||
#include <s32cc-clk-regs.h>
|
||||
#include <s32cc-clk-utils.h>
|
||||
#include <s32cc-mc-me.h>
|
||||
|
||||
#define MAX_STACK_DEPTH (40U)
|
||||
|
||||
|
@ -26,6 +25,11 @@ struct s32cc_clk_drv {
|
|||
uintptr_t armdfs_base;
|
||||
uintptr_t cgm0_base;
|
||||
uintptr_t cgm1_base;
|
||||
uintptr_t cgm5_base;
|
||||
uintptr_t ddrpll_base;
|
||||
uintptr_t mc_me;
|
||||
uintptr_t mc_rgm;
|
||||
uintptr_t rdc;
|
||||
};
|
||||
|
||||
static int update_stack_depth(unsigned int *depth)
|
||||
|
@ -47,6 +51,11 @@ static struct s32cc_clk_drv *get_drv(void)
|
|||
.armdfs_base = ARM_DFS_BASE_ADDR,
|
||||
.cgm0_base = CGM0_BASE_ADDR,
|
||||
.cgm1_base = CGM1_BASE_ADDR,
|
||||
.cgm5_base = MC_CGM5_BASE_ADDR,
|
||||
.ddrpll_base = DDRPLL_BASE_ADDR,
|
||||
.mc_me = MC_ME_BASE_ADDR,
|
||||
.mc_rgm = MC_RGM_BASE_ADDR,
|
||||
.rdc = RDC_BASE_ADDR,
|
||||
};
|
||||
|
||||
return &driver;
|
||||
|
@ -86,6 +95,9 @@ static int get_base_addr(enum s32cc_clk_source id, const struct s32cc_clk_drv *d
|
|||
case S32CC_PERIPH_PLL:
|
||||
*base = drv->periphpll_base;
|
||||
break;
|
||||
case S32CC_DDR_PLL:
|
||||
*base = drv->ddrpll_base;
|
||||
break;
|
||||
case S32CC_ARM_DFS:
|
||||
*base = drv->armdfs_base;
|
||||
break;
|
||||
|
@ -95,6 +107,9 @@ static int get_base_addr(enum s32cc_clk_source id, const struct s32cc_clk_drv *d
|
|||
case S32CC_CGM1:
|
||||
*base = drv->cgm1_base;
|
||||
break;
|
||||
case S32CC_CGM5:
|
||||
*base = drv->cgm5_base;
|
||||
break;
|
||||
case S32CC_FIRC:
|
||||
break;
|
||||
case S32CC_SIRC:
|
||||
|
@ -140,9 +155,10 @@ static int enable_osc(struct s32cc_clk_obj *module,
|
|||
unsigned int depth)
|
||||
{
|
||||
const struct s32cc_osc *osc = s32cc_obj2osc(module);
|
||||
unsigned int ldepth = depth;
|
||||
int ret = 0;
|
||||
|
||||
ret = update_stack_depth(&depth);
|
||||
ret = update_stack_depth(&ldepth);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -321,11 +337,12 @@ static int enable_pll(struct s32cc_clk_obj *module,
|
|||
const struct s32cc_pll *pll = s32cc_obj2pll(module);
|
||||
const struct s32cc_clkmux *mux;
|
||||
uintptr_t pll_addr = UL(0x0);
|
||||
unsigned int ldepth = depth;
|
||||
unsigned long sclk_freq;
|
||||
uint32_t sclk_id;
|
||||
int ret;
|
||||
|
||||
ret = update_stack_depth(&depth);
|
||||
ret = update_stack_depth(&ldepth);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -421,11 +438,12 @@ static int enable_pll_div(struct s32cc_clk_obj *module,
|
|||
{
|
||||
const struct s32cc_pll_out_div *pdiv = s32cc_obj2plldiv(module);
|
||||
uintptr_t pll_addr = 0x0ULL;
|
||||
unsigned int ldepth = depth;
|
||||
const struct s32cc_pll *pll;
|
||||
uint32_t dc;
|
||||
int ret;
|
||||
|
||||
ret = update_stack_depth(&depth);
|
||||
ret = update_stack_depth(&ldepth);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -562,10 +580,11 @@ static int enable_mux(struct s32cc_clk_obj *module,
|
|||
unsigned int depth)
|
||||
{
|
||||
const struct s32cc_clkmux *mux = s32cc_obj2clkmux(module);
|
||||
unsigned int ldepth = depth;
|
||||
const struct s32cc_clk *clk;
|
||||
int ret = 0;
|
||||
|
||||
ret = update_stack_depth(&depth);
|
||||
ret = update_stack_depth(&ldepth);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -585,6 +604,7 @@ static int enable_mux(struct s32cc_clk_obj *module,
|
|||
/* PLL mux will be enabled by PLL setup */
|
||||
case S32CC_ARM_PLL:
|
||||
case S32CC_PERIPH_PLL:
|
||||
case S32CC_DDR_PLL:
|
||||
break;
|
||||
case S32CC_CGM1:
|
||||
ret = enable_cgm_mux(mux, drv);
|
||||
|
@ -592,6 +612,9 @@ static int enable_mux(struct s32cc_clk_obj *module,
|
|||
case S32CC_CGM0:
|
||||
ret = enable_cgm_mux(mux, drv);
|
||||
break;
|
||||
case S32CC_CGM5:
|
||||
ret = enable_cgm_mux(mux, drv);
|
||||
break;
|
||||
default:
|
||||
ERROR("Unknown mux parent type: %d\n", mux->module);
|
||||
ret = -EINVAL;
|
||||
|
@ -616,9 +639,10 @@ static int enable_dfs(struct s32cc_clk_obj *module,
|
|||
const struct s32cc_clk_drv *drv,
|
||||
unsigned int depth)
|
||||
{
|
||||
unsigned int ldepth = depth;
|
||||
int ret = 0;
|
||||
|
||||
ret = update_stack_depth(&depth);
|
||||
ret = update_stack_depth(&ldepth);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -782,13 +806,14 @@ static int enable_dfs_div(struct s32cc_clk_obj *module,
|
|||
unsigned int depth)
|
||||
{
|
||||
const struct s32cc_dfs_div *dfs_div = s32cc_obj2dfsdiv(module);
|
||||
unsigned int ldepth = depth;
|
||||
const struct s32cc_pll *pll;
|
||||
const struct s32cc_dfs *dfs;
|
||||
uintptr_t dfs_addr = 0UL;
|
||||
uint32_t mfi, mfn;
|
||||
int ret = 0;
|
||||
|
||||
ret = update_stack_depth(&depth);
|
||||
ret = update_stack_depth(&ldepth);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -821,6 +846,86 @@ typedef int (*enable_clk_t)(struct s32cc_clk_obj *module,
|
|||
const struct s32cc_clk_drv *drv,
|
||||
unsigned int depth);
|
||||
|
||||
static int enable_part(struct s32cc_clk_obj *module,
|
||||
const struct s32cc_clk_drv *drv,
|
||||
unsigned int depth)
|
||||
{
|
||||
const struct s32cc_part *part = s32cc_obj2part(module);
|
||||
uint32_t part_no = part->partition_id;
|
||||
|
||||
if ((drv->mc_me == 0UL) || (drv->mc_rgm == 0UL) || (drv->rdc == 0UL)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return mc_me_enable_partition(drv->mc_me, drv->mc_rgm, drv->rdc, part_no);
|
||||
}
|
||||
|
||||
static int enable_part_block(struct s32cc_clk_obj *module,
|
||||
const struct s32cc_clk_drv *drv,
|
||||
unsigned int depth)
|
||||
{
|
||||
const struct s32cc_part_block *block = s32cc_obj2partblock(module);
|
||||
const struct s32cc_part *part = block->part;
|
||||
uint32_t part_no = part->partition_id;
|
||||
unsigned int ldepth = depth;
|
||||
uint32_t cofb;
|
||||
int ret;
|
||||
|
||||
ret = update_stack_depth(&ldepth);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((block->block >= s32cc_part_block0) &&
|
||||
(block->block <= s32cc_part_block15)) {
|
||||
cofb = (uint32_t)block->block - (uint32_t)s32cc_part_block0;
|
||||
mc_me_enable_part_cofb(drv->mc_me, part_no, cofb, block->status);
|
||||
} else {
|
||||
ERROR("Unknown partition block type: %d\n", block->block);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct s32cc_clk_obj *
|
||||
get_part_block_parent(const struct s32cc_clk_obj *module)
|
||||
{
|
||||
const struct s32cc_part_block *block = s32cc_obj2partblock(module);
|
||||
|
||||
return &block->part->desc;
|
||||
}
|
||||
|
||||
static int enable_module_with_refcount(struct s32cc_clk_obj *module,
|
||||
const struct s32cc_clk_drv *drv,
|
||||
unsigned int depth);
|
||||
|
||||
static int enable_part_block_link(struct s32cc_clk_obj *module,
|
||||
const struct s32cc_clk_drv *drv,
|
||||
unsigned int depth)
|
||||
{
|
||||
const struct s32cc_part_block_link *link = s32cc_obj2partblocklink(module);
|
||||
struct s32cc_part_block *block = link->block;
|
||||
unsigned int ldepth = depth;
|
||||
int ret;
|
||||
|
||||
ret = update_stack_depth(&ldepth);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Move the enablement algorithm to partition tree */
|
||||
return enable_module_with_refcount(&block->desc, drv, ldepth);
|
||||
}
|
||||
|
||||
static struct s32cc_clk_obj *
|
||||
get_part_block_link_parent(const struct s32cc_clk_obj *module)
|
||||
{
|
||||
const struct s32cc_part_block_link *link = s32cc_obj2partblocklink(module);
|
||||
|
||||
return link->parent;
|
||||
}
|
||||
|
||||
static int no_enable(struct s32cc_clk_obj *module,
|
||||
const struct s32cc_clk_drv *drv,
|
||||
unsigned int depth)
|
||||
|
@ -832,24 +937,25 @@ static int exec_cb_with_refcount(enable_clk_t en_cb, struct s32cc_clk_obj *mod,
|
|||
const struct s32cc_clk_drv *drv, bool leaf_node,
|
||||
unsigned int depth)
|
||||
{
|
||||
unsigned int ldepth = depth;
|
||||
int ret = 0;
|
||||
|
||||
if (mod == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = update_stack_depth(&depth);
|
||||
ret = update_stack_depth(&ldepth);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Refcount will be updated as part of the recursivity */
|
||||
if (leaf_node) {
|
||||
return en_cb(mod, drv, depth);
|
||||
return en_cb(mod, drv, ldepth);
|
||||
}
|
||||
|
||||
if (mod->refcount == 0U) {
|
||||
ret = en_cb(mod, drv, depth);
|
||||
ret = en_cb(mod, drv, ldepth);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
|
@ -866,7 +972,7 @@ static int enable_module(struct s32cc_clk_obj *module,
|
|||
unsigned int depth)
|
||||
{
|
||||
struct s32cc_clk_obj *parent = get_module_parent(module);
|
||||
static const enable_clk_t enable_clbs[8] = {
|
||||
static const enable_clk_t enable_clbs[12] = {
|
||||
[s32cc_clk_t] = no_enable,
|
||||
[s32cc_osc_t] = enable_osc,
|
||||
[s32cc_pll_t] = enable_pll,
|
||||
|
@ -875,11 +981,15 @@ static int enable_module(struct s32cc_clk_obj *module,
|
|||
[s32cc_shared_clkmux_t] = enable_mux,
|
||||
[s32cc_dfs_t] = enable_dfs,
|
||||
[s32cc_dfs_div_t] = enable_dfs_div,
|
||||
[s32cc_part_t] = enable_part,
|
||||
[s32cc_part_block_t] = enable_part_block,
|
||||
[s32cc_part_block_link_t] = enable_part_block_link,
|
||||
};
|
||||
unsigned int ldepth = depth;
|
||||
uint32_t index;
|
||||
int ret = 0;
|
||||
|
||||
ret = update_stack_depth(&depth);
|
||||
ret = update_stack_depth(&ldepth);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -904,13 +1014,13 @@ static int enable_module(struct s32cc_clk_obj *module,
|
|||
parent = get_module_parent(module);
|
||||
|
||||
ret = exec_cb_with_refcount(enable_module, parent, drv,
|
||||
false, depth);
|
||||
false, ldepth);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = exec_cb_with_refcount(enable_clbs[index], module, drv,
|
||||
true, depth);
|
||||
true, ldepth);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -1238,7 +1348,7 @@ typedef struct s32cc_clk_obj *(*get_parent_clb_t)(const struct s32cc_clk_obj *cl
|
|||
|
||||
static struct s32cc_clk_obj *get_module_parent(const struct s32cc_clk_obj *module)
|
||||
{
|
||||
static const get_parent_clb_t parents_clbs[8] = {
|
||||
static const get_parent_clb_t parents_clbs[12] = {
|
||||
[s32cc_clk_t] = get_clk_parent,
|
||||
[s32cc_osc_t] = get_no_parent,
|
||||
[s32cc_pll_t] = get_pll_parent,
|
||||
|
@ -1247,6 +1357,9 @@ static struct s32cc_clk_obj *get_module_parent(const struct s32cc_clk_obj *modul
|
|||
[s32cc_shared_clkmux_t] = get_mux_parent,
|
||||
[s32cc_dfs_t] = get_dfs_parent,
|
||||
[s32cc_dfs_div_t] = get_dfs_div_parent,
|
||||
[s32cc_part_t] = get_no_parent,
|
||||
[s32cc_part_block_t] = get_part_block_parent,
|
||||
[s32cc_part_block_link_t] = get_part_block_link_parent,
|
||||
};
|
||||
uint32_t index;
|
||||
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
#define S32CC_A53_MIN_FREQ (48UL * MHZ)
|
||||
#define S32CC_A53_MAX_FREQ (1000UL * MHZ)
|
||||
|
||||
/* Partitions */
|
||||
static struct s32cc_part part0 = S32CC_PART(0);
|
||||
|
||||
/* Oscillators */
|
||||
static struct s32cc_osc fxosc =
|
||||
S32CC_OSC_INIT(S32CC_FXOSC);
|
||||
|
@ -139,7 +142,40 @@ static struct s32cc_pll_out_div periph_pll_phi3_div =
|
|||
static struct s32cc_clk periph_pll_phi3_clk =
|
||||
S32CC_FREQ_MODULE_CLK(periph_pll_phi3_div, 0, 133333333);
|
||||
|
||||
static struct s32cc_clk *s32cc_hw_clk_list[22] = {
|
||||
/* DDR PLL */
|
||||
static struct s32cc_clkmux ddr_pll_mux =
|
||||
S32CC_CLKMUX_INIT(S32CC_DDR_PLL, 0, 2,
|
||||
S32CC_CLK_FIRC,
|
||||
S32CC_CLK_FXOSC, 0, 0, 0);
|
||||
static struct s32cc_clk ddr_pll_mux_clk =
|
||||
S32CC_MODULE_CLK(ddr_pll_mux);
|
||||
static struct s32cc_pll ddrpll =
|
||||
S32CC_PLL_INIT(ddr_pll_mux_clk, S32CC_DDR_PLL, 1);
|
||||
static struct s32cc_clk ddr_pll_vco_clk =
|
||||
S32CC_FREQ_MODULE_CLK(ddrpll, 1300 * MHZ, 1600 * MHZ);
|
||||
|
||||
static struct s32cc_pll_out_div ddr_pll_phi0_div =
|
||||
S32CC_PLL_OUT_DIV_INIT(ddrpll, 0);
|
||||
static struct s32cc_clk ddr_pll_phi0_clk =
|
||||
S32CC_FREQ_MODULE_CLK(ddr_pll_phi0_div, 0, 800 * MHZ);
|
||||
|
||||
/* MC_CGM5 */
|
||||
static struct s32cc_clkmux cgm5_mux0 =
|
||||
S32CC_SHARED_CLKMUX_INIT(S32CC_CGM5, 0, 2,
|
||||
S32CC_CLK_FIRC,
|
||||
S32CC_CLK_DDR_PLL_PHI0,
|
||||
0, 0, 0);
|
||||
static struct s32cc_clk cgm5_mux0_clk = S32CC_MODULE_CLK(cgm5_mux0);
|
||||
|
||||
/* DDR clock */
|
||||
static struct s32cc_part_block part0_block1 =
|
||||
S32CC_PART_BLOCK(&part0, s32cc_part_block1);
|
||||
static struct s32cc_part_block_link ddr_block_link =
|
||||
S32CC_PART_BLOCK_LINK(cgm5_mux0_clk, &part0_block1);
|
||||
static struct s32cc_clk ddr_clk =
|
||||
S32CC_FREQ_MODULE_CLK(ddr_block_link, 0, 800 * MHZ);
|
||||
|
||||
static struct s32cc_clk *s32cc_hw_clk_list[37] = {
|
||||
/* Oscillators */
|
||||
[S32CC_CLK_ID(S32CC_CLK_FIRC)] = &firc_clk,
|
||||
[S32CC_CLK_ID(S32CC_CLK_SIRC)] = &sirc_clk,
|
||||
|
@ -150,6 +186,8 @@ static struct s32cc_clk *s32cc_hw_clk_list[22] = {
|
|||
[S32CC_CLK_ID(S32CC_CLK_ARM_PLL_DFS1)] = &arm_dfs1_clk,
|
||||
/* PERIPH PLL */
|
||||
[S32CC_CLK_ID(S32CC_CLK_PERIPH_PLL_PHI3)] = &periph_pll_phi3_clk,
|
||||
/* DDR PLL */
|
||||
[S32CC_CLK_ID(S32CC_CLK_DDR_PLL_PHI0)] = &ddr_pll_phi0_clk,
|
||||
};
|
||||
|
||||
static struct s32cc_clk_array s32cc_hw_clocks = {
|
||||
|
@ -158,7 +196,7 @@ static struct s32cc_clk_array s32cc_hw_clocks = {
|
|||
.n_clks = ARRAY_SIZE(s32cc_hw_clk_list),
|
||||
};
|
||||
|
||||
static struct s32cc_clk *s32cc_arch_clk_list[18] = {
|
||||
static struct s32cc_clk *s32cc_arch_clk_list[22] = {
|
||||
/* ARM PLL */
|
||||
[S32CC_CLK_ID(S32CC_CLK_ARM_PLL_MUX)] = &arm_pll_mux_clk,
|
||||
[S32CC_CLK_ID(S32CC_CLK_ARM_PLL_VCO)] = &arm_pll_vco_clk,
|
||||
|
@ -184,6 +222,13 @@ static struct s32cc_clk *s32cc_arch_clk_list[18] = {
|
|||
/* Linflex */
|
||||
[S32CC_CLK_ID(S32CC_CLK_LINFLEX)] = &linflex_clk,
|
||||
[S32CC_CLK_ID(S32CC_CLK_LINFLEX_BAUD)] = &linflex_baud_clk,
|
||||
/* DDR PLL */
|
||||
[S32CC_CLK_ID(S32CC_CLK_DDR_PLL_MUX)] = &ddr_pll_mux_clk,
|
||||
[S32CC_CLK_ID(S32CC_CLK_DDR_PLL_VCO)] = &ddr_pll_vco_clk,
|
||||
/* MC_CGM5 */
|
||||
[S32CC_CLK_ID(S32CC_CLK_MC_CGM5_MUX0)] = &cgm5_mux0_clk,
|
||||
/* DDR */
|
||||
[S32CC_CLK_ID(S32CC_CLK_DDR)] = &ddr_clk,
|
||||
};
|
||||
|
||||
static struct s32cc_clk_array s32cc_arch_clocks = {
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#define S32CC_XBAR_2X_FREQ (800U * MHZ)
|
||||
#define S32CC_PERIPH_PLL_VCO_FREQ (2U * GHZ)
|
||||
#define S32CC_PERIPH_PLL_PHI3_FREQ UART_CLOCK_HZ
|
||||
#define S32CC_DDR_PLL_VCO_FREQ (1600U * MHZ)
|
||||
#define S32CC_DDR_PLL_PHI0_FREQ (800U * MHZ)
|
||||
|
||||
static int setup_fxosc(void)
|
||||
{
|
||||
|
@ -139,6 +141,45 @@ static int enable_uart_clk(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int setup_ddr_pll(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = clk_set_parent(S32CC_CLK_DDR_PLL_MUX, S32CC_CLK_FXOSC);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_set_rate(S32CC_CLK_DDR_PLL_VCO, S32CC_DDR_PLL_VCO_FREQ, NULL);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_set_rate(S32CC_CLK_DDR_PLL_PHI0, S32CC_DDR_PLL_PHI0_FREQ, NULL);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int enable_ddr_clk(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = clk_set_parent(S32CC_CLK_MC_CGM5_MUX0, S32CC_CLK_DDR_PLL_PHI0);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_enable(S32CC_CLK_DDR);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int s32cc_init_early_clks(void)
|
||||
{
|
||||
int ret;
|
||||
|
@ -175,5 +216,15 @@ int s32cc_init_early_clks(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = setup_ddr_pll();
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = enable_ddr_clk();
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -95,4 +95,12 @@
|
|||
#define S32CC_CLK_LINFLEX_BAUD S32CC_ARCH_CLK(16)
|
||||
#define S32CC_CLK_LINFLEX S32CC_ARCH_CLK(17)
|
||||
|
||||
/* DDR PLL */
|
||||
#define S32CC_CLK_DDR_PLL_MUX S32CC_ARCH_CLK(18)
|
||||
#define S32CC_CLK_DDR_PLL_VCO S32CC_ARCH_CLK(19)
|
||||
|
||||
/* DDR clock */
|
||||
#define S32CC_CLK_MC_CGM5_MUX0 S32CC_ARCH_CLK(20)
|
||||
#define S32CC_CLK_DDR S32CC_ARCH_CLK(21)
|
||||
|
||||
#endif /* S32CC_CLK_IDS_H */
|
||||
|
|
|
@ -22,6 +22,9 @@ enum s32cc_clkm_type {
|
|||
s32cc_clkmux_t,
|
||||
s32cc_shared_clkmux_t,
|
||||
s32cc_fixed_div_t,
|
||||
s32cc_part_t,
|
||||
s32cc_part_block_t,
|
||||
s32cc_part_block_link_t,
|
||||
};
|
||||
|
||||
enum s32cc_clk_source {
|
||||
|
@ -33,6 +36,8 @@ enum s32cc_clk_source {
|
|||
S32CC_PERIPH_PLL,
|
||||
S32CC_CGM0,
|
||||
S32CC_CGM1,
|
||||
S32CC_DDR_PLL,
|
||||
S32CC_CGM5,
|
||||
};
|
||||
|
||||
struct s32cc_clk_obj {
|
||||
|
@ -208,6 +213,76 @@ struct s32cc_clk_array {
|
|||
#define S32CC_CHILD_CLK(PARENT, MIN_F, MAX_F) \
|
||||
S32CC_FREQ_CLK(NULL, &(PARENT), MIN_F, MAX_F)
|
||||
|
||||
struct s32cc_part {
|
||||
struct s32cc_clk_obj desc;
|
||||
uint32_t partition_id;
|
||||
};
|
||||
|
||||
#define S32CC_PART(PART_NUM) \
|
||||
{ \
|
||||
.desc = { \
|
||||
.type = s32cc_part_t, \
|
||||
}, \
|
||||
.partition_id = (PART_NUM), \
|
||||
}
|
||||
|
||||
enum s32cc_part_block_type {
|
||||
s32cc_part_block0,
|
||||
s32cc_part_block1,
|
||||
s32cc_part_block2,
|
||||
s32cc_part_block3,
|
||||
s32cc_part_block4,
|
||||
s32cc_part_block5,
|
||||
s32cc_part_block6,
|
||||
s32cc_part_block7,
|
||||
s32cc_part_block8,
|
||||
s32cc_part_block9,
|
||||
s32cc_part_block10,
|
||||
s32cc_part_block11,
|
||||
s32cc_part_block12,
|
||||
s32cc_part_block13,
|
||||
s32cc_part_block14,
|
||||
s32cc_part_block15,
|
||||
};
|
||||
|
||||
struct s32cc_part_block {
|
||||
struct s32cc_clk_obj desc;
|
||||
struct s32cc_part *part;
|
||||
enum s32cc_part_block_type block;
|
||||
bool status;
|
||||
};
|
||||
|
||||
#define S32CC_PART_BLOCK_STATUS(PART_META, BLOCK_TYPE, STATUS) \
|
||||
{ \
|
||||
.desc = { \
|
||||
.type = s32cc_part_block_t, \
|
||||
}, \
|
||||
.part = (PART_META), \
|
||||
.block = (BLOCK_TYPE), \
|
||||
.status = (STATUS), \
|
||||
}
|
||||
|
||||
#define S32CC_PART_BLOCK(PARENT, BLOCK_TYPE) \
|
||||
S32CC_PART_BLOCK_STATUS(PARENT, BLOCK_TYPE, true)
|
||||
|
||||
#define S32CC_PART_BLOCK_NO_STATUS(PARENT, BLOCK_TYPE) \
|
||||
S32CC_PART_BLOCK_STATUS(PARENT, BLOCK_TYPE, false)
|
||||
|
||||
struct s32cc_part_block_link {
|
||||
struct s32cc_clk_obj desc;
|
||||
struct s32cc_clk_obj *parent;
|
||||
struct s32cc_part_block *block;
|
||||
};
|
||||
|
||||
#define S32CC_PART_BLOCK_LINK(PARENT, BLOCK) \
|
||||
{ \
|
||||
.desc = { \
|
||||
.type = s32cc_part_block_link_t, \
|
||||
}, \
|
||||
.parent = &(PARENT).desc, \
|
||||
.block = (BLOCK), \
|
||||
}
|
||||
|
||||
static inline struct s32cc_osc *s32cc_obj2osc(const struct s32cc_clk_obj *mod)
|
||||
{
|
||||
uintptr_t osc_addr;
|
||||
|
@ -294,4 +369,30 @@ static inline struct s32cc_dfs_div *s32cc_obj2dfsdiv(const struct s32cc_clk_obj
|
|||
return (struct s32cc_dfs_div *)dfs_div_addr;
|
||||
}
|
||||
|
||||
static inline struct s32cc_part *s32cc_obj2part(const struct s32cc_clk_obj *mod)
|
||||
{
|
||||
uintptr_t part_addr;
|
||||
|
||||
part_addr = ((uintptr_t)mod) - offsetof(struct s32cc_part, desc);
|
||||
return (struct s32cc_part *)part_addr;
|
||||
}
|
||||
|
||||
static inline struct s32cc_part_block *
|
||||
s32cc_obj2partblock(const struct s32cc_clk_obj *mod)
|
||||
{
|
||||
uintptr_t part_blk_addr;
|
||||
|
||||
part_blk_addr = ((uintptr_t)mod) - offsetof(struct s32cc_part_block, desc);
|
||||
return (struct s32cc_part_block *)part_blk_addr;
|
||||
}
|
||||
|
||||
static inline struct s32cc_part_block_link *
|
||||
s32cc_obj2partblocklink(const struct s32cc_clk_obj *mod)
|
||||
{
|
||||
uintptr_t blk_link;
|
||||
|
||||
blk_link = ((uintptr_t)mod) - offsetof(struct s32cc_part_block_link, desc);
|
||||
return (struct s32cc_part_block_link *)blk_link;
|
||||
}
|
||||
|
||||
#endif /* S32CC_CLK_MODULES_H */
|
||||
|
|
Loading…
Add table
Reference in a new issue