| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * r8a77970 Clock Pulse Generator / Module Standby and Software Reset |
|---|
| 3 | 4 | * |
|---|
| 4 | | - * Copyright (C) 2017 Cogent Embedded Inc. |
|---|
| 5 | + * Copyright (C) 2017-2018 Cogent Embedded Inc. |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * Based on r8a7795-cpg-mssr.c |
|---|
| 7 | 8 | * |
|---|
| 8 | 9 | * Copyright (C) 2015 Glider bvba |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 11 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 12 | | - * the Free Software Foundation; version 2 of the License. |
|---|
| 13 | 10 | */ |
|---|
| 14 | 11 | |
|---|
| 12 | +#include <linux/clk-provider.h> |
|---|
| 15 | 13 | #include <linux/device.h> |
|---|
| 16 | 14 | #include <linux/init.h> |
|---|
| 17 | 15 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 21 | 19 | |
|---|
| 22 | 20 | #include "renesas-cpg-mssr.h" |
|---|
| 23 | 21 | #include "rcar-gen3-cpg.h" |
|---|
| 22 | + |
|---|
| 23 | +#define CPG_SD0CKCR 0x0074 |
|---|
| 24 | + |
|---|
| 25 | +enum r8a77970_clk_types { |
|---|
| 26 | + CLK_TYPE_R8A77970_SD0H = CLK_TYPE_GEN3_SOC_BASE, |
|---|
| 27 | + CLK_TYPE_R8A77970_SD0, |
|---|
| 28 | +}; |
|---|
| 24 | 29 | |
|---|
| 25 | 30 | enum clk_ids { |
|---|
| 26 | 31 | /* Core Clock Outputs exported to DT */ |
|---|
| .. | .. |
|---|
| 40 | 45 | |
|---|
| 41 | 46 | /* Module Clocks */ |
|---|
| 42 | 47 | MOD_CLK_BASE |
|---|
| 48 | +}; |
|---|
| 49 | + |
|---|
| 50 | +static spinlock_t cpg_lock; |
|---|
| 51 | + |
|---|
| 52 | +static const struct clk_div_table cpg_sd0h_div_table[] = { |
|---|
| 53 | + { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, |
|---|
| 54 | + { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 }, |
|---|
| 55 | + { 8, 24 }, { 10, 36 }, { 11, 48 }, { 0, 0 }, |
|---|
| 56 | +}; |
|---|
| 57 | + |
|---|
| 58 | +static const struct clk_div_table cpg_sd0_div_table[] = { |
|---|
| 59 | + { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 }, |
|---|
| 60 | + { 8, 24 }, { 10, 36 }, { 11, 48 }, { 12, 10 }, |
|---|
| 61 | + { 0, 0 }, |
|---|
| 43 | 62 | }; |
|---|
| 44 | 63 | |
|---|
| 45 | 64 | static const struct cpg_core_clk r8a77970_core_clks[] __initconst = { |
|---|
| .. | .. |
|---|
| 68 | 87 | DEF_FIXED("s2d2", R8A77970_CLK_S2D2, CLK_PLL1_DIV2, 12, 1), |
|---|
| 69 | 88 | DEF_FIXED("s2d4", R8A77970_CLK_S2D4, CLK_PLL1_DIV2, 24, 1), |
|---|
| 70 | 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 | + |
|---|
| 71 | 97 | DEF_FIXED("cl", R8A77970_CLK_CL, CLK_PLL1_DIV2, 48, 1), |
|---|
| 72 | 98 | DEF_FIXED("cp", R8A77970_CLK_CP, CLK_EXTAL, 2, 1), |
|---|
| 99 | + DEF_FIXED("cpex", R8A77970_CLK_CPEX, CLK_EXTAL, 2, 1), |
|---|
| 73 | 100 | |
|---|
| 74 | 101 | DEF_DIV6P1("canfd", R8A77970_CLK_CANFD, CLK_PLL1_DIV4, 0x244), |
|---|
| 75 | 102 | DEF_DIV6P1("mso", R8A77970_CLK_MSO, CLK_PLL1_DIV4, 0x014), |
|---|
| .. | .. |
|---|
| 80 | 107 | }; |
|---|
| 81 | 108 | |
|---|
| 82 | 109 | static 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), |
|---|
| 83 | 115 | DEF_MOD("ivcp1e", 127, R8A77970_CLK_S2D1), |
|---|
| 84 | 116 | DEF_MOD("scif4", 203, R8A77970_CLK_S2D4), |
|---|
| 85 | 117 | DEF_MOD("scif3", 204, R8A77970_CLK_S2D4), |
|---|
| .. | .. |
|---|
| 92 | 124 | DEF_MOD("mfis", 213, R8A77970_CLK_S2D2), |
|---|
| 93 | 125 | DEF_MOD("sys-dmac2", 217, R8A77970_CLK_S2D1), |
|---|
| 94 | 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), |
|---|
| 95 | 133 | DEF_MOD("rwdt", 402, R8A77970_CLK_R), |
|---|
| 96 | 134 | DEF_MOD("intc-ex", 407, R8A77970_CLK_CP), |
|---|
| 97 | 135 | DEF_MOD("intc-ap", 408, R8A77970_CLK_S2D1), |
|---|
| .. | .. |
|---|
| 118 | 156 | DEF_MOD("gpio1", 911, R8A77970_CLK_CP), |
|---|
| 119 | 157 | DEF_MOD("gpio0", 912, R8A77970_CLK_CP), |
|---|
| 120 | 158 | DEF_MOD("can-fd", 914, R8A77970_CLK_S2D2), |
|---|
| 159 | + DEF_MOD("rpc-if", 917, R8A77970_CLK_RPC), |
|---|
| 121 | 160 | DEF_MOD("i2c4", 927, R8A77970_CLK_S2D2), |
|---|
| 122 | 161 | DEF_MOD("i2c3", 928, R8A77970_CLK_S2D2), |
|---|
| 123 | 162 | DEF_MOD("i2c2", 929, R8A77970_CLK_S2D2), |
|---|
| .. | .. |
|---|
| 126 | 165 | }; |
|---|
| 127 | 166 | |
|---|
| 128 | 167 | static const unsigned int r8a77970_crit_mod_clks[] __initconst = { |
|---|
| 168 | + MOD_CLK_ID(402), /* RWDT */ |
|---|
| 129 | 169 | MOD_CLK_ID(408), /* INTC-AP (GIC) */ |
|---|
| 130 | 170 | }; |
|---|
| 131 | | - |
|---|
| 132 | 171 | |
|---|
| 133 | 172 | /* |
|---|
| 134 | 173 | * CPG Clock Data |
|---|
| .. | .. |
|---|
| 173 | 212 | if (error) |
|---|
| 174 | 213 | return error; |
|---|
| 175 | 214 | |
|---|
| 215 | + spin_lock_init(&cpg_lock); |
|---|
| 216 | + |
|---|
| 176 | 217 | cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; |
|---|
| 177 | 218 | |
|---|
| 178 | 219 | return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode); |
|---|
| 220 | +} |
|---|
| 221 | + |
|---|
| 222 | +static struct clk * __init r8a77970_cpg_clk_register(struct device *dev, |
|---|
| 223 | + const struct cpg_core_clk *core, const struct cpg_mssr_info *info, |
|---|
| 224 | + struct clk **clks, void __iomem *base, |
|---|
| 225 | + struct raw_notifier_head *notifiers) |
|---|
| 226 | +{ |
|---|
| 227 | + const struct clk_div_table *table; |
|---|
| 228 | + const struct clk *parent; |
|---|
| 229 | + unsigned int shift; |
|---|
| 230 | + |
|---|
| 231 | + switch (core->type) { |
|---|
| 232 | + case CLK_TYPE_R8A77970_SD0H: |
|---|
| 233 | + table = cpg_sd0h_div_table; |
|---|
| 234 | + shift = 8; |
|---|
| 235 | + break; |
|---|
| 236 | + case CLK_TYPE_R8A77970_SD0: |
|---|
| 237 | + table = cpg_sd0_div_table; |
|---|
| 238 | + shift = 4; |
|---|
| 239 | + break; |
|---|
| 240 | + default: |
|---|
| 241 | + return rcar_gen3_cpg_clk_register(dev, core, info, clks, base, |
|---|
| 242 | + notifiers); |
|---|
| 243 | + } |
|---|
| 244 | + |
|---|
| 245 | + parent = clks[core->parent]; |
|---|
| 246 | + if (IS_ERR(parent)) |
|---|
| 247 | + return ERR_CAST(parent); |
|---|
| 248 | + |
|---|
| 249 | + return clk_register_divider_table(NULL, core->name, |
|---|
| 250 | + __clk_get_name(parent), 0, |
|---|
| 251 | + base + CPG_SD0CKCR, |
|---|
| 252 | + shift, 4, 0, table, &cpg_lock); |
|---|
| 179 | 253 | } |
|---|
| 180 | 254 | |
|---|
| 181 | 255 | const struct cpg_mssr_info r8a77970_cpg_mssr_info __initconst = { |
|---|
| .. | .. |
|---|
| 196 | 270 | |
|---|
| 197 | 271 | /* Callbacks */ |
|---|
| 198 | 272 | .init = r8a77970_cpg_mssr_init, |
|---|
| 199 | | - .cpg_clk_register = rcar_gen3_cpg_clk_register, |
|---|
| 273 | + .cpg_clk_register = r8a77970_cpg_clk_register, |
|---|
| 200 | 274 | }; |
|---|