mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-23 21:44:15 +00:00
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:
commit
a229e41a86
6 changed files with 399 additions and 6 deletions
|
@ -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)
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Add table
Reference in a new issue