Merge changes from topic "nxp-clk/add_usdhc_clock" into integration

* changes:
  feat(s32g274a): enable sdhc clock
  feat(nxp-clk): add clock modules for uSDHC
  feat(nxp-clk): get MC_CGM divider's parent
  feat(nxp-clk): get MC_CGM divider's rate
  feat(nxp-clk): set MC_CGM divider's rate
  feat(nxp-clk): enable MC_CGM dividers
  feat(nxp-clk): get parent for the fixed dividers
  feat(nxp-clk): set the rate for partition objects
  feat(nxp-clk): add clock objects for CGM dividers
  feat(nxp-clk): add base address for PERIPH_DFS
This commit is contained in:
Olivier Deprez 2025-02-18 15:23:50 +01:00 committed by TrustedFirmware Code Review
commit a229e41a86
6 changed files with 399 additions and 6 deletions

View file

@ -11,6 +11,7 @@
#define ARMPLL_BASE_ADDR (0x40038000UL) #define ARMPLL_BASE_ADDR (0x40038000UL)
#define PERIPHPLL_BASE_ADDR (0x4003C000UL) #define PERIPHPLL_BASE_ADDR (0x4003C000UL)
#define ARM_DFS_BASE_ADDR (0x40054000UL) #define ARM_DFS_BASE_ADDR (0x40054000UL)
#define PERIPH_DFS_BASE_ADDR (0x40058000UL)
#define CGM0_BASE_ADDR (0x40030000UL) #define CGM0_BASE_ADDR (0x40030000UL)
#define CGM1_BASE_ADDR (0x40034000UL) #define CGM1_BASE_ADDR (0x40034000UL)
#define DDRPLL_BASE_ADDR (0x40044000UL) #define DDRPLL_BASE_ADDR (0x40044000UL)
@ -92,6 +93,25 @@
#define MC_CGM_MUXn_CSS_SWTRG_SAFE_CLK_INACTIVE 0x5U #define MC_CGM_MUXn_CSS_SWTRG_SAFE_CLK_INACTIVE 0x5U
#define MC_CGM_MUXn_CSS_SWIP BIT_32(16U) #define MC_CGM_MUXn_CSS_SWIP BIT_32(16U)
#define MC_CGM_MUXn_CSS_SAFE_SW BIT_32(3U) #define MC_CGM_MUXn_CSS_SAFE_SW BIT_32(3U)
#define MC_CGM_MUXn_DCm(CGM_ADDR, MUX, DC) \
(((CGM_ADDR) + 0x308UL) + \
((MUX) * 0x40UL) + ((DC) * 0x4UL))
#define MC_CGM_MUXn_DCm_DIV_OFFSET (16U)
#define MC_CGM_MUXn_DCm_DIV_MASK GENMASK_32(23U, MC_CGM_MUXn_DCm_DIV_OFFSET)
#define MC_CGM_MUXn_DCm_DIV_SET(VAL) (MC_CGM_MUXn_DCm_DIV_MASK & ((VAL) \
<< MC_CGM_MUXn_DCm_DIV_OFFSET))
#define MC_CGM_MUXn_DCm_DIV(VAL) ((MC_CGM_MUXn_DCm_DIV_MASK & (VAL)) \
>> MC_CGM_MUXn_DCm_DIV_OFFSET)
#define MC_CGM_MUXn_DCm_DE BIT_32(31U)
#define MC_CGM_MUXn_DIV_UPD_STAT(CGM_ADDR, MUX) \
(((CGM_ADDR) + 0x33CUL + ((MUX) * 0x40UL)))
#define MC_CGM_MUXn_DIV_UPD_STAT_DIVSTAT_OFFSET (0U)
#define MC_CGM_MUXn_DIV_UPD_STAT_DIVSTAT(CSS) \
((MC_CGM_MUXn_DIV_UPD_STAT_DIVSTAT_MASK \
& (CSS)) \
>> MC_CGM_MUXn_DIV_UPD_STAT_DIVSTAT_OFFSET)
#define MC_CGM_MUXn_DIV_UPD_STAT_DIVSTAT_MASK BIT_32(0U)
/* DFS */ /* DFS */
#define DFS_PORTSR(DFS_ADDR) ((DFS_ADDR) + 0xCUL) #define DFS_PORTSR(DFS_ADDR) ((DFS_ADDR) + 0xCUL)

