rcar-gen4-cpg.c (7714B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * R-Car Gen4 Clock Pulse Generator 4 * 5 * Copyright (C) 2021 Renesas Electronics Corp. 6 * 7 * Based on rcar-gen3-cpg.c 8 * 9 * Copyright (C) 2015-2018 Glider bvba 10 * Copyright (C) 2019 Renesas Electronics Corp. 11 */ 12 13#include <linux/bitfield.h> 14#include <linux/clk.h> 15#include <linux/clk-provider.h> 16#include <linux/device.h> 17#include <linux/err.h> 18#include <linux/init.h> 19#include <linux/io.h> 20#include <linux/slab.h> 21 22#include "renesas-cpg-mssr.h" 23#include "rcar-gen4-cpg.h" 24#include "rcar-cpg-lib.h" 25 26static const struct rcar_gen4_cpg_pll_config *cpg_pll_config __initconst; 27static unsigned int cpg_clk_extalr __initdata; 28static u32 cpg_mode __initdata; 29 30/* 31 * Z0 Clock & Z1 Clock 32 */ 33#define CPG_FRQCRB 0x00000804 34#define CPG_FRQCRB_KICK BIT(31) 35#define CPG_FRQCRC 0x00000808 36 37struct cpg_z_clk { 38 struct clk_hw hw; 39 void __iomem *reg; 40 void __iomem *kick_reg; 41 unsigned long max_rate; /* Maximum rate for normal mode */ 42 unsigned int fixed_div; 43 u32 mask; 44}; 45 46#define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw) 47 48static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw, 49 unsigned long parent_rate) 50{ 51 struct cpg_z_clk *zclk = to_z_clk(hw); 52 unsigned int mult; 53 u32 val; 54 55 val = readl(zclk->reg) & zclk->mask; 56 mult = 32 - (val >> __ffs(zclk->mask)); 57 58 return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult, 59 32 * zclk->fixed_div); 60} 61 62static int cpg_z_clk_determine_rate(struct clk_hw *hw, 63 struct clk_rate_request *req) 64{ 65 struct cpg_z_clk *zclk = to_z_clk(hw); 66 unsigned int min_mult, max_mult, mult; 67 unsigned long rate, prate; 68 69 rate = min(req->rate, req->max_rate); 70 if (rate <= zclk->max_rate) { 71 /* Set parent rate to initial value for normal modes */ 72 prate = zclk->max_rate; 73 } else { 74 /* Set increased parent rate for boost modes */ 75 prate = rate; 76 } 77 req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), 78 prate * zclk->fixed_div); 79 80 prate = req->best_parent_rate / zclk->fixed_div; 81 min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL); 82 max_mult = min(div64_ul(req->max_rate * 32ULL, prate), 32ULL); 83 if (max_mult < min_mult) 84 return -EINVAL; 85 86 mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL, prate); 87 mult = clamp(mult, min_mult, max_mult); 88 89 req->rate = DIV_ROUND_CLOSEST_ULL((u64)prate * mult, 32); 90 return 0; 91} 92 93static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate, 94 unsigned long parent_rate) 95{ 96 struct cpg_z_clk *zclk = to_z_clk(hw); 97 unsigned int mult; 98 unsigned int i; 99 100 mult = DIV64_U64_ROUND_CLOSEST(rate * 32ULL * zclk->fixed_div, 101 parent_rate); 102 mult = clamp(mult, 1U, 32U); 103 104 if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK) 105 return -EBUSY; 106 107 cpg_reg_modify(zclk->reg, zclk->mask, (32 - mult) << __ffs(zclk->mask)); 108 109 /* 110 * Set KICK bit in FRQCRB to update hardware setting and wait for 111 * clock change completion. 112 */ 113 cpg_reg_modify(zclk->kick_reg, 0, CPG_FRQCRB_KICK); 114 115 /* 116 * Note: There is no HW information about the worst case latency. 117 * 118 * Using experimental measurements, it seems that no more than 119 * ~10 iterations are needed, independently of the CPU rate. 120 * Since this value might be dependent on external xtal rate, pll1 121 * rate or even the other emulation clocks rate, use 1000 as a 122 * "super" safe value. 123 */ 124 for (i = 1000; i; i--) { 125 if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK)) 126 return 0; 127 128 cpu_relax(); 129 } 130 131 return -ETIMEDOUT; 132} 133 134static const struct clk_ops cpg_z_clk_ops = { 135 .recalc_rate = cpg_z_clk_recalc_rate, 136 .determine_rate = cpg_z_clk_determine_rate, 137 .set_rate = cpg_z_clk_set_rate, 138}; 139 140static struct clk * __init cpg_z_clk_register(const char *name, 141 const char *parent_name, 142 void __iomem *reg, 143 unsigned int div, 144 unsigned int offset) 145{ 146 struct clk_init_data init = {}; 147 struct cpg_z_clk *zclk; 148 struct clk *clk; 149 150 zclk = kzalloc(sizeof(*zclk), GFP_KERNEL); 151 if (!zclk) 152 return ERR_PTR(-ENOMEM); 153 154 init.name = name; 155 init.ops = &cpg_z_clk_ops; 156 init.flags = CLK_SET_RATE_PARENT; 157 init.parent_names = &parent_name; 158 init.num_parents = 1; 159 160 zclk->reg = reg + CPG_FRQCRC; 161 zclk->kick_reg = reg + CPG_FRQCRB; 162 zclk->hw.init = &init; 163 zclk->mask = GENMASK(offset + 4, offset); 164 zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */ 165 166 clk = clk_register(NULL, &zclk->hw); 167 if (IS_ERR(clk)) { 168 kfree(zclk); 169 return clk; 170 } 171 172 zclk->max_rate = clk_hw_get_rate(clk_hw_get_parent(&zclk->hw)) / 173 zclk->fixed_div; 174 return clk; 175} 176 177/* 178 * RPC Clocks 179 */ 180static const struct clk_div_table cpg_rpcsrc_div_table[] = { 181 { 0, 4 }, { 1, 6 }, { 2, 5 }, { 3, 6 }, { 0, 0 }, 182}; 183 184struct clk * __init rcar_gen4_cpg_clk_register(struct device *dev, 185 const struct cpg_core_clk *core, const struct cpg_mssr_info *info, 186 struct clk **clks, void __iomem *base, 187 struct raw_notifier_head *notifiers) 188{ 189 const struct clk *parent; 190 unsigned int mult = 1; 191 unsigned int div = 1; 192 u32 value; 193 194 parent = clks[core->parent & 0xffff]; /* some types use high bits */ 195 if (IS_ERR(parent)) 196 return ERR_CAST(parent); 197 198 switch (core->type) { 199 case CLK_TYPE_GEN4_MAIN: 200 div = cpg_pll_config->extal_div; 201 break; 202 203 case CLK_TYPE_GEN4_PLL1: 204 mult = cpg_pll_config->pll1_mult; 205 div = cpg_pll_config->pll1_div; 206 break; 207 208 case CLK_TYPE_GEN4_PLL2: 209 mult = cpg_pll_config->pll2_mult; 210 div = cpg_pll_config->pll2_div; 211 break; 212 213 case CLK_TYPE_GEN4_PLL3: 214 mult = cpg_pll_config->pll3_mult; 215 div = cpg_pll_config->pll3_div; 216 break; 217 218 case CLK_TYPE_GEN4_PLL4: 219 mult = cpg_pll_config->pll4_mult; 220 div = cpg_pll_config->pll4_div; 221 break; 222 223 case CLK_TYPE_GEN4_PLL5: 224 mult = cpg_pll_config->pll5_mult; 225 div = cpg_pll_config->pll5_div; 226 break; 227 228 case CLK_TYPE_GEN4_PLL6: 229 mult = cpg_pll_config->pll6_mult; 230 div = cpg_pll_config->pll6_div; 231 break; 232 233 case CLK_TYPE_GEN4_PLL2X_3X: 234 value = readl(base + core->offset); 235 mult = (((value >> 24) & 0x7f) + 1) * 2; 236 break; 237 238 case CLK_TYPE_GEN4_Z: 239 return cpg_z_clk_register(core->name, __clk_get_name(parent), 240 base, core->div, core->offset); 241 242 case CLK_TYPE_GEN4_SDSRC: 243 div = ((readl(base + SD0CKCR1) >> 29) & 0x03) + 4; 244 break; 245 246 case CLK_TYPE_GEN4_SDH: 247 return cpg_sdh_clk_register(core->name, base + core->offset, 248 __clk_get_name(parent), notifiers); 249 250 case CLK_TYPE_GEN4_SD: 251 return cpg_sd_clk_register(core->name, base + core->offset, 252 __clk_get_name(parent)); 253 254 case CLK_TYPE_GEN4_MDSEL: 255 /* 256 * Clock selectable between two parents and two fixed dividers 257 * using a mode pin 258 */ 259 if (cpg_mode & BIT(core->offset)) { 260 div = core->div & 0xffff; 261 } else { 262 parent = clks[core->parent >> 16]; 263 if (IS_ERR(parent)) 264 return ERR_CAST(parent); 265 div = core->div >> 16; 266 } 267 mult = 1; 268 break; 269 270 case CLK_TYPE_GEN4_OSC: 271 /* 272 * Clock combining OSC EXTAL predivider and a fixed divider 273 */ 274 div = cpg_pll_config->osc_prediv * core->div; 275 break; 276 277 case CLK_TYPE_GEN4_RPCSRC: 278 return clk_register_divider_table(NULL, core->name, 279 __clk_get_name(parent), 0, 280 base + CPG_RPCCKCR, 3, 2, 0, 281 cpg_rpcsrc_div_table, 282 &cpg_lock); 283 284 case CLK_TYPE_GEN4_RPC: 285 return cpg_rpc_clk_register(core->name, base + CPG_RPCCKCR, 286 __clk_get_name(parent), notifiers); 287 288 case CLK_TYPE_GEN4_RPCD2: 289 return cpg_rpcd2_clk_register(core->name, base + CPG_RPCCKCR, 290 __clk_get_name(parent)); 291 292 default: 293 return ERR_PTR(-EINVAL); 294 } 295 296 return clk_register_fixed_factor(NULL, core->name, 297 __clk_get_name(parent), 0, mult, div); 298} 299 300int __init rcar_gen4_cpg_init(const struct rcar_gen4_cpg_pll_config *config, 301 unsigned int clk_extalr, u32 mode) 302{ 303 cpg_pll_config = config; 304 cpg_clk_extalr = clk_extalr; 305 cpg_mode = mode; 306 307 spin_lock_init(&cpg_lock); 308 309 return 0; 310}