clk: meson: g12a: add cpu clocks
authorNeil Armstrong <narmstrong@baylibre.com>
Mon, 4 Mar 2019 13:11:29 +0000 (14:11 +0100)
committerNeil Armstrong <narmstrong@baylibre.com>
Mon, 1 Apr 2019 08:45:11 +0000 (10:45 +0200)
Add the Amlogic G12A Family CPU Clock tree in read/only for now.

The CPU clock can either use the SYS_PLL for > 1GHz frequencies or
use a couple of div+mux from 1GHz/667MHz/24MHz source with 2 non-glitch
muxes.

Proper DVFS support will come in a second time.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Acked-by: Jerome Brunet <jbrunet@baylibre.com>
[narmstrong: fixed cpu clocks namings]
Link: https://lkml.kernel.org/r/20190304131129.7762-3-narmstrong@baylibre.com
drivers/clk/meson/g12a.c
drivers/clk/meson/g12a.h

index 0e1ce8c..10ba8bc 100644 (file)
@@ -150,6 +150,318 @@ static struct clk_regmap g12a_sys_pll = {
        },
 };
 
+static struct clk_regmap g12a_sys_pll_div16_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .bit_idx = 24,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "sys_pll_div16_en",
+               .ops = &clk_regmap_gate_ro_ops,
+               .parent_names = (const char *[]){ "sys_pll" },
+               .num_parents = 1,
+               /*
+                * This clock is used to debug the sys_pll range
+                * Linux should not change it at runtime
+                */
+       },
+};
+
+static struct clk_fixed_factor g12a_sys_pll_div16 = {
+       .mult = 1,
+       .div = 16,
+       .hw.init = &(struct clk_init_data){
+               .name = "sys_pll_div16",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "sys_pll_div16_en" },
+               .num_parents = 1,
+       },
+};
+
+/* Datasheet names this field as "premux0" */
+static struct clk_regmap g12a_cpu_clk_premux0 = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL0,
+               .mask = 0x3,
+               .shift = 0,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_dyn0_sel",
+               .ops = &clk_regmap_mux_ro_ops,
+               .parent_names = (const char *[]){ IN_PREFIX "xtal",
+                                                 "fclk_div2",
+                                                 "fclk_div3" },
+               .num_parents = 3,
+       },
+};
+
+/* Datasheet names this field as "mux0_divn_tcnt" */
+static struct clk_regmap g12a_cpu_clk_mux0_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL0,
+               .shift = 4,
+               .width = 6,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_dyn0_div",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_dyn0_sel" },
+               .num_parents = 1,
+       },
+};
+
+/* Datasheet names this field as "postmux0" */
+static struct clk_regmap g12a_cpu_clk_postmux0 = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL0,
+               .mask = 0x1,
+               .shift = 2,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_dyn0",
+               .ops = &clk_regmap_mux_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_dyn0_sel",
+                                                 "cpu_clk_dyn0_div" },
+               .num_parents = 2,
+       },
+};
+
+/* Datasheet names this field as "premux1" */
+static struct clk_regmap g12a_cpu_clk_premux1 = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL0,
+               .mask = 0x3,
+               .shift = 16,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_dyn1_sel",
+               .ops = &clk_regmap_mux_ro_ops,
+               .parent_names = (const char *[]){ IN_PREFIX "xtal",
+                                                 "fclk_div2",
+                                                 "fclk_div3" },
+               .num_parents = 3,
+       },
+};
+
+/* Datasheet names this field as "Mux1_divn_tcnt" */
+static struct clk_regmap g12a_cpu_clk_mux1_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL0,
+               .shift = 20,
+               .width = 6,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_dyn1_div",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_dyn1_sel" },
+               .num_parents = 1,
+       },
+};
+
+/* Datasheet names this field as "postmux1" */
+static struct clk_regmap g12a_cpu_clk_postmux1 = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL0,
+               .mask = 0x1,
+               .shift = 18,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_dyn1",
+               .ops = &clk_regmap_mux_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_dyn1_sel",
+                                                 "cpu_clk_dyn1_div" },
+               .num_parents = 2,
+       },
+};
+
+/* Datasheet names this field as "Final_dyn_mux_sel" */
+static struct clk_regmap g12a_cpu_clk_dyn = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL0,
+               .mask = 0x1,
+               .shift = 10,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_dyn",
+               .ops = &clk_regmap_mux_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_dyn0",
+                                                 "cpu_clk_dyn1" },
+               .num_parents = 2,
+       },
+};
+
+/* Datasheet names this field as "Final_mux_sel" */
+static struct clk_regmap g12a_cpu_clk = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL0,
+               .mask = 0x1,
+               .shift = 11,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk",
+               .ops = &clk_regmap_mux_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_dyn",
+                                                 "sys_pll" },
+               .num_parents = 2,
+       },
+};
+
+static struct clk_regmap g12a_cpu_clk_div16_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .bit_idx = 1,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "cpu_clk_div16_en",
+               .ops = &clk_regmap_gate_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk" },
+               .num_parents = 1,
+               /*
+                * This clock is used to debug the cpu_clk range
+                * Linux should not change it at runtime
+                */
+       },
+};
+
+static struct clk_fixed_factor g12a_cpu_clk_div16 = {
+       .mult = 1,
+       .div = 16,
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_div16",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "cpu_clk_div16_en" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_cpu_clk_apb_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .shift = 3,
+               .width = 3,
+               .flags = CLK_DIVIDER_POWER_OF_TWO,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_apb_div",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_cpu_clk_apb = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .bit_idx = 1,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "cpu_clk_apb",
+               .ops = &clk_regmap_gate_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_apb_div" },
+               .num_parents = 1,
+               /*
+                * This clock is set by the ROM monitor code,
+                * Linux should not change it at runtime
+                */
+       },
+};
+
+static struct clk_regmap g12a_cpu_clk_atb_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .shift = 6,
+               .width = 3,
+               .flags = CLK_DIVIDER_POWER_OF_TWO,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_atb_div",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_cpu_clk_atb = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .bit_idx = 17,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "cpu_clk_atb",
+               .ops = &clk_regmap_gate_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_atb_div" },
+               .num_parents = 1,
+               /*
+                * This clock is set by the ROM monitor code,
+                * Linux should not change it at runtime
+                */
+       },
+};
+
+static struct clk_regmap g12a_cpu_clk_axi_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .shift = 9,
+               .width = 3,
+               .flags = CLK_DIVIDER_POWER_OF_TWO,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_axi_div",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_cpu_clk_axi = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .bit_idx = 18,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "cpu_clk_axi",
+               .ops = &clk_regmap_gate_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_axi_div" },
+               .num_parents = 1,
+               /*
+                * This clock is set by the ROM monitor code,
+                * Linux should not change it at runtime
+                */
+       },
+};
+
+static struct clk_regmap g12a_cpu_clk_trace_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .shift = 20,
+               .width = 3,
+               .flags = CLK_DIVIDER_POWER_OF_TWO,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cpu_clk_trace_div",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_cpu_clk_trace = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_SYS_CPU_CLK_CNTL1,
+               .bit_idx = 23,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "cpu_clk_trace",
+               .ops = &clk_regmap_gate_ro_ops,
+               .parent_names = (const char *[]){ "cpu_clk_trace_div" },
+               .num_parents = 1,
+               /*
+                * This clock is set by the ROM monitor code,
+                * Linux should not change it at runtime
+                */
+       },
+};
+
 static const struct pll_mult_range g12a_gp0_pll_mult_range = {
        .min = 55,
        .max = 255,
@@ -2167,6 +2479,26 @@ static struct clk_hw_onecell_data g12a_hw_onecell_data = {
                [CLKID_MALI]                    = &g12a_mali.hw,
                [CLKID_MPLL_5OM_DIV]            = &g12a_mpll_50m_div.hw,
                [CLKID_MPLL_5OM]                = &g12a_mpll_50m.hw,
+               [CLKID_SYS_PLL_DIV16_EN]        = &g12a_sys_pll_div16_en.hw,
+               [CLKID_SYS_PLL_DIV16]           = &g12a_sys_pll_div16.hw,
+               [CLKID_CPU_CLK_DYN0_SEL]        = &g12a_cpu_clk_premux0.hw,
+               [CLKID_CPU_CLK_DYN0_DIV]        = &g12a_cpu_clk_mux0_div.hw,
+               [CLKID_CPU_CLK_DYN0]            = &g12a_cpu_clk_postmux0.hw,
+               [CLKID_CPU_CLK_DYN1_SEL]        = &g12a_cpu_clk_premux1.hw,
+               [CLKID_CPU_CLK_DYN1_DIV]        = &g12a_cpu_clk_mux1_div.hw,
+               [CLKID_CPU_CLK_DYN1]            = &g12a_cpu_clk_postmux1.hw,
+               [CLKID_CPU_CLK_DYN]             = &g12a_cpu_clk_dyn.hw,
+               [CLKID_CPU_CLK]                 = &g12a_cpu_clk.hw,
+               [CLKID_CPU_CLK_DIV16_EN]        = &g12a_cpu_clk_div16_en.hw,
+               [CLKID_CPU_CLK_DIV16]           = &g12a_cpu_clk_div16.hw,
+               [CLKID_CPU_CLK_APB_DIV]         = &g12a_cpu_clk_apb_div.hw,
+               [CLKID_CPU_CLK_APB]             = &g12a_cpu_clk_apb.hw,
+               [CLKID_CPU_CLK_ATB_DIV]         = &g12a_cpu_clk_atb_div.hw,
+               [CLKID_CPU_CLK_ATB]             = &g12a_cpu_clk_atb.hw,
+               [CLKID_CPU_CLK_AXI_DIV]         = &g12a_cpu_clk_axi_div.hw,
+               [CLKID_CPU_CLK_AXI]             = &g12a_cpu_clk_axi.hw,
+               [CLKID_CPU_CLK_TRACE_DIV]       = &g12a_cpu_clk_trace_div.hw,
+               [CLKID_CPU_CLK_TRACE]           = &g12a_cpu_clk_trace.hw,
                [NR_CLKS]                       = NULL,
        },
        .num = NR_CLKS,
@@ -2335,6 +2667,24 @@ static struct clk_regmap *const g12a_clk_regmaps[] = {
        &g12a_mali_1,
        &g12a_mali,
        &g12a_mpll_50m,
+       &g12a_sys_pll_div16_en,
+       &g12a_cpu_clk_premux0,
+       &g12a_cpu_clk_mux0_div,
+       &g12a_cpu_clk_postmux0,
+       &g12a_cpu_clk_premux1,
+       &g12a_cpu_clk_mux1_div,
+       &g12a_cpu_clk_postmux1,
+       &g12a_cpu_clk_dyn,
+       &g12a_cpu_clk,
+       &g12a_cpu_clk_div16_en,
+       &g12a_cpu_clk_apb_div,
+       &g12a_cpu_clk_apb,
+       &g12a_cpu_clk_atb_div,
+       &g12a_cpu_clk_atb,
+       &g12a_cpu_clk_axi_div,
+       &g12a_cpu_clk_axi,
+       &g12a_cpu_clk_trace_div,
+       &g12a_cpu_clk_trace,
 };
 
 static const struct meson_eeclkc_data g12a_clkc_data = {
index f399dfe..70aa469 100644 (file)
@@ -50,6 +50,7 @@
 #define HHI_GCLK_MPEG2                 0x148
 #define HHI_GCLK_OTHER                 0x150
 #define HHI_GCLK_OTHER2                        0x154
+#define HHI_SYS_CPU_CLK_CNTL1          0x15c
 #define HHI_VID_CLK_DIV                        0x164
 #define HHI_MPEG_CLK_CNTL              0x174
 #define HHI_AUD_CLK_CNTL               0x178
 #define CLKID_MALI_0_DIV                       170
 #define CLKID_MALI_1_DIV                       173
 #define CLKID_MPLL_5OM_DIV                     176
+#define CLKID_SYS_PLL_DIV16_EN                 178
+#define CLKID_SYS_PLL_DIV16                    179
+#define CLKID_CPU_CLK_DYN0_SEL                 180
+#define CLKID_CPU_CLK_DYN0_DIV                 181
+#define CLKID_CPU_CLK_DYN0                     182
+#define CLKID_CPU_CLK_DYN1_SEL                 183
+#define CLKID_CPU_CLK_DYN1_DIV                 184
+#define CLKID_CPU_CLK_DYN1                     185
+#define CLKID_CPU_CLK_DYN                      186
+#define CLKID_CPU_CLK_DIV16_EN                 188
+#define CLKID_CPU_CLK_DIV16                    189
+#define CLKID_CPU_CLK_APB_DIV                  190
+#define CLKID_CPU_CLK_APB                      191
+#define CLKID_CPU_CLK_ATB_DIV                  192
+#define CLKID_CPU_CLK_ATB                      193
+#define CLKID_CPU_CLK_AXI_DIV                  194
+#define CLKID_CPU_CLK_AXI                      195
+#define CLKID_CPU_CLK_TRACE_DIV                        196
+#define CLKID_CPU_CLK_TRACE                    197
 
-#define NR_CLKS                                        178
+#define NR_CLKS                                        198
 
 /* include the CLKIDs that have been made part of the DT binding */
 #include <dt-bindings/clock/g12a-clkc.h>