diff --git a/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h b/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h index 84e76f77e..e54d58130 100644 --- a/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h +++ b/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h @@ -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) diff --git a/drivers/nxp/clk/s32cc/include/s32cc-mc-me.h b/drivers/nxp/clk/s32cc/include/s32cc-mc-me.h new file mode 100644 index 000000000..8249fc55f --- /dev/null +++ b/drivers/nxp/clk/s32cc/include/s32cc-mc-me.h @@ -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 +#include + +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 */ diff --git a/drivers/nxp/clk/s32cc/include/s32cc-mc-rgm.h b/drivers/nxp/clk/s32cc/include/s32cc-mc-rgm.h index 5ff55fb6a..d6234daf8 100644 --- a/drivers/nxp/clk/s32cc/include/s32cc-mc-rgm.h +++ b/drivers/nxp/clk/s32cc/include/s32cc-mc-rgm.h @@ -8,5 +8,7 @@ #include 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 */ diff --git a/drivers/nxp/clk/s32cc/mc_me.c b/drivers/nxp/clk/s32cc/mc_me.c new file mode 100644 index 000000000..04d04253d --- /dev/null +++ b/drivers/nxp/clk/s32cc/mc_me.c @@ -0,0 +1,173 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#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) { + } + } +} diff --git a/drivers/nxp/clk/s32cc/mc_rgm.c b/drivers/nxp/clk/s32cc/mc_rgm.c index cbf402240..c66b01391 100644 --- a/drivers/nxp/clk/s32cc/mc_rgm.c +++ b/drivers/nxp/clk/s32cc/mc_rgm.c @@ -7,7 +7,10 @@ #include #include -#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) { + } +} diff --git a/drivers/nxp/clk/s32cc/s32cc_clk.mk b/drivers/nxp/clk/s32cc/s32cc_clk.mk index 2a9a37661..602179e3b 100644 --- a/drivers/nxp/clk/s32cc/s32cc_clk.mk +++ b/drivers/nxp/clk/s32cc/s32cc_clk.mk @@ -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 \ diff --git a/drivers/nxp/clk/s32cc/s32cc_clk_drv.c b/drivers/nxp/clk/s32cc/s32cc_clk_drv.c index 14b03d96c..9b5760753 100644 --- a/drivers/nxp/clk/s32cc/s32cc_clk_drv.c +++ b/drivers/nxp/clk/s32cc/s32cc_clk_drv.c @@ -4,15 +4,14 @@ * SPDX-License-Identifier: BSD-3-Clause */ #include - -#include - #include #include #include #include #include +#include #include +#include #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; diff --git a/drivers/nxp/clk/s32cc/s32cc_clk_modules.c b/drivers/nxp/clk/s32cc/s32cc_clk_modules.c index 17ded0e56..71055abc0 100644 --- a/drivers/nxp/clk/s32cc/s32cc_clk_modules.c +++ b/drivers/nxp/clk/s32cc/s32cc_clk_modules.c @@ -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 = { diff --git a/drivers/nxp/clk/s32cc/s32cc_early_clks.c b/drivers/nxp/clk/s32cc/s32cc_early_clks.c index 3f6d3d7ce..02b9df93c 100644 --- a/drivers/nxp/clk/s32cc/s32cc_early_clks.c +++ b/drivers/nxp/clk/s32cc/s32cc_early_clks.c @@ -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; } diff --git a/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h b/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h index de633ae20..d34dc22fc 100644 --- a/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h +++ b/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h @@ -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 */ diff --git a/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h b/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h index a6d58cc0a..4837f795b 100644 --- a/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h +++ b/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.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 */