392 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * R-Car Gen2 Clock Pulse Generator4 *5 * Copyright (C) 2016 Cogent Embedded Inc.6 */7 8#include <linux/bug.h>9#include <linux/clk.h>10#include <linux/clk-provider.h>11#include <linux/device.h>12#include <linux/err.h>13#include <linux/init.h>14#include <linux/io.h>15#include <linux/slab.h>16#include <linux/sys_soc.h>17 18#include "renesas-cpg-mssr.h"19#include "rcar-gen2-cpg.h"20 21#define CPG_FRQCRB 0x000422#define CPG_FRQCRB_KICK BIT(31)23#define CPG_SDCKCR 0x007424#define CPG_PLL0CR 0x00d825#define CPG_PLL0CR_STC_SHIFT 2426#define CPG_PLL0CR_STC_MASK (0x7f << CPG_PLL0CR_STC_SHIFT)27#define CPG_FRQCRC 0x00e028#define CPG_FRQCRC_ZFC_SHIFT 829#define CPG_FRQCRC_ZFC_MASK (0x1f << CPG_FRQCRC_ZFC_SHIFT)30#define CPG_ADSPCKCR 0x025c31#define CPG_RCANCKCR 0x027032 33static DEFINE_SPINLOCK(cpg_lock);34 35/*36 * Z Clock37 *38 * Traits of this clock:39 * prepare - clk_prepare only ensures that parents are prepared40 * enable - clk_enable only ensures that parents are enabled41 * rate - rate is adjustable. clk->rate = parent->rate * mult / 3242 * parent - fixed parent. No clk_set_parent support43 */44 45struct cpg_z_clk {46 struct clk_hw hw;47 void __iomem *reg;48 void __iomem *kick_reg;49};50 51#define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw)52 53static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,54 unsigned long parent_rate)55{56 struct cpg_z_clk *zclk = to_z_clk(hw);57 unsigned int mult;58 unsigned int val;59 60 val = (readl(zclk->reg) & CPG_FRQCRC_ZFC_MASK) >> CPG_FRQCRC_ZFC_SHIFT;61 mult = 32 - val;62 63 return div_u64((u64)parent_rate * mult, 32);64}65 66static int cpg_z_clk_determine_rate(struct clk_hw *hw,67 struct clk_rate_request *req)68{69 unsigned long prate = req->best_parent_rate;70 unsigned int min_mult, max_mult, mult;71 72 min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL);73 max_mult = min(div64_ul(req->max_rate * 32ULL, prate), 32ULL);74 if (max_mult < min_mult)75 return -EINVAL;76 77 mult = div64_ul(req->rate * 32ULL, prate);78 mult = clamp(mult, min_mult, max_mult);79 80 req->rate = div_u64((u64)prate * mult, 32);81 return 0;82}83 84static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,85 unsigned long parent_rate)86{87 struct cpg_z_clk *zclk = to_z_clk(hw);88 unsigned int mult;89 u32 val, kick;90 unsigned int i;91 92 mult = div64_ul(rate * 32ULL, parent_rate);93 mult = clamp(mult, 1U, 32U);94 95 if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)96 return -EBUSY;97 98 val = readl(zclk->reg);99 val &= ~CPG_FRQCRC_ZFC_MASK;100 val |= (32 - mult) << CPG_FRQCRC_ZFC_SHIFT;101 writel(val, zclk->reg);102 103 /*104 * Set KICK bit in FRQCRB to update hardware setting and wait for105 * clock change completion.106 */107 kick = readl(zclk->kick_reg);108 kick |= CPG_FRQCRB_KICK;109 writel(kick, zclk->kick_reg);110 111 /*112 * Note: There is no HW information about the worst case latency.113 *114 * Using experimental measurements, it seems that no more than115 * ~10 iterations are needed, independently of the CPU rate.116 * Since this value might be dependent on external xtal rate, pll1117 * rate or even the other emulation clocks rate, use 1000 as a118 * "super" safe value.119 */120 for (i = 1000; i; i--) {121 if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))122 return 0;123 124 cpu_relax();125 }126 127 return -ETIMEDOUT;128}129 130static const struct clk_ops cpg_z_clk_ops = {131 .recalc_rate = cpg_z_clk_recalc_rate,132 .determine_rate = cpg_z_clk_determine_rate,133 .set_rate = cpg_z_clk_set_rate,134};135 136static struct clk * __init cpg_z_clk_register(const char *name,137 const char *parent_name,138 void __iomem *base)139{140 struct clk_init_data init = {};141 struct cpg_z_clk *zclk;142 struct clk *clk;143 144 zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);145 if (!zclk)146 return ERR_PTR(-ENOMEM);147 148 init.name = name;149 init.ops = &cpg_z_clk_ops;150 init.parent_names = &parent_name;151 init.num_parents = 1;152 153 zclk->reg = base + CPG_FRQCRC;154 zclk->kick_reg = base + CPG_FRQCRB;155 zclk->hw.init = &init;156 157 clk = clk_register(NULL, &zclk->hw);158 if (IS_ERR(clk))159 kfree(zclk);160 161 return clk;162}163 164static struct clk * __init cpg_rcan_clk_register(const char *name,165 const char *parent_name,166 void __iomem *base)167{168 struct clk_fixed_factor *fixed;169 struct clk_gate *gate;170 struct clk *clk;171 172 fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);173 if (!fixed)174 return ERR_PTR(-ENOMEM);175 176 fixed->mult = 1;177 fixed->div = 6;178 179 gate = kzalloc(sizeof(*gate), GFP_KERNEL);180 if (!gate) {181 kfree(fixed);182 return ERR_PTR(-ENOMEM);183 }184 185 gate->reg = base + CPG_RCANCKCR;186 gate->bit_idx = 8;187 gate->flags = CLK_GATE_SET_TO_DISABLE;188 gate->lock = &cpg_lock;189 190 clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,191 &fixed->hw, &clk_fixed_factor_ops,192 &gate->hw, &clk_gate_ops, 0);193 if (IS_ERR(clk)) {194 kfree(gate);195 kfree(fixed);196 }197 198 return clk;199}200 201/* ADSP divisors */202static const struct clk_div_table cpg_adsp_div_table[] = {203 { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 },204 { 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 },205 { 10, 36 }, { 11, 48 }, { 0, 0 },206};207 208static struct clk * __init cpg_adsp_clk_register(const char *name,209 const char *parent_name,210 void __iomem *base)211{212 struct clk_divider *div;213 struct clk_gate *gate;214 struct clk *clk;215 216 div = kzalloc(sizeof(*div), GFP_KERNEL);217 if (!div)218 return ERR_PTR(-ENOMEM);219 220 div->reg = base + CPG_ADSPCKCR;221 div->width = 4;222 div->table = cpg_adsp_div_table;223 div->lock = &cpg_lock;224 225 gate = kzalloc(sizeof(*gate), GFP_KERNEL);226 if (!gate) {227 kfree(div);228 return ERR_PTR(-ENOMEM);229 }230 231 gate->reg = base + CPG_ADSPCKCR;232 gate->bit_idx = 8;233 gate->flags = CLK_GATE_SET_TO_DISABLE;234 gate->lock = &cpg_lock;235 236 clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,237 &div->hw, &clk_divider_ops,238 &gate->hw, &clk_gate_ops, 0);239 if (IS_ERR(clk)) {240 kfree(gate);241 kfree(div);242 }243 244 return clk;245}246 247/* SDHI divisors */248static const struct clk_div_table cpg_sdh_div_table[] = {249 { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 },250 { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },251 { 8, 24 }, { 10, 36 }, { 11, 48 }, { 0, 0 },252};253 254static const struct clk_div_table cpg_sd01_div_table[] = {255 { 4, 8 }, { 5, 12 }, { 6, 16 }, { 7, 18 },256 { 8, 24 }, { 10, 36 }, { 11, 48 }, { 12, 10 },257 { 0, 0 },258};259 260static const struct rcar_gen2_cpg_pll_config *cpg_pll_config __initdata;261static unsigned int cpg_pll0_div __initdata;262static u32 cpg_mode __initdata;263static u32 cpg_quirks __initdata;264 265#define SD_SKIP_FIRST BIT(0) /* Skip first clock in SD table */266 267static const struct soc_device_attribute cpg_quirks_match[] __initconst = {268 {269 .soc_id = "r8a77470",270 .data = (void *)SD_SKIP_FIRST,271 },272 { /* sentinel */ }273};274 275struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,276 const struct cpg_core_clk *core, const struct cpg_mssr_info *info,277 struct clk **clks, void __iomem *base,278 struct raw_notifier_head *notifiers)279{280 const struct clk_div_table *table = NULL;281 const struct clk *parent;282 const char *parent_name;283 unsigned int mult = 1;284 unsigned int div = 1;285 unsigned int shift;286 287 parent = clks[core->parent];288 if (IS_ERR(parent))289 return ERR_CAST(parent);290 291 parent_name = __clk_get_name(parent);292 293 switch (core->type) {294 /* R-Car Gen2 */295 case CLK_TYPE_GEN2_MAIN:296 div = cpg_pll_config->extal_div;297 break;298 299 case CLK_TYPE_GEN2_PLL0:300 /*301 * PLL0 is a configurable multiplier clock except on R-Car302 * V2H/E2. Register the PLL0 clock as a fixed factor clock for303 * now as there's no generic multiplier clock implementation and304 * we currently have no need to change the multiplier value.305 */306 mult = cpg_pll_config->pll0_mult;307 div = cpg_pll0_div;308 if (!mult) {309 u32 pll0cr = readl(base + CPG_PLL0CR);310 311 mult = (((pll0cr & CPG_PLL0CR_STC_MASK) >>312 CPG_PLL0CR_STC_SHIFT) + 1) * 2;313 }314 break;315 316 case CLK_TYPE_GEN2_PLL1:317 mult = cpg_pll_config->pll1_mult / 2;318 break;319 320 case CLK_TYPE_GEN2_PLL3:321 mult = cpg_pll_config->pll3_mult;322 break;323 324 case CLK_TYPE_GEN2_Z:325 return cpg_z_clk_register(core->name, parent_name, base);326 327 case CLK_TYPE_GEN2_LB:328 div = cpg_mode & BIT(18) ? 36 : 24;329 break;330 331 case CLK_TYPE_GEN2_ADSP:332 return cpg_adsp_clk_register(core->name, parent_name, base);333 334 case CLK_TYPE_GEN2_SDH:335 table = cpg_sdh_div_table;336 shift = 8;337 break;338 339 case CLK_TYPE_GEN2_SD0:340 table = cpg_sd01_div_table;341 if (cpg_quirks & SD_SKIP_FIRST)342 table++;343 344 shift = 4;345 break;346 347 case CLK_TYPE_GEN2_SD1:348 table = cpg_sd01_div_table;349 if (cpg_quirks & SD_SKIP_FIRST)350 table++;351 352 shift = 0;353 break;354 355 case CLK_TYPE_GEN2_QSPI:356 div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) ?357 8 : 10;358 break;359 360 case CLK_TYPE_GEN2_RCAN:361 return cpg_rcan_clk_register(core->name, parent_name, base);362 363 default:364 return ERR_PTR(-EINVAL);365 }366 367 if (!table)368 return clk_register_fixed_factor(NULL, core->name, parent_name,369 0, mult, div);370 else371 return clk_register_divider_table(NULL, core->name,372 parent_name, 0,373 base + CPG_SDCKCR, shift, 4,374 0, table, &cpg_lock);375}376 377int __init rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config,378 unsigned int pll0_div, u32 mode)379{380 const struct soc_device_attribute *attr;381 382 cpg_pll_config = config;383 cpg_pll0_div = pll0_div;384 cpg_mode = mode;385 attr = soc_device_match(cpg_quirks_match);386 if (attr)387 cpg_quirks = (uintptr_t)attr->data;388 pr_debug("%s: mode = 0x%x quirks = 0x%x\n", __func__, mode, cpg_quirks);389 390 return 0;391}392