diff options
Diffstat (limited to 'bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0275-clk-renesas-rcar-gen3-Add-RPC-clocks.patch')
-rw-r--r-- | bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0275-clk-renesas-rcar-gen3-Add-RPC-clocks.patch | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0275-clk-renesas-rcar-gen3-Add-RPC-clocks.patch b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0275-clk-renesas-rcar-gen3-Add-RPC-clocks.patch new file mode 100644 index 00000000..813e0c27 --- /dev/null +++ b/bsp/meta-rcar/meta-rcar-gen3-adas/recipes-kernel/linux/linux-renesas/0275-clk-renesas-rcar-gen3-Add-RPC-clocks.patch @@ -0,0 +1,169 @@ +From c4d21aa145e4a995725af98d273eb33f63013082 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> +Date: Tue, 22 Jan 2019 22:59:35 +0300 +Subject: [PATCH 095/211] clk: renesas: rcar-gen3: Add RPC clocks + +The RPCSRC internal clock is controlled by the RPCCKCR.DIV[4:3] on all +the R-Car gen3 SoCs except V3M (R8A77970) but the encoding of this field +is different between SoCs; it makes sense to support the most common case +of this encoding in the R-Car gen3 CPG driver... + +After adding the RPCSRC clock, we can add the RPC[D2] clocks derived from +it and controlled by the RPCCKCR register on all the R-Car gen3 SoCs except +V3M (R8A77970); the composite clock driver seems handy for this task, using +the spinlock added in the previous patch... + +Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> +Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> +(cherry picked from commit db4a0073cc82a95d8d1a9b05fde82355fcce77d8) +[valentine.barshak: resolved minor conflicts] +Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com> +--- + drivers/clk/renesas/rcar-gen3-cpg.c | 101 ++++++++++++++++++++++++++++++++++++ + drivers/clk/renesas/rcar-gen3-cpg.h | 4 ++ + 2 files changed, 105 insertions(+) + +diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c +index 8e41380..c73b269 100644 +--- a/drivers/clk/renesas/rcar-gen3-cpg.c ++++ b/drivers/clk/renesas/rcar-gen3-cpg.c +@@ -720,6 +720,92 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, + return clk; + } + ++struct rpc_clock { ++ struct clk_divider div; ++ struct clk_gate gate; ++ /* ++ * One notifier covers both RPC and RPCD2 clocks as they are both ++ * controlled by the same RPCCKCR register... ++ */ ++ struct cpg_simple_notifier csn; ++}; ++ ++static const struct clk_div_table cpg_rpcsrc_div_table[] = { ++ { 2, 5 }, { 3, 6 }, { 0, 0 }, ++}; ++ ++static const struct clk_div_table cpg_rpc_div_table[] = { ++ { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 }, { 0, 0 }, ++}; ++ ++static struct clk * __init cpg_rpc_clk_register(const char *name, ++ void __iomem *base, const char *parent_name, ++ struct raw_notifier_head *notifiers) ++{ ++ struct rpc_clock *rpc; ++ struct clk *clk; ++ ++ rpc = kzalloc(sizeof(*rpc), GFP_KERNEL); ++ if (!rpc) ++ return ERR_PTR(-ENOMEM); ++ ++ rpc->div.reg = base + CPG_RPCCKCR; ++ rpc->div.width = 3; ++ rpc->div.table = cpg_rpc_div_table; ++ rpc->div.lock = &cpg_lock; ++ ++ rpc->gate.reg = base + CPG_RPCCKCR; ++ rpc->gate.bit_idx = 8; ++ rpc->gate.flags = CLK_GATE_SET_TO_DISABLE; ++ rpc->gate.lock = &cpg_lock; ++ ++ rpc->csn.reg = base + CPG_RPCCKCR; ++ ++ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL, ++ &rpc->div.hw, &clk_divider_ops, ++ &rpc->gate.hw, &clk_gate_ops, 0); ++ if (IS_ERR(clk)) { ++ kfree(rpc); ++ return clk; ++ } ++ ++ cpg_simple_notifier_register(notifiers, &rpc->csn); ++ return clk; ++} ++ ++struct rpcd2_clock { ++ struct clk_fixed_factor fixed; ++ struct clk_gate gate; ++}; ++ ++static struct clk * __init cpg_rpcd2_clk_register(const char *name, ++ void __iomem *base, ++ const char *parent_name) ++{ ++ struct rpcd2_clock *rpcd2; ++ struct clk *clk; ++ ++ rpcd2 = kzalloc(sizeof(*rpcd2), GFP_KERNEL); ++ if (!rpcd2) ++ return ERR_PTR(-ENOMEM); ++ ++ rpcd2->fixed.mult = 1; ++ rpcd2->fixed.div = 2; ++ ++ rpcd2->gate.reg = base + CPG_RPCCKCR; ++ rpcd2->gate.bit_idx = 9; ++ rpcd2->gate.flags = CLK_GATE_SET_TO_DISABLE; ++ rpcd2->gate.lock = &cpg_lock; ++ ++ clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL, ++ &rpcd2->fixed.hw, &clk_fixed_factor_ops, ++ &rpcd2->gate.hw, &clk_gate_ops, 0); ++ if (IS_ERR(clk)) ++ kfree(rpcd2); ++ ++ return clk; ++} ++ + static const struct rcar_gen3_cpg_pll_config *cpg_pll_config __initdata; + static unsigned int cpg_clk_extalr __initdata; + static u32 cpg_mode __initdata; +@@ -896,6 +982,21 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, + return cpg_zg_clk_register(core->name, __clk_get_name(parent), + base, core->div); + ++ case CLK_TYPE_GEN3_RPCSRC: ++ return clk_register_divider_table(NULL, core->name, ++ __clk_get_name(parent), 0, ++ base + CPG_RPCCKCR, 3, 2, 0, ++ cpg_rpcsrc_div_table, ++ &cpg_lock); ++ ++ case CLK_TYPE_GEN3_RPC: ++ return cpg_rpc_clk_register(core->name, base, ++ __clk_get_name(parent), notifiers); ++ ++ case CLK_TYPE_GEN3_RPCD2: ++ return cpg_rpcd2_clk_register(core->name, base, ++ __clk_get_name(parent)); ++ + default: + return ERR_PTR(-EINVAL); + } +diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h +index 8834afe..a39c11a 100644 +--- a/drivers/clk/renesas/rcar-gen3-cpg.h ++++ b/drivers/clk/renesas/rcar-gen3-cpg.h +@@ -27,6 +27,9 @@ enum rcar_gen3_clk_types { + CLK_TYPE_GEN3_ZG, + CLK_TYPE_GEN3_OSC, /* OSC EXTAL predivider and fixed divider */ + CLK_TYPE_GEN3_RCKSEL, /* Select parent/divider using RCKCR.CKSEL */ ++ CLK_TYPE_GEN3_RPCSRC, ++ CLK_TYPE_GEN3_RPC, ++ CLK_TYPE_GEN3_RPCD2, + + /* SoC specific definitions start here */ + CLK_TYPE_GEN3_SOC_BASE, +@@ -64,6 +67,7 @@ struct rcar_gen3_cpg_pll_config { + u8 osc_prediv; + }; + ++#define CPG_RPCCKCR 0x238 + #define CPG_RCKCR 0x240 + + struct clk *rcar_gen3_cpg_clk_register(struct device *dev, +-- +2.7.4 + |