Add the RPCSRC internal clock on R-Car V3H (R8A77980) -- it's 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. Add the RPC[D2] clocks (derived from this internal clock) and the RPC-IF module clock as well... Signed-off-by: Sergei Shtylyov <sergei.shtylyov@xxxxxxxxxxxxxxxxxx> --- drivers/clk/renesas/r8a77980-cpg-mssr.c | 40 +++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) Index: renesas-drivers/drivers/clk/renesas/r8a77980-cpg-mssr.c =================================================================== --- renesas-drivers.orig/drivers/clk/renesas/r8a77980-cpg-mssr.c +++ renesas-drivers/drivers/clk/renesas/r8a77980-cpg-mssr.c @@ -10,6 +10,7 @@ * Copyright (C) 2015 Glider bvba */ +#include <linux/clk-provider.h> #include <linux/device.h> #include <linux/init.h> #include <linux/kernel.h> @@ -21,6 +22,10 @@ #include "renesas-cpg-mssr.h" #include "rcar-gen3-cpg.h" +enum r8a77980_clk_types { + CLK_TYPE_R8A77980_RPCSRC = CLK_TYPE_GEN3_SOC_BASE, +}; + enum clk_ids { /* Core Clock Outputs exported to DT */ LAST_DT_CORE_CLK = R8A77980_CLK_OSC, @@ -41,12 +46,17 @@ enum clk_ids { CLK_S2, CLK_S3, CLK_SDSRC, + CLK_RPCSRC, CLK_OCO, /* Module Clocks */ MOD_CLK_BASE }; +static const struct clk_div_table cpg_rpcsrc_div_table[] = { + { 2, 5 }, { 3, 6 }, { 0, 0 }, +}; + static const struct cpg_core_clk r8a77980_core_clks[] __initconst = { /* External Clock Inputs */ DEF_INPUT("extal", CLK_EXTAL), @@ -65,8 +75,14 @@ static const struct cpg_core_clk r8a7798 DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), + DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_R8A77980_RPCSRC, CLK_PLL1), DEF_RATE(".oco", CLK_OCO, 32768), + DEF_BASE("rpc", R8A77980_CLK_RPC, CLK_TYPE_GEN3_RPC, + CLK_RPCSRC), + DEF_BASE("rpcd2", R8A77980_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, + R8A77980_CLK_RPC), + /* Core Clock Outputs */ DEF_FIXED("ztr", R8A77980_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), DEF_FIXED("ztrd2", R8A77980_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1), @@ -164,6 +180,7 @@ static const struct mssr_mod_clk r8a7798 DEF_MOD("gpio1", 911, R8A77980_CLK_CP), DEF_MOD("gpio0", 912, R8A77980_CLK_CP), DEF_MOD("can-fd", 914, R8A77980_CLK_S3D2), + DEF_MOD("rpc-if", 917, R8A77980_CLK_RPC), DEF_MOD("i2c4", 927, R8A77980_CLK_S0D6), DEF_MOD("i2c3", 928, R8A77980_CLK_S0D6), DEF_MOD("i2c2", 929, R8A77980_CLK_S3D2), @@ -215,6 +232,27 @@ static int __init r8a77980_cpg_mssr_init return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode); } +static struct clk * __init r8a77980_cpg_clk_register(struct device *dev, + const struct cpg_core_clk *core, const struct cpg_mssr_info *info, + struct clk **clks, void __iomem *base, + struct raw_notifier_head *notifiers) +{ + if (core->type == CLK_TYPE_R8A77980_RPCSRC) { + const struct clk *parent = clks[core->parent]; + + if (IS_ERR(parent)) + return ERR_CAST(parent); + + return clk_register_divider_table(NULL, core->name, + __clk_get_name(parent), 0, + base + CPG_RPCCKCR, 3, 2, 0, + cpg_rpcsrc_div_table, NULL); + } else { + return rcar_gen3_cpg_clk_register(dev, core, info, clks, base, + notifiers); + } +} + const struct cpg_mssr_info r8a77980_cpg_mssr_info __initconst = { /* Core Clocks */ .core_clks = r8a77980_core_clks, @@ -233,5 +271,5 @@ const struct cpg_mssr_info r8a77980_cpg_ /* Callbacks */ .init = r8a77980_cpg_mssr_init, - .cpg_clk_register = rcar_gen3_cpg_clk_register, + .cpg_clk_register = r8a77980_cpg_clk_register, };