brintos

brintos / linux-shallow public Read only

0
0
Text · 13.8 KiB · 20b89eb Raw
556 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * R-Car Gen3 Clock Pulse Generator4 *5 * Copyright (C) 2015-2018 Glider bvba6 * Copyright (C) 2019 Renesas Electronics Corp.7 *8 * Based on clk-rcar-gen3.c9 *10 * Copyright (C) 2015 Renesas Electronics Corp.11 */12 13#include <linux/bug.h>14#include <linux/bitfield.h>15#include <linux/clk.h>16#include <linux/clk-provider.h>17#include <linux/device.h>18#include <linux/err.h>19#include <linux/init.h>20#include <linux/io.h>21#include <linux/pm.h>22#include <linux/slab.h>23#include <linux/sys_soc.h>24 25#include "renesas-cpg-mssr.h"26#include "rcar-cpg-lib.h"27#include "rcar-gen3-cpg.h"28 29#define CPG_PLLECR		0x00d0	/* PLL Enable Control Register */30 31#define CPG_PLLECR_PLLST(n)	BIT(8 + (n))	/* PLLn Circuit Status */32 33#define CPG_PLL0CR		0x00d8	/* PLLn Control Registers */34#define CPG_PLL2CR		0x002c35#define CPG_PLL4CR		0x01f436 37#define CPG_PLLnCR_STC_MASK	GENMASK(30, 24)	/* PLL Circuit Mult. Ratio */38 39#define CPG_RCKCR_CKSEL	BIT(15)	/* RCLK Clock Source Select */40 41/* PLL Clocks */42struct cpg_pll_clk {43	struct clk_hw hw;44	void __iomem *pllcr_reg;45	void __iomem *pllecr_reg;46	unsigned int fixed_mult;47	u32 pllecr_pllst_mask;48};49 50#define to_pll_clk(_hw)   container_of(_hw, struct cpg_pll_clk, hw)51 52static unsigned long cpg_pll_clk_recalc_rate(struct clk_hw *hw,53					     unsigned long parent_rate)54{55	struct cpg_pll_clk *pll_clk = to_pll_clk(hw);56	unsigned int mult;57	u32 val;58 59	val = readl(pll_clk->pllcr_reg) & CPG_PLLnCR_STC_MASK;60	mult = (val >> __ffs(CPG_PLLnCR_STC_MASK)) + 1;61 62	return parent_rate * mult * pll_clk->fixed_mult;63}64 65static int cpg_pll_clk_determine_rate(struct clk_hw *hw,66				      struct clk_rate_request *req)67{68	struct cpg_pll_clk *pll_clk = to_pll_clk(hw);69	unsigned int min_mult, max_mult, mult;70	unsigned long prate;71 72	prate = req->best_parent_rate * pll_clk->fixed_mult;73	min_mult = max(div64_ul(req->min_rate, prate), 1ULL);74	max_mult = min(div64_ul(req->max_rate, prate), 128ULL);75	if (max_mult < min_mult)76		return -EINVAL;77 78	mult = DIV_ROUND_CLOSEST_ULL(req->rate, prate);79	mult = clamp(mult, min_mult, max_mult);80 81	req->rate = prate * mult;82	return 0;83}84 85static int cpg_pll_clk_set_rate(struct clk_hw *hw, unsigned long rate,86				unsigned long parent_rate)87{88	struct cpg_pll_clk *pll_clk = to_pll_clk(hw);89	unsigned int mult, i;90	u32 val;91 92	mult = DIV_ROUND_CLOSEST_ULL(rate, parent_rate * pll_clk->fixed_mult);93	mult = clamp(mult, 1U, 128U);94 95	val = readl(pll_clk->pllcr_reg);96	val &= ~CPG_PLLnCR_STC_MASK;97	val |= (mult - 1) << __ffs(CPG_PLLnCR_STC_MASK);98	writel(val, pll_clk->pllcr_reg);99 100	for (i = 1000; i; i--) {101		if (readl(pll_clk->pllecr_reg) & pll_clk->pllecr_pllst_mask)102			return 0;103 104		cpu_relax();105	}106 107	return -ETIMEDOUT;108}109 110static const struct clk_ops cpg_pll_clk_ops = {111	.recalc_rate = cpg_pll_clk_recalc_rate,112	.determine_rate = cpg_pll_clk_determine_rate,113	.set_rate = cpg_pll_clk_set_rate,114};115 116static struct clk * __init cpg_pll_clk_register(const char *name,117						const char *parent_name,118						void __iomem *base,119						unsigned int mult,120						unsigned int offset,121						unsigned int index)122 123{124	struct cpg_pll_clk *pll_clk;125	struct clk_init_data init = {};126	struct clk *clk;127 128	pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);129	if (!pll_clk)130		return ERR_PTR(-ENOMEM);131 132	init.name = name;133	init.ops = &cpg_pll_clk_ops;134	init.parent_names = &parent_name;135	init.num_parents = 1;136 137	pll_clk->hw.init = &init;138	pll_clk->pllcr_reg = base + offset;139	pll_clk->pllecr_reg = base + CPG_PLLECR;140	pll_clk->fixed_mult = mult;	/* PLL refclk x (setting + 1) x mult */141	pll_clk->pllecr_pllst_mask = CPG_PLLECR_PLLST(index);142 143	clk = clk_register(NULL, &pll_clk->hw);144	if (IS_ERR(clk))145		kfree(pll_clk);146 147	return clk;148}149 150/*151 * Z Clock & Z2 Clock152 *153 * Traits of this clock:154 * prepare - clk_prepare only ensures that parents are prepared155 * enable - clk_enable only ensures that parents are enabled156 * rate - rate is adjustable.157 *        clk->rate = (parent->rate * mult / 32 ) / fixed_div158 * parent - fixed parent.  No clk_set_parent support159 */160#define CPG_FRQCRB			0x00000004161#define CPG_FRQCRB_KICK			BIT(31)162#define CPG_FRQCRC			0x000000e0163 164struct cpg_z_clk {165	struct clk_hw hw;166	void __iomem *reg;167	void __iomem *kick_reg;168	unsigned long max_rate;		/* Maximum rate for normal mode */169	unsigned int fixed_div;170	u32 mask;171};172 173#define to_z_clk(_hw)	container_of(_hw, struct cpg_z_clk, hw)174 175static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,176					   unsigned long parent_rate)177{178	struct cpg_z_clk *zclk = to_z_clk(hw);179	unsigned int mult;180	u32 val;181 182	val = readl(zclk->reg) & zclk->mask;183	mult = 32 - (val >> __ffs(zclk->mask));184 185	return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult,186				     32 * zclk->fixed_div);187}188 189static int cpg_z_clk_determine_rate(struct clk_hw *hw,190				    struct clk_rate_request *req)191{192	struct cpg_z_clk *zclk = to_z_clk(hw);193	unsigned int min_mult, max_mult, mult;194	unsigned long rate, prate;195 196	rate = min(req->rate, req->max_rate);197	if (rate <= zclk->max_rate) {198		/* Set parent rate to initial value for normal modes */199		prate = zclk->max_rate;200	} else {201		/* Set increased parent rate for boost modes */202		prate = rate;203	}204	req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),205						  prate * zclk->fixed_div);206 207	prate = req->best_parent_rate / zclk->fixed_div;208	min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL);209	max_mult = min(div64_ul(req->max_rate * 32ULL, prate), 32ULL);210	if (max_mult < min_mult)211		return -EINVAL;212 213	mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL, prate);214	mult = clamp(mult, min_mult, max_mult);215 216	req->rate = DIV_ROUND_CLOSEST_ULL((u64)prate * mult, 32);217	return 0;218}219 220static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,221			      unsigned long parent_rate)222{223	struct cpg_z_clk *zclk = to_z_clk(hw);224	unsigned int mult;225	unsigned int i;226 227	mult = DIV64_U64_ROUND_CLOSEST(rate * 32ULL * zclk->fixed_div,228				       parent_rate);229	mult = clamp(mult, 1U, 32U);230 231	if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)232		return -EBUSY;233 234	cpg_reg_modify(zclk->reg, zclk->mask, (32 - mult) << __ffs(zclk->mask));235 236	/*237	 * Set KICK bit in FRQCRB to update hardware setting and wait for238	 * clock change completion.239	 */240	cpg_reg_modify(zclk->kick_reg, 0, CPG_FRQCRB_KICK);241 242	/*243	 * Note: There is no HW information about the worst case latency.244	 *245	 * Using experimental measurements, it seems that no more than246	 * ~10 iterations are needed, independently of the CPU rate.247	 * Since this value might be dependent on external xtal rate, pll1248	 * rate or even the other emulation clocks rate, use 1000 as a249	 * "super" safe value.250	 */251	for (i = 1000; i; i--) {252		if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))253			return 0;254 255		cpu_relax();256	}257 258	return -ETIMEDOUT;259}260 261static const struct clk_ops cpg_z_clk_ops = {262	.recalc_rate = cpg_z_clk_recalc_rate,263	.determine_rate = cpg_z_clk_determine_rate,264	.set_rate = cpg_z_clk_set_rate,265};266 267static struct clk * __init __cpg_z_clk_register(const char *name,268					      const char *parent_name,269					      void __iomem *reg,270					      unsigned int div,271					      unsigned int offset,272					      unsigned int fcr,273					      unsigned int flags)274{275	struct clk_init_data init = {};276	struct cpg_z_clk *zclk;277	struct clk *clk;278 279	zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);280	if (!zclk)281		return ERR_PTR(-ENOMEM);282 283	init.name = name;284	init.ops = &cpg_z_clk_ops;285	init.flags = flags;286	init.parent_names = &parent_name;287	init.num_parents = 1;288 289	zclk->reg = reg + fcr;290	zclk->kick_reg = reg + CPG_FRQCRB;291	zclk->hw.init = &init;292	zclk->mask = GENMASK(offset + 4, offset);293	zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */294 295	clk = clk_register(NULL, &zclk->hw);296	if (IS_ERR(clk)) {297		kfree(zclk);298		return clk;299	}300 301	zclk->max_rate = clk_hw_get_rate(clk_hw_get_parent(&zclk->hw)) /302			 zclk->fixed_div;303	return clk;304}305 306static struct clk * __init cpg_z_clk_register(const char *name,307					      const char *parent_name,308					      void __iomem *reg,309					      unsigned int div,310					      unsigned int offset)311{312	return __cpg_z_clk_register(name, parent_name, reg, div, offset,313				    CPG_FRQCRC, CLK_SET_RATE_PARENT);314}315 316static struct clk * __init cpg_zg_clk_register(const char *name,317					       const char *parent_name,318					       void __iomem *reg,319					       unsigned int div,320					       unsigned int offset)321{322	return __cpg_z_clk_register(name, parent_name, reg, div, offset,323				    CPG_FRQCRB, 0);324 325}326 327static const struct clk_div_table cpg_rpcsrc_div_table[] = {328	{ 2, 5 }, { 3, 6 }, { 0, 0 },329};330 331static const struct rcar_gen3_cpg_pll_config *cpg_pll_config __initdata;332static unsigned int cpg_clk_extalr __initdata;333static u32 cpg_mode __initdata;334static u32 cpg_quirks __initdata;335 336#define RCKCR_CKSEL	BIT(1)		/* Manual RCLK parent selection */337 338 339static const struct soc_device_attribute cpg_quirks_match[] __initconst = {340	{341		.soc_id = "r8a7796", .revision = "ES1.0",342		.data = (void *)(RCKCR_CKSEL),343	},344	{ /* sentinel */ }345};346 347struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,348	const struct cpg_core_clk *core, const struct cpg_mssr_info *info,349	struct clk **clks, void __iomem *base,350	struct raw_notifier_head *notifiers)351{352	const struct clk *parent;353	unsigned int mult = 1;354	unsigned int div = 1;355	u32 value;356 357	parent = clks[core->parent & 0xffff];	/* some types use high bits */358	if (IS_ERR(parent))359		return ERR_CAST(parent);360 361	switch (core->type) {362	case CLK_TYPE_GEN3_MAIN:363		div = cpg_pll_config->extal_div;364		break;365 366	case CLK_TYPE_GEN3_PLL0:367		/*368		 * PLL0 is implemented as a custom clock, to change the369		 * multiplier when cpufreq changes between normal and boost370		 * modes.371		 */372		return cpg_pll_clk_register(core->name, __clk_get_name(parent),373					    base, 2, CPG_PLL0CR, 0);374 375	case CLK_TYPE_GEN3_PLL1:376		mult = cpg_pll_config->pll1_mult;377		div = cpg_pll_config->pll1_div;378		break;379 380	case CLK_TYPE_GEN3_PLL2:381		/*382		 * PLL2 is implemented as a custom clock, to change the383		 * multiplier when cpufreq changes between normal and boost384		 * modes.385		 */386		return cpg_pll_clk_register(core->name, __clk_get_name(parent),387					    base, 2, CPG_PLL2CR, 2);388 389	case CLK_TYPE_GEN3_PLL3:390		mult = cpg_pll_config->pll3_mult;391		div = cpg_pll_config->pll3_div;392		break;393 394	case CLK_TYPE_GEN3_PLL4:395		/*396		 * PLL4 is a configurable multiplier clock. Register it as a397		 * fixed factor clock for now as there's no generic multiplier398		 * clock implementation and we currently have no need to change399		 * the multiplier value.400		 */401		value = readl(base + CPG_PLL4CR);402		mult = (((value >> 24) & 0x7f) + 1) * 2;403		break;404 405	case CLK_TYPE_GEN3_SDH:406		return cpg_sdh_clk_register(core->name, base + core->offset,407					   __clk_get_name(parent), notifiers);408 409	case CLK_TYPE_GEN3_SD:410		return cpg_sd_clk_register(core->name, base + core->offset,411					   __clk_get_name(parent));412 413	case CLK_TYPE_GEN3_R:414		if (cpg_quirks & RCKCR_CKSEL) {415			struct cpg_simple_notifier *csn;416 417			csn = kzalloc(sizeof(*csn), GFP_KERNEL);418			if (!csn)419				return ERR_PTR(-ENOMEM);420 421			csn->reg = base + CPG_RCKCR;422 423			/*424			 * RINT is default.425			 * Only if EXTALR is populated, we switch to it.426			 */427			value = readl(csn->reg) & 0x3f;428 429			if (clk_get_rate(clks[cpg_clk_extalr])) {430				parent = clks[cpg_clk_extalr];431				value |= CPG_RCKCR_CKSEL;432			}433 434			writel(value, csn->reg);435			cpg_simple_notifier_register(notifiers, csn);436			break;437		}438 439		/* Select parent clock of RCLK by MD28 */440		if (cpg_mode & BIT(28))441			parent = clks[cpg_clk_extalr];442		break;443 444	case CLK_TYPE_GEN3_MDSEL:445		/*446		 * Clock selectable between two parents and two fixed dividers447		 * using a mode pin448		 */449		if (cpg_mode & BIT(core->offset)) {450			div = core->div & 0xffff;451		} else {452			parent = clks[core->parent >> 16];453			if (IS_ERR(parent))454				return ERR_CAST(parent);455			div = core->div >> 16;456		}457		mult = 1;458		break;459 460	case CLK_TYPE_GEN3_Z:461		return cpg_z_clk_register(core->name, __clk_get_name(parent),462					  base, core->div, core->offset);463 464	case CLK_TYPE_GEN3_ZG:465		return cpg_zg_clk_register(core->name, __clk_get_name(parent),466					   base, core->div, core->offset);467 468	case CLK_TYPE_GEN3_OSC:469		/*470		 * Clock combining OSC EXTAL predivider and a fixed divider471		 */472		div = cpg_pll_config->osc_prediv * core->div;473		break;474 475	case CLK_TYPE_GEN3_RCKSEL:476		/*477		 * Clock selectable between two parents and two fixed dividers478		 * using RCKCR.CKSEL479		 */480		if (readl(base + CPG_RCKCR) & CPG_RCKCR_CKSEL) {481			div = core->div & 0xffff;482		} else {483			parent = clks[core->parent >> 16];484			if (IS_ERR(parent))485				return ERR_CAST(parent);486			div = core->div >> 16;487		}488		break;489 490	case CLK_TYPE_GEN3_RPCSRC:491		return clk_register_divider_table(NULL, core->name,492						  __clk_get_name(parent), 0,493						  base + CPG_RPCCKCR, 3, 2, 0,494						  cpg_rpcsrc_div_table,495						  &cpg_lock);496 497	case CLK_TYPE_GEN3_E3_RPCSRC:498		/*499		 * Register RPCSRC as fixed factor clock based on the500		 * MD[4:1] pins and CPG_RPCCKCR[4:3] register value for501		 * which has been set prior to booting the kernel.502		 */503		value = (readl(base + CPG_RPCCKCR) & GENMASK(4, 3)) >> 3;504 505		switch (value) {506		case 0:507			div = 5;508			break;509		case 1:510			div = 3;511			break;512		case 2:513			parent = clks[core->parent >> 16];514			if (IS_ERR(parent))515				return ERR_CAST(parent);516			div = core->div;517			break;518		case 3:519		default:520			div = 2;521			break;522		}523		break;524 525	case CLK_TYPE_GEN3_RPC:526		return cpg_rpc_clk_register(core->name, base + CPG_RPCCKCR,527					    __clk_get_name(parent), notifiers);528 529	case CLK_TYPE_GEN3_RPCD2:530		return cpg_rpcd2_clk_register(core->name, base + CPG_RPCCKCR,531					      __clk_get_name(parent));532 533	default:534		return ERR_PTR(-EINVAL);535	}536 537	return clk_register_fixed_factor(NULL, core->name,538					 __clk_get_name(parent), 0, mult, div);539}540 541int __init rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config,542			      unsigned int clk_extalr, u32 mode)543{544	const struct soc_device_attribute *attr;545 546	cpg_pll_config = config;547	cpg_clk_extalr = clk_extalr;548	cpg_mode = mode;549	attr = soc_device_match(cpg_quirks_match);550	if (attr)551		cpg_quirks = (uintptr_t)attr->data;552	pr_debug("%s: mode = 0x%x quirks = 0x%x\n", __func__, mode, cpg_quirks);553 554	return 0;555}556