1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Renesas RCar Gen3 CPG MSSR driver 4 * 5 * Copyright (C) 2017 Marek Vasut <marek.vasut@gmail.com> 6 * 7 * Based on the following driver from Linux kernel: 8 * r8a7796 Clock Pulse Generator / Module Standby and Software Reset 9 * 10 * Copyright (C) 2016 Glider bvba 11 */ 12 13 #include <common.h> 14 #include <clk-uclass.h> 15 #include <dm.h> 16 #include <errno.h> 17 #include <wait_bit.h> 18 #include <asm/io.h> 19 20 #include <dt-bindings/clock/renesas-cpg-mssr.h> 21 22 #include "renesas-cpg-mssr.h" 23 #include "rcar-gen3-cpg.h" 24 25 #define CPG_RST_MODEMR 0x0060 26 27 #define CPG_PLL0CR 0x00d8 28 #define CPG_PLL2CR 0x002c 29 #define CPG_PLL4CR 0x01f4 30 31 #define CPG_RPC_PREDIV_MASK 0x3 32 #define CPG_RPC_PREDIV_OFFSET 3 33 #define CPG_RPC_POSTDIV_MASK 0x7 34 #define CPG_RPC_POSTDIV_OFFSET 0 35 36 /* 37 * SDn Clock 38 */ 39 #define CPG_SD_STP_HCK BIT(9) 40 #define CPG_SD_STP_CK BIT(8) 41 42 #define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK) 43 #define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0) 44 45 #define CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) \ 46 { \ 47 .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \ 48 ((stp_ck) ? CPG_SD_STP_CK : 0) | \ 49 ((sd_srcfc) << 2) | \ 50 ((sd_fc) << 0), \ 51 .div = (sd_div), \ 52 } 53 54 struct sd_div_table { 55 u32 val; 56 unsigned int div; 57 }; 58 59 /* SDn divider 60 * sd_srcfc sd_fc div 61 * stp_hck stp_ck (div) (div) = sd_srcfc x sd_fc 62 *------------------------------------------------------------------- 63 * 0 0 0 (1) 1 (4) 4 64 * 0 0 1 (2) 1 (4) 8 65 * 1 0 2 (4) 1 (4) 16 66 * 1 0 3 (8) 1 (4) 32 67 * 1 0 4 (16) 1 (4) 64 68 * 0 0 0 (1) 0 (2) 2 69 * 0 0 1 (2) 0 (2) 4 70 * 1 0 2 (4) 0 (2) 8 71 * 1 0 3 (8) 0 (2) 16 72 * 1 0 4 (16) 0 (2) 32 73 */ 74 static const struct sd_div_table cpg_sd_div_table[] = { 75 /* CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) */ 76 CPG_SD_DIV_TABLE_DATA(0, 0, 0, 1, 4), 77 CPG_SD_DIV_TABLE_DATA(0, 0, 1, 1, 8), 78 CPG_SD_DIV_TABLE_DATA(1, 0, 2, 1, 16), 79 CPG_SD_DIV_TABLE_DATA(1, 0, 3, 1, 32), 80 CPG_SD_DIV_TABLE_DATA(1, 0, 4, 1, 64), 81 CPG_SD_DIV_TABLE_DATA(0, 0, 0, 0, 2), 82 CPG_SD_DIV_TABLE_DATA(0, 0, 1, 0, 4), 83 CPG_SD_DIV_TABLE_DATA(1, 0, 2, 0, 8), 84 CPG_SD_DIV_TABLE_DATA(1, 0, 3, 0, 16), 85 CPG_SD_DIV_TABLE_DATA(1, 0, 4, 0, 32), 86 }; 87 88 static int gen3_clk_setup_sdif_div(struct clk *clk) 89 { 90 struct gen3_clk_priv *priv = dev_get_priv(clk->dev); 91 struct cpg_mssr_info *info = priv->info; 92 const struct cpg_core_clk *core; 93 struct clk parent; 94 int ret; 95 96 ret = renesas_clk_get_parent(clk, info, &parent); 97 if (ret) { 98 printf("%s[%i] parent fail, ret=%i\n", __func__, __LINE__, ret); 99 return ret; 100 } 101 102 if (renesas_clk_is_mod(&parent)) 103 return 0; 104 105 ret = renesas_clk_get_core(&parent, info, &core); 106 if (ret) 107 return ret; 108 109 if (core->type != CLK_TYPE_GEN3_SD) 110 return 0; 111 112 debug("%s[%i] SDIF offset=%x\n", __func__, __LINE__, core->offset); 113 114 writel(1, priv->base + core->offset); 115 116 return 0; 117 } 118 119 static int gen3_clk_enable(struct clk *clk) 120 { 121 struct gen3_clk_priv *priv = dev_get_priv(clk->dev); 122 int ret = gen3_clk_setup_sdif_div(clk); 123 124 if (ret) 125 return ret; 126 127 return renesas_clk_endisable(clk, priv->base, true); 128 } 129 130 static int gen3_clk_disable(struct clk *clk) 131 { 132 struct gen3_clk_priv *priv = dev_get_priv(clk->dev); 133 134 return renesas_clk_endisable(clk, priv->base, false); 135 } 136 137 static ulong gen3_clk_get_rate(struct clk *clk) 138 { 139 struct gen3_clk_priv *priv = dev_get_priv(clk->dev); 140 struct cpg_mssr_info *info = priv->info; 141 struct clk parent; 142 const struct cpg_core_clk *core; 143 const struct rcar_gen3_cpg_pll_config *pll_config = 144 priv->cpg_pll_config; 145 u32 value, mult, prediv, postdiv, rate = 0; 146 int i, ret; 147 148 debug("%s[%i] Clock: id=%lu\n", __func__, __LINE__, clk->id); 149 150 ret = renesas_clk_get_parent(clk, info, &parent); 151 if (ret) { 152 printf("%s[%i] parent fail, ret=%i\n", __func__, __LINE__, ret); 153 return ret; 154 } 155 156 if (renesas_clk_is_mod(clk)) { 157 rate = gen3_clk_get_rate(&parent); 158 debug("%s[%i] MOD clk: parent=%lu => rate=%u\n", 159 __func__, __LINE__, parent.id, rate); 160 return rate; 161 } 162 163 ret = renesas_clk_get_core(clk, info, &core); 164 if (ret) 165 return ret; 166 167 switch (core->type) { 168 case CLK_TYPE_IN: 169 if (core->id == info->clk_extal_id) { 170 rate = clk_get_rate(&priv->clk_extal); 171 debug("%s[%i] EXTAL clk: rate=%u\n", 172 __func__, __LINE__, rate); 173 return rate; 174 } 175 176 if (core->id == info->clk_extalr_id) { 177 rate = clk_get_rate(&priv->clk_extalr); 178 debug("%s[%i] EXTALR clk: rate=%u\n", 179 __func__, __LINE__, rate); 180 return rate; 181 } 182 183 return -EINVAL; 184 185 case CLK_TYPE_GEN3_MAIN: 186 rate = gen3_clk_get_rate(&parent) / pll_config->extal_div; 187 debug("%s[%i] MAIN clk: parent=%i extal_div=%i => rate=%u\n", 188 __func__, __LINE__, 189 core->parent, pll_config->extal_div, rate); 190 return rate; 191 192 case CLK_TYPE_GEN3_PLL0: 193 value = readl(priv->base + CPG_PLL0CR); 194 mult = (((value >> 24) & 0x7f) + 1) * 2; 195 rate = gen3_clk_get_rate(&parent) * mult; 196 debug("%s[%i] PLL0 clk: parent=%i mult=%u => rate=%u\n", 197 __func__, __LINE__, core->parent, mult, rate); 198 return rate; 199 200 case CLK_TYPE_GEN3_PLL1: 201 rate = gen3_clk_get_rate(&parent) * pll_config->pll1_mult; 202 debug("%s[%i] PLL1 clk: parent=%i mul=%i => rate=%u\n", 203 __func__, __LINE__, 204 core->parent, pll_config->pll1_mult, rate); 205 return rate; 206 207 case CLK_TYPE_GEN3_PLL2: 208 value = readl(priv->base + CPG_PLL2CR); 209 mult = (((value >> 24) & 0x7f) + 1) * 2; 210 rate = gen3_clk_get_rate(&parent) * mult; 211 debug("%s[%i] PLL2 clk: parent=%i mult=%u => rate=%u\n", 212 __func__, __LINE__, core->parent, mult, rate); 213 return rate; 214 215 case CLK_TYPE_GEN3_PLL3: 216 rate = gen3_clk_get_rate(&parent) * pll_config->pll3_mult; 217 debug("%s[%i] PLL3 clk: parent=%i mul=%i => rate=%u\n", 218 __func__, __LINE__, 219 core->parent, pll_config->pll3_mult, rate); 220 return rate; 221 222 case CLK_TYPE_GEN3_PLL4: 223 value = readl(priv->base + CPG_PLL4CR); 224 mult = (((value >> 24) & 0x7f) + 1) * 2; 225 rate = gen3_clk_get_rate(&parent) * mult; 226 debug("%s[%i] PLL4 clk: parent=%i mult=%u => rate=%u\n", 227 __func__, __LINE__, core->parent, mult, rate); 228 return rate; 229 230 case CLK_TYPE_FF: 231 case CLK_TYPE_GEN3_PE: /* FIXME */ 232 rate = (gen3_clk_get_rate(&parent) * core->mult) / core->div; 233 debug("%s[%i] FIXED clk: parent=%i div=%i mul=%i => rate=%u\n", 234 __func__, __LINE__, 235 core->parent, core->mult, core->div, rate); 236 return rate; 237 238 case CLK_TYPE_GEN3_SD: /* FIXME */ 239 value = readl(priv->base + core->offset); 240 value &= CPG_SD_STP_MASK | CPG_SD_FC_MASK; 241 242 for (i = 0; i < ARRAY_SIZE(cpg_sd_div_table); i++) { 243 if (cpg_sd_div_table[i].val != value) 244 continue; 245 246 rate = gen3_clk_get_rate(&parent) / 247 cpg_sd_div_table[i].div; 248 debug("%s[%i] SD clk: parent=%i div=%i => rate=%u\n", 249 __func__, __LINE__, 250 core->parent, cpg_sd_div_table[i].div, rate); 251 252 return rate; 253 } 254 255 return -EINVAL; 256 257 case CLK_TYPE_GEN3_RPC: 258 rate = gen3_clk_get_rate(&parent); 259 260 value = readl(priv->base + core->offset); 261 262 prediv = (value >> CPG_RPC_PREDIV_OFFSET) & 263 CPG_RPC_PREDIV_MASK; 264 if (prediv == 2) 265 rate /= 5; 266 else if (prediv == 3) 267 rate /= 6; 268 else 269 return -EINVAL; 270 271 postdiv = (value >> CPG_RPC_POSTDIV_OFFSET) & 272 CPG_RPC_POSTDIV_MASK; 273 rate /= postdiv + 1; 274 275 debug("%s[%i] RPC clk: parent=%i prediv=%i postdiv=%i => rate=%u\n", 276 __func__, __LINE__, 277 core->parent, prediv, postdiv, rate); 278 279 return -EINVAL; 280 281 } 282 283 printf("%s[%i] unknown fail\n", __func__, __LINE__); 284 285 return -ENOENT; 286 } 287 288 static ulong gen3_clk_set_rate(struct clk *clk, ulong rate) 289 { 290 /* Force correct SD-IF divider configuration if applicable */ 291 gen3_clk_setup_sdif_div(clk); 292 return gen3_clk_get_rate(clk); 293 } 294 295 static int gen3_clk_of_xlate(struct clk *clk, struct ofnode_phandle_args *args) 296 { 297 if (args->args_count != 2) { 298 debug("Invaild args_count: %d\n", args->args_count); 299 return -EINVAL; 300 } 301 302 clk->id = (args->args[0] << 16) | args->args[1]; 303 304 return 0; 305 } 306 307 const struct clk_ops gen3_clk_ops = { 308 .enable = gen3_clk_enable, 309 .disable = gen3_clk_disable, 310 .get_rate = gen3_clk_get_rate, 311 .set_rate = gen3_clk_set_rate, 312 .of_xlate = gen3_clk_of_xlate, 313 }; 314 315 int gen3_clk_probe(struct udevice *dev) 316 { 317 struct gen3_clk_priv *priv = dev_get_priv(dev); 318 struct cpg_mssr_info *info = 319 (struct cpg_mssr_info *)dev_get_driver_data(dev); 320 fdt_addr_t rst_base; 321 u32 cpg_mode; 322 int ret; 323 324 priv->base = (struct gen3_base *)devfdt_get_addr(dev); 325 if (!priv->base) 326 return -EINVAL; 327 328 priv->info = info; 329 ret = fdt_node_offset_by_compatible(gd->fdt_blob, -1, info->reset_node); 330 if (ret < 0) 331 return ret; 332 333 rst_base = fdtdec_get_addr(gd->fdt_blob, ret, "reg"); 334 if (rst_base == FDT_ADDR_T_NONE) 335 return -EINVAL; 336 337 cpg_mode = readl(rst_base + CPG_RST_MODEMR); 338 339 priv->cpg_pll_config = 340 (struct rcar_gen3_cpg_pll_config *)info->get_pll_config(cpg_mode); 341 if (!priv->cpg_pll_config->extal_div) 342 return -EINVAL; 343 344 ret = clk_get_by_name(dev, "extal", &priv->clk_extal); 345 if (ret < 0) 346 return ret; 347 348 if (info->extalr_node) { 349 ret = clk_get_by_name(dev, info->extalr_node, &priv->clk_extalr); 350 if (ret < 0) 351 return ret; 352 } 353 354 return 0; 355 } 356 357 int gen3_clk_remove(struct udevice *dev) 358 { 359 struct gen3_clk_priv *priv = dev_get_priv(dev); 360 361 return renesas_clk_remove(priv->base, priv->info); 362 } 363