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