feat(nxp-clk): add clock objects for ARM PLL
Add all the clock objects needed to describe the ARM PLL, which can be
powered by either FXOSC or FIRC oscillators.
Change-Id: I2585ed38178ca1d5c5485adb38af1b3b8d94f1f6
Signed-off-by: Ghennadi Procopciuc <ghennadi.procopciuc@nxp.com>
diff --git a/drivers/nxp/clk/s32cc/s32cc_clk_drv.c b/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
index c331a82..c15b033 100644
--- a/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
+++ b/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
@@ -142,6 +142,15 @@
case s32cc_clk_t:
ret = enable_clk_module(module, drv, depth);
break;
+ case s32cc_clkmux_t:
+ ret = -ENOTSUP;
+ break;
+ case s32cc_pll_t:
+ ret = -ENOTSUP;
+ break;
+ case s32cc_pll_out_div_t:
+ ret = -ENOTSUP;
+ break;
default:
ret = -EINVAL;
break;
@@ -251,6 +260,11 @@
case s32cc_osc_t:
ret = set_osc_freq(module, rate, orate, depth);
break;
+ case s32cc_clkmux_t:
+ case s32cc_pll_t:
+ case s32cc_pll_out_div_t:
+ ret = -ENOTSUP;
+ break;
default:
ret = -EINVAL;
break;
diff --git a/drivers/nxp/clk/s32cc/s32cc_clk_modules.c b/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
index f8fc52f..b75c3ff 100644
--- a/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
+++ b/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
@@ -23,11 +23,30 @@
static struct s32cc_clk sirc_clk =
S32CC_MODULE_CLK(sirc);
-static struct s32cc_clk *s32cc_hw_clk_list[3] = {
+/* ARM PLL */
+static struct s32cc_clkmux arm_pll_mux =
+ S32CC_CLKMUX_INIT(S32CC_ARM_PLL, 0, 2,
+ S32CC_CLK_FIRC,
+ S32CC_CLK_FXOSC, 0, 0, 0);
+static struct s32cc_clk arm_pll_mux_clk =
+ S32CC_MODULE_CLK(arm_pll_mux);
+static struct s32cc_pll armpll =
+ S32CC_PLL_INIT(arm_pll_mux_clk, S32CC_ARM_PLL, 2);
+static struct s32cc_clk arm_pll_vco_clk =
+ S32CC_FREQ_MODULE_CLK(armpll, 1400 * MHZ, 2000 * MHZ);
+
+static struct s32cc_pll_out_div arm_pll_phi0_div =
+ S32CC_PLL_OUT_DIV_INIT(armpll, 0);
+static struct s32cc_clk arm_pll_phi0_clk =
+ S32CC_FREQ_MODULE_CLK(arm_pll_phi0_div, 0, GHZ);
+
+static struct s32cc_clk *s32cc_hw_clk_list[5] = {
/* Oscillators */
[S32CC_CLK_ID(S32CC_CLK_FIRC)] = &firc_clk,
[S32CC_CLK_ID(S32CC_CLK_SIRC)] = &sirc_clk,
[S32CC_CLK_ID(S32CC_CLK_FXOSC)] = &fxosc_clk,
+ /* ARM PLL */
+ [S32CC_CLK_ID(S32CC_CLK_ARM_PLL_PHI0)] = &arm_pll_phi0_clk,
};
static struct s32cc_clk_array s32cc_hw_clocks = {
@@ -36,10 +55,23 @@
.n_clks = ARRAY_SIZE(s32cc_hw_clk_list),
};
+static struct s32cc_clk *s32cc_arch_clk_list[2] = {
+ /* 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,
+};
+
+static struct s32cc_clk_array s32cc_arch_clocks = {
+ .type_mask = S32CC_CLK_TYPE(S32CC_CLK_ARM_PLL_MUX),
+ .clks = &s32cc_arch_clk_list[0],
+ .n_clks = ARRAY_SIZE(s32cc_arch_clk_list),
+};
+
struct s32cc_clk *s32cc_get_arch_clk(unsigned long id)
{
- static const struct s32cc_clk_array *clk_table[1] = {
+ static const struct s32cc_clk_array *clk_table[2] = {
&s32cc_hw_clocks,
+ &s32cc_arch_clocks,
};
return s32cc_get_clk_from_table(clk_table, ARRAY_SIZE(clk_table), id);
diff --git a/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h b/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
index 9524f72..648af63 100644
--- a/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
+++ b/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
@@ -14,12 +14,16 @@
enum s32cc_clkm_type {
s32cc_osc_t,
s32cc_clk_t,
+ s32cc_pll_t,
+ s32cc_pll_out_div_t,
+ s32cc_clkmux_t,
};
enum s32cc_clk_source {
S32CC_FIRC,
S32CC_FXOSC,
S32CC_SIRC,
+ S32CC_ARM_PLL,
};
struct s32cc_clk_obj {
@@ -42,6 +46,65 @@
.source = (SOURCE), \
}
+struct s32cc_clkmux {
+ struct s32cc_clk_obj desc;
+ enum s32cc_clk_source module;
+ uint8_t index; /* Mux index in parent module */
+ unsigned long source_id; /* Selected source */
+ uint8_t nclks; /* Number of input clocks */
+ unsigned long clkids[5]; /* IDs of the input clocks */
+};
+
+#define S32CC_CLKMUX_TYPE_INIT(TYPE, MODULE, INDEX, NCLKS, ...) \
+{ \
+ .desc = { \
+ .type = (TYPE), \
+ }, \
+ .module = (MODULE), \
+ .index = (INDEX), \
+ .nclks = (NCLKS), \
+ .clkids = {__VA_ARGS__}, \
+}
+
+#define S32CC_CLKMUX_INIT(MODULE, INDEX, NCLKS, ...) \
+ S32CC_CLKMUX_TYPE_INIT(s32cc_clkmux_t, MODULE, \
+ INDEX, NCLKS, __VA_ARGS__)
+
+struct s32cc_pll {
+ struct s32cc_clk_obj desc;
+ struct s32cc_clk_obj *source;
+ enum s32cc_clk_source instance;
+ unsigned long vco_freq;
+ uint32_t ndividers;
+ uintptr_t base;
+};
+
+#define S32CC_PLL_INIT(PLL_MUX_CLK, INSTANCE, NDIVIDERS) \
+{ \
+ .desc = { \
+ .type = s32cc_pll_t, \
+ }, \
+ .source = &(PLL_MUX_CLK).desc, \
+ .instance = (INSTANCE), \
+ .ndividers = (NDIVIDERS), \
+}
+
+struct s32cc_pll_out_div {
+ struct s32cc_clk_obj desc;
+ struct s32cc_clk_obj *parent;
+ uint32_t index;
+ unsigned long freq;
+};
+
+#define S32CC_PLL_OUT_DIV_INIT(PARENT, INDEX) \
+{ \
+ .desc = { \
+ .type = s32cc_pll_out_div_t, \
+ }, \
+ .parent = &(PARENT).desc, \
+ .index = (INDEX), \
+}
+
struct s32cc_clk {
struct s32cc_clk_obj desc;
struct s32cc_clk_obj *module;