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:
Madhukar Pappireddy 2024-10-09 16:11:09 +02:00 committed by TrustedFirmware Code Review
commit 01c80c1956
11 changed files with 554 additions and 20 deletions

View file

@ -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)

View 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 */

View file

@ -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 */

View 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) {
}
}
}

View file

@ -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) {
}
}

View file

@ -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 \

View file

@ -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;

View file

@ -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 = {

View file

@ -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;
}

View file

@ -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 */

View file

@ -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 */