273 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * r8a77970 Clock Pulse Generator / Module Standby and Software Reset4 *5 * Copyright (C) 2017-2018 Cogent Embedded Inc.6 *7 * Based on r8a7795-cpg-mssr.c8 *9 * Copyright (C) 2015 Glider bvba10 */11 12#include <linux/clk-provider.h>13#include <linux/device.h>14#include <linux/init.h>15#include <linux/kernel.h>16#include <linux/soc/renesas/rcar-rst.h>17 18#include <dt-bindings/clock/r8a77970-cpg-mssr.h>19 20#include "renesas-cpg-mssr.h"21#include "rcar-cpg-lib.h"22#include "rcar-gen3-cpg.h"23 24#define CPG_SD0CKCR 0x007425 26enum r8a77970_clk_types {27 CLK_TYPE_R8A77970_SD0H = CLK_TYPE_GEN3_SOC_BASE,28 CLK_TYPE_R8A77970_SD0,29};30 31enum clk_ids {32 /* Core Clock Outputs exported to DT */33 LAST_DT_CORE_CLK = R8A77970_CLK_OSC,34 35 /* External Input Clocks */36 CLK_EXTAL,37 CLK_EXTALR,38 39 /* Internal Core Clocks */40 CLK_MAIN,41 CLK_PLL0,42 CLK_PLL1,43 CLK_PLL3,44 CLK_PLL1_DIV2,45 CLK_PLL1_DIV4,46 47 /* Module Clocks */48 MOD_CLK_BASE49};50 51static const struct clk_div_table cpg_sd0h_div_table[] = {52 { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 },53 { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },54 { 8, 24 }, { 10, 36 }, { 11, 48 }, { 0, 0 },55};56 57static const struct clk_div_table cpg_sd0_div_table[] = {58 { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },59 { 8, 24 }, { 10, 36 }, { 11, 48 }, { 12, 10 },60 { 0, 0 },61};62 63static const struct cpg_core_clk r8a77970_core_clks[] __initconst = {64 /* External Clock Inputs */65 DEF_INPUT("extal", CLK_EXTAL),66 DEF_INPUT("extalr", CLK_EXTALR),67 68 /* Internal Core Clocks */69 DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),70 DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN),71 DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),72 DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),73 74 DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),75 DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1),76 77 /* Core Clock Outputs */78 DEF_FIXED("z2", R8A77970_CLK_Z2, CLK_PLL1_DIV4, 1, 1),79 DEF_FIXED("ztr", R8A77970_CLK_ZTR, CLK_PLL1_DIV2, 6, 1),80 DEF_FIXED("ztrd2", R8A77970_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),81 DEF_FIXED("zt", R8A77970_CLK_ZT, CLK_PLL1_DIV2, 4, 1),82 DEF_FIXED("zx", R8A77970_CLK_ZX, CLK_PLL1_DIV2, 3, 1),83 DEF_FIXED("s1d1", R8A77970_CLK_S1D1, CLK_PLL1_DIV2, 4, 1),84 DEF_FIXED("s1d2", R8A77970_CLK_S1D2, CLK_PLL1_DIV2, 8, 1),85 DEF_FIXED("s1d4", R8A77970_CLK_S1D4, CLK_PLL1_DIV2, 16, 1),86 DEF_FIXED("s2d1", R8A77970_CLK_S2D1, CLK_PLL1_DIV2, 6, 1),87 DEF_FIXED("s2d2", R8A77970_CLK_S2D2, CLK_PLL1_DIV2, 12, 1),88 DEF_FIXED("s2d4", R8A77970_CLK_S2D4, CLK_PLL1_DIV2, 24, 1),89 90 DEF_BASE("sd0h", R8A77970_CLK_SD0H, CLK_TYPE_R8A77970_SD0H,91 CLK_PLL1_DIV2),92 DEF_BASE("sd0", R8A77970_CLK_SD0, CLK_TYPE_R8A77970_SD0, CLK_PLL1_DIV2),93 94 DEF_FIXED("rpc", R8A77970_CLK_RPC, CLK_PLL1_DIV2, 5, 1),95 DEF_FIXED("rpcd2", R8A77970_CLK_RPCD2, CLK_PLL1_DIV2, 10, 1),96 97 DEF_FIXED("cl", R8A77970_CLK_CL, CLK_PLL1_DIV2, 48, 1),98 DEF_FIXED("cp", R8A77970_CLK_CP, CLK_EXTAL, 2, 1),99 DEF_FIXED("cpex", R8A77970_CLK_CPEX, CLK_EXTAL, 2, 1),100 101 DEF_DIV6P1("canfd", R8A77970_CLK_CANFD, CLK_PLL1_DIV4, 0x244),102 DEF_DIV6P1("mso", R8A77970_CLK_MSO, CLK_PLL1_DIV4, 0x014),103 DEF_DIV6P1("csi0", R8A77970_CLK_CSI0, CLK_PLL1_DIV4, 0x00c),104 105 DEF_FIXED("osc", R8A77970_CLK_OSC, CLK_PLL1_DIV2, 12*1024, 1),106 DEF_FIXED("r", R8A77970_CLK_R, CLK_EXTALR, 1, 1),107};108 109static const struct mssr_mod_clk r8a77970_mod_clks[] __initconst = {110 DEF_MOD("tmu4", 121, R8A77970_CLK_S2D2),111 DEF_MOD("tmu3", 122, R8A77970_CLK_S2D2),112 DEF_MOD("tmu2", 123, R8A77970_CLK_S2D2),113 DEF_MOD("tmu1", 124, R8A77970_CLK_S2D2),114 DEF_MOD("tmu0", 125, R8A77970_CLK_CP),115 DEF_MOD("ivcp1e", 127, R8A77970_CLK_S2D1),116 DEF_MOD("scif4", 203, R8A77970_CLK_S2D4),117 DEF_MOD("scif3", 204, R8A77970_CLK_S2D4),118 DEF_MOD("scif1", 206, R8A77970_CLK_S2D4),119 DEF_MOD("scif0", 207, R8A77970_CLK_S2D4),120 DEF_MOD("msiof3", 208, R8A77970_CLK_MSO),121 DEF_MOD("msiof2", 209, R8A77970_CLK_MSO),122 DEF_MOD("msiof1", 210, R8A77970_CLK_MSO),123 DEF_MOD("msiof0", 211, R8A77970_CLK_MSO),124 DEF_MOD("mfis", 213, R8A77970_CLK_S2D2),125 DEF_MOD("sys-dmac2", 217, R8A77970_CLK_S2D1),126 DEF_MOD("sys-dmac1", 218, R8A77970_CLK_S2D1),127 DEF_MOD("cmt3", 300, R8A77970_CLK_R),128 DEF_MOD("cmt2", 301, R8A77970_CLK_R),129 DEF_MOD("cmt1", 302, R8A77970_CLK_R),130 DEF_MOD("cmt0", 303, R8A77970_CLK_R),131 DEF_MOD("tpu0", 304, R8A77970_CLK_S2D4),132 DEF_MOD("sd-if", 314, R8A77970_CLK_SD0),133 DEF_MOD("rwdt", 402, R8A77970_CLK_R),134 DEF_MOD("intc-ex", 407, R8A77970_CLK_CP),135 DEF_MOD("intc-ap", 408, R8A77970_CLK_S2D1),136 DEF_MOD("hscif3", 517, R8A77970_CLK_S2D1),137 DEF_MOD("hscif2", 518, R8A77970_CLK_S2D1),138 DEF_MOD("hscif1", 519, R8A77970_CLK_S2D1),139 DEF_MOD("hscif0", 520, R8A77970_CLK_S2D1),140 DEF_MOD("thermal", 522, R8A77970_CLK_CP),141 DEF_MOD("pwm", 523, R8A77970_CLK_S2D4),142 DEF_MOD("fcpvd0", 603, R8A77970_CLK_S2D1),143 DEF_MOD("vspd0", 623, R8A77970_CLK_S2D1),144 DEF_MOD("csi40", 716, R8A77970_CLK_CSI0),145 DEF_MOD("du0", 724, R8A77970_CLK_S2D1),146 DEF_MOD("lvds", 727, R8A77970_CLK_S2D1),147 DEF_MOD("vin3", 808, R8A77970_CLK_S2D1),148 DEF_MOD("vin2", 809, R8A77970_CLK_S2D1),149 DEF_MOD("vin1", 810, R8A77970_CLK_S2D1),150 DEF_MOD("vin0", 811, R8A77970_CLK_S2D1),151 DEF_MOD("etheravb", 812, R8A77970_CLK_S2D2),152 DEF_MOD("gpio5", 907, R8A77970_CLK_CP),153 DEF_MOD("gpio4", 908, R8A77970_CLK_CP),154 DEF_MOD("gpio3", 909, R8A77970_CLK_CP),155 DEF_MOD("gpio2", 910, R8A77970_CLK_CP),156 DEF_MOD("gpio1", 911, R8A77970_CLK_CP),157 DEF_MOD("gpio0", 912, R8A77970_CLK_CP),158 DEF_MOD("can-fd", 914, R8A77970_CLK_S2D2),159 DEF_MOD("rpc-if", 917, R8A77970_CLK_RPC),160 DEF_MOD("i2c4", 927, R8A77970_CLK_S2D2),161 DEF_MOD("i2c3", 928, R8A77970_CLK_S2D2),162 DEF_MOD("i2c2", 929, R8A77970_CLK_S2D2),163 DEF_MOD("i2c1", 930, R8A77970_CLK_S2D2),164 DEF_MOD("i2c0", 931, R8A77970_CLK_S2D2),165};166 167static const unsigned int r8a77970_crit_mod_clks[] __initconst = {168 MOD_CLK_ID(402), /* RWDT */169 MOD_CLK_ID(408), /* INTC-AP (GIC) */170};171 172/*173 * CPG Clock Data174 */175 176/*177 * MD EXTAL PLL0 PLL1 PLL3178 * 14 13 19 (MHz)179 *-------------------------------------------------180 * 0 0 0 16.66 x 1 x192 x192 x96181 * 0 0 1 16.66 x 1 x192 x192 x80182 * 0 1 0 20 x 1 x160 x160 x80183 * 0 1 1 20 x 1 x160 x160 x66184 * 1 0 0 27 / 2 x236 x236 x118185 * 1 0 1 27 / 2 x236 x236 x98186 * 1 1 0 33.33 / 2 x192 x192 x96187 * 1 1 1 33.33 / 2 x192 x192 x80188 */189#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \190 (((md) & BIT(13)) >> 12) | \191 (((md) & BIT(19)) >> 19))192 193static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[8] __initconst = {194 /* EXTAL div PLL1 mult/div PLL3 mult/div */195 { 1, 192, 1, 96, 1, },196 { 1, 192, 1, 80, 1, },197 { 1, 160, 1, 80, 1, },198 { 1, 160, 1, 66, 1, },199 { 2, 236, 1, 118, 1, },200 { 2, 236, 1, 98, 1, },201 { 2, 192, 1, 96, 1, },202 { 2, 192, 1, 80, 1, },203};204 205static int __init r8a77970_cpg_mssr_init(struct device *dev)206{207 const struct rcar_gen3_cpg_pll_config *cpg_pll_config;208 u32 cpg_mode;209 int error;210 211 error = rcar_rst_read_mode_pins(&cpg_mode);212 if (error)213 return error;214 215 cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];216 217 return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);218}219 220static struct clk * __init r8a77970_cpg_clk_register(struct device *dev,221 const struct cpg_core_clk *core, const struct cpg_mssr_info *info,222 struct clk **clks, void __iomem *base,223 struct raw_notifier_head *notifiers)224{225 const struct clk_div_table *table;226 const struct clk *parent;227 unsigned int shift;228 229 switch (core->type) {230 case CLK_TYPE_R8A77970_SD0H:231 table = cpg_sd0h_div_table;232 shift = 8;233 break;234 case CLK_TYPE_R8A77970_SD0:235 table = cpg_sd0_div_table;236 shift = 4;237 break;238 default:239 return rcar_gen3_cpg_clk_register(dev, core, info, clks, base,240 notifiers);241 }242 243 parent = clks[core->parent];244 if (IS_ERR(parent))245 return ERR_CAST(parent);246 247 return clk_register_divider_table(NULL, core->name,248 __clk_get_name(parent), 0,249 base + CPG_SD0CKCR,250 shift, 4, 0, table, &cpg_lock);251}252 253const struct cpg_mssr_info r8a77970_cpg_mssr_info __initconst = {254 /* Core Clocks */255 .core_clks = r8a77970_core_clks,256 .num_core_clks = ARRAY_SIZE(r8a77970_core_clks),257 .last_dt_core_clk = LAST_DT_CORE_CLK,258 .num_total_core_clks = MOD_CLK_BASE,259 260 /* Module Clocks */261 .mod_clks = r8a77970_mod_clks,262 .num_mod_clks = ARRAY_SIZE(r8a77970_mod_clks),263 .num_hw_mod_clks = 12 * 32,264 265 /* Critical Module Clocks */266 .crit_mod_clks = r8a77970_crit_mod_clks,267 .num_crit_mod_clks = ARRAY_SIZE(r8a77970_crit_mod_clks),268 269 /* Callbacks */270 .init = r8a77970_cpg_mssr_init,271 .cpg_clk_register = r8a77970_cpg_clk_register,272};273