View file

@ -24,6 +24,7 @@ struct s32cc_clk_drv {
uintptr_t armpll_base; uintptr_t armpll_base;
uintptr_t periphpll_base; uintptr_t periphpll_base;
uintptr_t armdfs_base; uintptr_t armdfs_base;
uintptr_t periphdfs_base;
uintptr_t cgm0_base; uintptr_t cgm0_base;
uintptr_t cgm1_base; uintptr_t cgm1_base;
uintptr_t cgm5_base; uintptr_t cgm5_base;
@ -58,6 +59,7 @@ static struct s32cc_clk_drv *get_drv(void)
.armpll_base = ARMPLL_BASE_ADDR, .armpll_base = ARMPLL_BASE_ADDR,
.periphpll_base = PERIPHPLL_BASE_ADDR, .periphpll_base = PERIPHPLL_BASE_ADDR,
.armdfs_base = ARM_DFS_BASE_ADDR, .armdfs_base = ARM_DFS_BASE_ADDR,
.periphdfs_base = PERIPH_DFS_BASE_ADDR,
.cgm0_base = CGM0_BASE_ADDR, .cgm0_base = CGM0_BASE_ADDR,
.cgm1_base = CGM1_BASE_ADDR, .cgm1_base = CGM1_BASE_ADDR,
.cgm5_base = MC_CGM5_BASE_ADDR, .cgm5_base = MC_CGM5_BASE_ADDR,
@ -110,6 +112,9 @@ static int get_base_addr(enum s32cc_clk_source id, const struct s32cc_clk_drv *d
case S32CC_ARM_DFS: case S32CC_ARM_DFS:
*base = drv->armdfs_base; *base = drv->armdfs_base;
break; break;
case S32CC_PERIPH_DFS:
*base = drv->periphdfs_base;
break;
case S32CC_CGM0: case S32CC_CGM0:
*base = drv->cgm0_base; *base = drv->cgm0_base;
break; break;
@ -1085,6 +1090,232 @@ static int get_part_block_link_freq(const struct s32cc_clk_obj *module,
return get_module_rate(block->parent, drv, rate, ldepth); return get_module_rate(block->parent, drv, rate, ldepth);
} }
static void cgm_mux_div_config(uintptr_t cgm_addr, uint32_t mux,
uint32_t dc, uint32_t div_index)
{
uint32_t updstat;
uint32_t dc_val = mmio_read_32(MC_CGM_MUXn_DCm(cgm_addr, mux, div_index));
dc_val &= (MC_CGM_MUXn_DCm_DIV_MASK | MC_CGM_MUXn_DCm_DE);
if (dc_val == (MC_CGM_MUXn_DCm_DE | MC_CGM_MUXn_DCm_DIV_SET(dc))) {
return;
}
/* Set the divider */
mmio_write_32(MC_CGM_MUXn_DCm(cgm_addr, mux, div_index),
MC_CGM_MUXn_DCm_DE | MC_CGM_MUXn_DCm_DIV_SET(dc));
/* Wait for divider to get updated */
do {
updstat = mmio_read_32(MC_CGM_MUXn_DIV_UPD_STAT(cgm_addr, mux));
} while (MC_CGM_MUXn_DIV_UPD_STAT_DIVSTAT(updstat) != 0U);
}
static inline struct s32cc_clkmux *get_cgm_div_mux(const struct s32cc_cgm_div *cgm_div)
{
const struct s32cc_clk_obj *parent = cgm_div->parent;
const struct s32cc_clk_obj *mux_obj;
const struct s32cc_clk *clk;
if (parent == NULL) {
ERROR("Failed to identify CGM DIV's parent\n");
return NULL;
}
if (parent->type != s32cc_clk_t) {
ERROR("The parent of the CGM DIV isn't a clock\n");
return NULL;
}
clk = s32cc_obj2clk(parent);
if (clk->module == NULL) {
ERROR("The clock isn't connected to a module\n");
return NULL;
}
mux_obj = clk->module;
if ((mux_obj->type != s32cc_clkmux_t) &&
(mux_obj->type != s32cc_shared_clkmux_t)) {
ERROR("The parent of the CGM DIV isn't a MUX\n");
return NULL;
}
return s32cc_obj2clkmux(mux_obj);
}
static int enable_cgm_div(struct s32cc_clk_obj *module,
const struct s32cc_clk_drv *drv, unsigned int depth)
{
const struct s32cc_cgm_div *cgm_div = s32cc_obj2cgmdiv(module);
const struct s32cc_clkmux *mux;
unsigned int ldepth = depth;
uintptr_t cgm_addr = 0ULL;
uint64_t pfreq, dc64;
uint32_t dc;
int ret;
ret = update_stack_depth(&ldepth);
if (ret != 0) {
return ret;
}
if (cgm_div->parent == NULL) {
ERROR("Failed to identify CGM divider's parent\n");
return -EINVAL;
}
if (cgm_div->freq == 0U) {
ERROR("The frequency of the divider %" PRIu32 " is not set\n",
cgm_div->index);
return -EINVAL;
}
mux = get_cgm_div_mux(cgm_div);
if (mux == NULL) {
return -EINVAL;
}
ret = get_base_addr(mux->module, drv, &cgm_addr);
if (ret != 0) {
ERROR("Failed to get CGM base address of the MUX module %d\n",
mux->module);
return ret;
}
ret = get_module_rate(cgm_div->parent, drv, &pfreq, ldepth);
if (ret != 0) {
ERROR("Failed to enable the div due to unknown frequency of "
"the CGM MUX %" PRIu8 "(CGM=%" PRIxPTR ")\n",
mux->index, cgm_addr);
return -EINVAL;
}
dc64 = ((pfreq * FP_PRECISION) / cgm_div->freq) / FP_PRECISION;
dc = (uint32_t)dc64;
if ((pfreq / dc64) != cgm_div->freq) {
ERROR("Cannot set CGM divider (mux:%" PRIu8 ", div:%" PRIu32
") for input = %lu & output = %lu, Nearest freq = %lu\n",
mux->index, cgm_div->index, (unsigned long)pfreq,
cgm_div->freq, (unsigned long)(pfreq / dc));
return -EINVAL;
}
cgm_mux_div_config(cgm_addr, mux->index, dc - 1U, cgm_div->index);
return 0;
}
static int set_cgm_div_freq(const struct s32cc_clk_obj *module,
unsigned long rate, unsigned long *orate,
unsigned int *depth)
{
struct s32cc_cgm_div *cgm_div = s32cc_obj2cgmdiv(module);
int ret;
ret = update_stack_depth(depth);
if (ret != 0) {
return ret;
}
if (cgm_div->parent == NULL) {
ERROR("Failed to identify the CGM divider's parent\n");
return -EINVAL;
}
cgm_div->freq = rate;
*orate = rate;
return 0;
}
static inline bool is_cgm_div_enabled(uintptr_t cgm_addr, uint32_t mux,
uint32_t div_index)
{
uint32_t dc_val;
dc_val = mmio_read_32(MC_CGM_MUXn_DCm(cgm_addr, mux, div_index));
return ((dc_val & MC_CGM_MUXn_DCm_DE) != 0U);
}
static unsigned long calc_cgm_div_freq(uintptr_t cgm_addr, uint32_t mux,
uint32_t div_index, unsigned long pfreq)
{
uint32_t dc_val;
uint32_t dc_div;
dc_val = mmio_read_32(MC_CGM_MUXn_DCm(cgm_addr, mux, div_index));
dc_div = MC_CGM_MUXn_DCm_DIV(dc_val) + 1U;
return pfreq * FP_PRECISION / dc_div / FP_PRECISION;
}
static int get_cgm_div_freq(const struct s32cc_clk_obj *module,
const struct s32cc_clk_drv *drv,
unsigned long *rate, unsigned int depth)
{
const struct s32cc_cgm_div *cgm_div = s32cc_obj2cgmdiv(module);
const struct s32cc_clkmux *mux;
unsigned int ldepth = depth;
uintptr_t cgm_addr = 0ULL;
unsigned long pfreq;
int ret;
ret = update_stack_depth(&ldepth);
if (ret != 0) {
return ret;
}
if (cgm_div->parent == NULL) {
ERROR("Failed to identify CGM divider's parent\n");
return -EINVAL;
}
mux = get_cgm_div_mux(cgm_div);
if (mux == NULL) {
return -EINVAL;
}
ret = get_base_addr(mux->module, drv, &cgm_addr);
if (ret != 0) {
ERROR("Failed to get CGM base address of the MUX module %d\n",
mux->module);
return ret;
}
if (!is_cgm_div_enabled(cgm_addr, mux->index, cgm_div->index)) {
*rate = cgm_div->freq;
return 0;
}
ret = get_module_rate(cgm_div->parent, drv, &pfreq, ldepth);
if (ret != 0) {
ERROR("Failed to get the frequency of CGM MUX %" PRIu8 "(CGM=0x%" PRIxPTR ")\n",
mux->index, cgm_addr);
return ret;
}
*rate = calc_cgm_div_freq(cgm_addr, mux->index, cgm_div->index, pfreq);
return 0;
}
static struct s32cc_clk_obj *
get_cgm_div_parent(const struct s32cc_clk_obj *module)
{
const struct s32cc_cgm_div *cgm_div = s32cc_obj2cgmdiv(module);
if (cgm_div->parent == NULL) {
ERROR("Failed to identify the CGM divider's parent\n");
return NULL;
}
return cgm_div->parent;
}
static int no_enable(struct s32cc_clk_obj *module, static int no_enable(struct s32cc_clk_obj *module,
const struct s32cc_clk_drv *drv, const struct s32cc_clk_drv *drv,
unsigned int depth) unsigned int depth)
@ -1131,7 +1362,7 @@ static int enable_module(struct s32cc_clk_obj *module,
unsigned int depth) unsigned int depth)
{ {
struct s32cc_clk_obj *parent = get_module_parent(module); struct s32cc_clk_obj *parent = get_module_parent(module);
static const enable_clk_t enable_clbs[12] = { static const enable_clk_t enable_clbs[13] = {
[s32cc_clk_t] = no_enable, [s32cc_clk_t] = no_enable,
[s32cc_osc_t] = enable_osc, [s32cc_osc_t] = enable_osc,
[s32cc_pll_t] = enable_pll, [s32cc_pll_t] = enable_pll,
@ -1143,6 +1374,7 @@ static int enable_module(struct s32cc_clk_obj *module,
[s32cc_part_t] = enable_part, [s32cc_part_t] = enable_part,
[s32cc_part_block_t] = enable_part_block, [s32cc_part_block_t] = enable_part_block,
[s32cc_part_block_link_t] = enable_part_block_link, [s32cc_part_block_link_t] = enable_part_block_link,
[s32cc_cgm_div_t] = enable_cgm_div,
}; };
unsigned int ldepth = depth; unsigned int ldepth = depth;
uint32_t index; uint32_t index;
@ -1558,6 +1790,13 @@ static int get_fixed_div_freq(const struct s32cc_clk_obj *module,
return 0; return 0;
} }
static inline struct s32cc_clk_obj *get_fixed_div_parent(const struct s32cc_clk_obj *module)
{
const struct s32cc_fixed_div *fdiv = s32cc_obj2fixeddiv(module);
return fdiv->parent;
}
static int set_mux_freq(const struct s32cc_clk_obj *module, unsigned long rate, static int set_mux_freq(const struct s32cc_clk_obj *module, unsigned long rate,
unsigned long *orate, unsigned int *depth) unsigned long *orate, unsigned int *depth)
{ {
@ -1703,6 +1942,28 @@ static int get_dfs_div_freq(const struct s32cc_clk_obj *module,
return 0; return 0;
} }
static int set_part_block_link_freq(const struct s32cc_clk_obj *module,
unsigned long rate, unsigned long *orate,
const unsigned int *depth)
{
const struct s32cc_part_block_link *link = s32cc_obj2partblocklink(module);
const struct s32cc_clk_obj *parent = link->parent;
unsigned int ldepth = *depth;
int ret;
ret = update_stack_depth(&ldepth);
if (ret != 0) {
return ret;
}
if (parent == NULL) {
ERROR("Partition block link with no parent\n");
return -EINVAL;
}
return set_module_rate(parent, rate, orate, &ldepth);
}
static int set_module_rate(const struct s32cc_clk_obj *module, static int set_module_rate(const struct s32cc_clk_obj *module,
unsigned long rate, unsigned long *orate, unsigned long rate, unsigned long *orate,
unsigned int *depth) unsigned int *depth)
@ -1738,12 +1999,24 @@ static int set_module_rate(const struct s32cc_clk_obj *module,
case s32cc_shared_clkmux_t: case s32cc_shared_clkmux_t:
ret = set_mux_freq(module, rate, orate, depth); ret = set_mux_freq(module, rate, orate, depth);
break; break;
case s32cc_cgm_div_t:
ret = set_cgm_div_freq(module, rate, orate, depth);
break;
case s32cc_dfs_t: case s32cc_dfs_t:
ERROR("Setting the frequency of a DFS is not allowed!"); ERROR("Setting the frequency of a DFS is not allowed!");
break; break;
case s32cc_dfs_div_t: case s32cc_dfs_div_t:
ret = set_dfs_div_freq(module, rate, orate, depth); ret = set_dfs_div_freq(module, rate, orate, depth);
break; break;
case s32cc_part_block_link_t:
ret = set_part_block_link_freq(module, rate, orate, depth);
break;
case s32cc_part_t:
ERROR("It's not allowed to set the frequency of a partition !");
break;
case s32cc_part_block_t:
ERROR("It's not allowed to set the frequency of a partition block !");
break;
default: default:
break; break;
} }
@ -1801,6 +2074,9 @@ static int get_module_rate(const struct s32cc_clk_obj *module,
case s32cc_part_block_link_t: case s32cc_part_block_link_t:
ret = get_part_block_link_freq(module, drv, rate, ldepth); ret = get_part_block_link_freq(module, drv, rate, ldepth);
break; break;
case s32cc_cgm_div_t:
ret = get_cgm_div_freq(module, drv, rate, ldepth);
break;
default: default:
ret = -EINVAL; ret = -EINVAL;
break; break;
@ -1862,7 +2138,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 struct s32cc_clk_obj *get_module_parent(const struct s32cc_clk_obj *module)
{ {
static const get_parent_clb_t parents_clbs[12] = { static const get_parent_clb_t parents_clbs[13] = {
[s32cc_clk_t] = get_clk_parent, [s32cc_clk_t] = get_clk_parent,
[s32cc_osc_t] = get_no_parent, [s32cc_osc_t] = get_no_parent,
[s32cc_pll_t] = get_pll_parent, [s32cc_pll_t] = get_pll_parent,
@ -1872,8 +2148,10 @@ static struct s32cc_clk_obj *get_module_parent(const struct s32cc_clk_obj *modul
[s32cc_dfs_t] = get_dfs_parent, [s32cc_dfs_t] = get_dfs_parent,
[s32cc_dfs_div_t] = get_dfs_div_parent, [s32cc_dfs_div_t] = get_dfs_div_parent,
[s32cc_part_t] = get_no_parent, [s32cc_part_t] = get_no_parent,
[s32cc_fixed_div_t] = get_fixed_div_parent,
[s32cc_part_block_t] = get_part_block_parent, [s32cc_part_block_t] = get_part_block_parent,
[s32cc_part_block_link_t] = get_part_block_link_parent, [s32cc_part_block_link_t] = get_part_block_link_parent,
[s32cc_cgm_div_t] = get_cgm_div_parent,
}; };
uint32_t index; uint32_t index;
@ -1980,11 +2258,12 @@ static int s32cc_clk_set_parent(unsigned long id, unsigned long parent_id)
static int s32cc_clk_mmap_regs(const struct s32cc_clk_drv *drv) static int s32cc_clk_mmap_regs(const struct s32cc_clk_drv *drv)
{ {
const uintptr_t base_addrs[11] = { const uintptr_t base_addrs[12] = {
drv->fxosc_base, drv->fxosc_base,
drv->armpll_base, drv->armpll_base,
drv->periphpll_base, drv->periphpll_base,
drv->armdfs_base, drv->armdfs_base,
drv->periphdfs_base,
drv->cgm0_base, drv->cgm0_base,
drv->cgm1_base, drv->cgm1_base,
drv->cgm5_base, drv->cgm5_base,

View file

@ -68,6 +68,12 @@ static struct s32cc_clkmux cgm0_mux8 =
S32CC_CLK_FXOSC, 0, 0); S32CC_CLK_FXOSC, 0, 0);
static struct s32cc_clk cgm0_mux8_clk = S32CC_MODULE_CLK(cgm0_mux8); static struct s32cc_clk cgm0_mux8_clk = S32CC_MODULE_CLK(cgm0_mux8);
static struct s32cc_clkmux cgm0_mux14 =
S32CC_CLKMUX_INIT(S32CC_CGM0, 14, 2,
S32CC_CLK_FIRC,
S32CC_CLK_PERIPH_PLL_DFS3, 0, 0, 0);
static struct s32cc_clk cgm0_mux14_clk = S32CC_MODULE_CLK(cgm0_mux14);
/* XBAR */ /* XBAR */
static struct s32cc_clk xbar_2x_clk = static struct s32cc_clk xbar_2x_clk =
S32CC_CHILD_CLK(cgm0_mux0_clk, 48 * MHZ, 800 * MHZ); S32CC_CHILD_CLK(cgm0_mux0_clk, 48 * MHZ, 800 * MHZ);
@ -142,6 +148,14 @@ static struct s32cc_pll_out_div periph_pll_phi3_div =
static struct s32cc_clk periph_pll_phi3_clk = static struct s32cc_clk periph_pll_phi3_clk =
S32CC_FREQ_MODULE_CLK(periph_pll_phi3_div, 0, 133333333); S32CC_FREQ_MODULE_CLK(periph_pll_phi3_div, 0, 133333333);
/* PERIPH DFS */
static struct s32cc_dfs periphdfs =
S32CC_DFS_INIT(periphpll, S32CC_PERIPH_DFS);
static struct s32cc_dfs_div periph_dfs3_div =
S32CC_DFS_DIV_INIT(periphdfs, 0);
static struct s32cc_clk periph_dfs3_clk =
S32CC_FREQ_MODULE_CLK(periph_dfs3_div, 416 * MHZ, 800 * MHZ);
/* DDR PLL */ /* DDR PLL */
static struct s32cc_clkmux ddr_pll_mux = static struct s32cc_clkmux ddr_pll_mux =
S32CC_CLKMUX_INIT(S32CC_DDR_PLL, 0, 2, S32CC_CLKMUX_INIT(S32CC_DDR_PLL, 0, 2,
@ -175,6 +189,15 @@ static struct s32cc_part_block_link ddr_block_link =
static struct s32cc_clk ddr_clk = static struct s32cc_clk ddr_clk =
S32CC_FREQ_MODULE_CLK(ddr_block_link, 0, 800 * MHZ); S32CC_FREQ_MODULE_CLK(ddr_block_link, 0, 800 * MHZ);
/* SDHC_CLK */
static struct s32cc_part_block part0_block0 =
S32CC_PART_BLOCK(&part0, s32cc_part_block0);
static struct s32cc_cgm_div sdhc_div = S32CC_CGM_DIV_INIT(cgm0_mux14_clk, 0);
static struct s32cc_part_block_link usdhc_block_link =
S32CC_PART_BLOCK_LINK(sdhc_div, &part0_block0);
static struct s32cc_clk usdhc_clk =
S32CC_FREQ_MODULE_CLK(usdhc_block_link, 0, 400 * MHZ);
static struct s32cc_clk *s32cc_hw_clk_list[37] = { static struct s32cc_clk *s32cc_hw_clk_list[37] = {
/* Oscillators */ /* Oscillators */
[S32CC_CLK_ID(S32CC_CLK_FIRC)] = &firc_clk, [S32CC_CLK_ID(S32CC_CLK_FIRC)] = &firc_clk,
@ -186,6 +209,8 @@ static struct s32cc_clk *s32cc_hw_clk_list[37] = {
[S32CC_CLK_ID(S32CC_CLK_ARM_PLL_DFS1)] = &arm_dfs1_clk, [S32CC_CLK_ID(S32CC_CLK_ARM_PLL_DFS1)] = &arm_dfs1_clk,
/* PERIPH PLL */ /* PERIPH PLL */
[S32CC_CLK_ID(S32CC_CLK_PERIPH_PLL_PHI3)] = &periph_pll_phi3_clk, [S32CC_CLK_ID(S32CC_CLK_PERIPH_PLL_PHI3)] = &periph_pll_phi3_clk,
/* PERIPH DFS */
[S32CC_CLK_ID(S32CC_CLK_PERIPH_PLL_DFS3)] = &periph_dfs3_clk,
/* DDR PLL */ /* DDR PLL */
[S32CC_CLK_ID(S32CC_CLK_DDR_PLL_PHI0)] = &ddr_pll_phi0_clk, [S32CC_CLK_ID(S32CC_CLK_DDR_PLL_PHI0)] = &ddr_pll_phi0_clk,
}; };
@ -196,7 +221,7 @@ static struct s32cc_clk_array s32cc_hw_clocks = {
.n_clks = ARRAY_SIZE(s32cc_hw_clk_list), .n_clks = ARRAY_SIZE(s32cc_hw_clk_list),
}; };
static struct s32cc_clk *s32cc_arch_clk_list[22] = { static struct s32cc_clk *s32cc_arch_clk_list[24] = {
/* ARM PLL */ /* ARM PLL */
[S32CC_CLK_ID(S32CC_CLK_ARM_PLL_MUX)] = &arm_pll_mux_clk, [S32CC_CLK_ID(S32CC_CLK_ARM_PLL_MUX)] = &arm_pll_mux_clk,
[S32CC_CLK_ID(S32CC_CLK_ARM_PLL_VCO)] = &arm_pll_vco_clk, [S32CC_CLK_ID(S32CC_CLK_ARM_PLL_VCO)] = &arm_pll_vco_clk,
@ -206,6 +231,7 @@ static struct s32cc_clk *s32cc_arch_clk_list[22] = {
/* MC_CGM0 */ /* MC_CGM0 */
[S32CC_CLK_ID(S32CC_CLK_MC_CGM0_MUX0)] = &cgm0_mux0_clk, [S32CC_CLK_ID(S32CC_CLK_MC_CGM0_MUX0)] = &cgm0_mux0_clk,
[S32CC_CLK_ID(S32CC_CLK_MC_CGM0_MUX8)] = &cgm0_mux8_clk, [S32CC_CLK_ID(S32CC_CLK_MC_CGM0_MUX8)] = &cgm0_mux8_clk,
[S32CC_CLK_ID(S32CC_CLK_MC_CGM0_MUX14)] = &cgm0_mux14_clk,
/* XBAR */ /* XBAR */
[S32CC_CLK_ID(S32CC_CLK_XBAR_2X)] = &xbar_2x_clk, [S32CC_CLK_ID(S32CC_CLK_XBAR_2X)] = &xbar_2x_clk,
[S32CC_CLK_ID(S32CC_CLK_XBAR)] = &xbar_clk, [S32CC_CLK_ID(S32CC_CLK_XBAR)] = &xbar_clk,
@ -229,6 +255,8 @@ static struct s32cc_clk *s32cc_arch_clk_list[22] = {
[S32CC_CLK_ID(S32CC_CLK_MC_CGM5_MUX0)] = &cgm5_mux0_clk, [S32CC_CLK_ID(S32CC_CLK_MC_CGM5_MUX0)] = &cgm5_mux0_clk,
/* DDR */ /* DDR */
[S32CC_CLK_ID(S32CC_CLK_DDR)] = &ddr_clk, [S32CC_CLK_ID(S32CC_CLK_DDR)] = &ddr_clk,
/* USDHC */
[S32CC_CLK_ID(S32CC_CLK_USDHC)] = &usdhc_clk,
}; };
static struct s32cc_clk_array s32cc_arch_clocks = { static struct s32cc_clk_array s32cc_arch_clocks = {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2024 NXP * Copyright 2024-2025 NXP
* *
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
@ -18,6 +18,8 @@
#define S32CC_PERIPH_PLL_PHI3_FREQ UART_CLOCK_HZ #define S32CC_PERIPH_PLL_PHI3_FREQ UART_CLOCK_HZ
#define S32CC_DDR_PLL_VCO_FREQ (1600U * MHZ) #define S32CC_DDR_PLL_VCO_FREQ (1600U * MHZ)
#define S32CC_DDR_PLL_PHI0_FREQ (800U * MHZ) #define S32CC_DDR_PLL_PHI0_FREQ (800U * MHZ)
#define S32CC_PERIPH_DFS_PHI3_FREQ (800U * MHZ)
#define S32CC_USDHC_FREQ (400U * MHZ)
static int setup_fxosc(void) static int setup_fxosc(void)
{ {
@ -180,6 +182,35 @@ static int enable_ddr_clk(void)
return ret; return ret;
} }
static int enable_usdhc_clk(void)
{
int ret;
ret = clk_set_parent(S32CC_CLK_MC_CGM0_MUX14,
S32CC_CLK_PERIPH_PLL_DFS3);
if (ret != 0) {
return ret;
}
ret = clk_set_rate(S32CC_CLK_PERIPH_PLL_DFS3,
S32CC_PERIPH_DFS_PHI3_FREQ, NULL);
if (ret != 0) {
return ret;
}
ret = clk_set_rate(S32CC_CLK_USDHC, S32CC_USDHC_FREQ, NULL);
if (ret != 0) {
return ret;
}
ret = clk_enable(S32CC_CLK_USDHC);
if (ret != 0) {
return ret;
}
return ret;
}
int s32cc_init_core_clocks(void) int s32cc_init_core_clocks(void)
{ {
int ret; int ret;
@ -241,5 +272,10 @@ int s32cc_init_early_clks(void)
return ret; return ret;
} }
ret = enable_usdhc_clk();
if (ret != 0) {
return ret;
}
return ret; return ret;
} }

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause */ /* SPDX-License-Identifier: BSD-3-Clause */
/* /*
* Copyright 2024 NXP * Copyright 2024-2025 NXP
*/ */
#ifndef S32CC_CLK_IDS_H #ifndef S32CC_CLK_IDS_H
#define S32CC_CLK_IDS_H #define S32CC_CLK_IDS_H
@ -103,4 +103,8 @@
#define S32CC_CLK_MC_CGM5_MUX0 S32CC_ARCH_CLK(20) #define S32CC_CLK_MC_CGM5_MUX0 S32CC_ARCH_CLK(20)
#define S32CC_CLK_DDR S32CC_ARCH_CLK(21) #define S32CC_CLK_DDR S32CC_ARCH_CLK(21)
/* USDHC clock */
#define S32CC_CLK_MC_CGM0_MUX14 S32CC_ARCH_CLK(22)
#define S32CC_CLK_USDHC S32CC_ARCH_CLK(23)
#endif /* S32CC_CLK_IDS_H */ #endif /* S32CC_CLK_IDS_H */

View file

@ -19,6 +19,7 @@ enum s32cc_clkm_type {
s32cc_pll_out_div_t, s32cc_pll_out_div_t,
s32cc_dfs_t, s32cc_dfs_t,
s32cc_dfs_div_t, s32cc_dfs_div_t,
s32cc_cgm_div_t,
s32cc_clkmux_t, s32cc_clkmux_t,
s32cc_shared_clkmux_t, s32cc_shared_clkmux_t,
s32cc_fixed_div_t, s32cc_fixed_div_t,
@ -37,6 +38,7 @@ enum s32cc_clk_source {
S32CC_CGM0, S32CC_CGM0,
S32CC_CGM1, S32CC_CGM1,
S32CC_DDR_PLL, S32CC_DDR_PLL,
S32CC_PERIPH_DFS,
S32CC_CGM5, S32CC_CGM5,
}; };
@ -287,6 +289,22 @@ struct s32cc_part_block_link {
.block = (BLOCK), \ .block = (BLOCK), \
} }
struct s32cc_cgm_div {
struct s32cc_clk_obj desc;
struct s32cc_clk_obj *parent;
unsigned long freq;
uint32_t index;
};
#define S32CC_CGM_DIV_INIT(PARENT, INDEX) \
{ \
.desc = { \
.type = s32cc_cgm_div_t, \
}, \
.parent = &(PARENT).desc, \
.index = (INDEX), \
}
static inline struct s32cc_osc *s32cc_obj2osc(const struct s32cc_clk_obj *mod) static inline struct s32cc_osc *s32cc_obj2osc(const struct s32cc_clk_obj *mod)
{ {
uintptr_t osc_addr; uintptr_t osc_addr;
@ -399,4 +417,12 @@ s32cc_obj2partblocklink(const struct s32cc_clk_obj *mod)
return (struct s32cc_part_block_link *)blk_link; return (struct s32cc_part_block_link *)blk_link;
} }
static inline struct s32cc_cgm_div *s32cc_obj2cgmdiv(const struct s32cc_clk_obj *mod)
{
uintptr_t cgm_div_addr;
cgm_div_addr = ((uintptr_t)mod) - offsetof(struct s32cc_cgm_div, desc);
return (struct s32cc_cgm_div *)cgm_div_addr;
}
#endif /* S32CC_CLK_MODULES_H */ #endif /* S32CC_CLK_MODULES_H */