File Index
Files and directories
Sign in
FILE

clk-core.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/microchip/clk-core.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Purna Chandra Mandal,<purna.mandal@microchip.com>
   4 * Copyright (C) 2015 Microchip Technology Inc.  All rights reserved.
   5 */
   6#include <linux/clk-provider.h>
   7#include <linux/delay.h>
   8#include <linux/device.h>
   9#include <linux/interrupt.h>
  10#include <linux/io.h>
  11#include <linux/iopoll.h>
  12#include <asm/mach-pic32/pic32.h>
  13#include <asm/traps.h>
  14
  15#include "clk-core.h"
  16
  17/* OSCCON Reg fields */
  18#define OSC_CUR_MASK		0x07
  19#define OSC_CUR_SHIFT		12
  20#define OSC_NEW_MASK		0x07
  21#define OSC_NEW_SHIFT		8
  22#define OSC_SWEN		BIT(0)
  23
  24/* SPLLCON Reg fields */
  25#define PLL_RANGE_MASK		0x07
  26#define PLL_RANGE_SHIFT		0
  27#define PLL_ICLK_MASK		0x01
  28#define PLL_ICLK_SHIFT		7
  29#define PLL_IDIV_MASK		0x07
  30#define PLL_IDIV_SHIFT		8
  31#define PLL_ODIV_MASK		0x07
  32#define PLL_ODIV_SHIFT		24
  33#define PLL_MULT_MASK		0x7F
  34#define PLL_MULT_SHIFT		16
  35#define PLL_MULT_MAX		128
  36#define PLL_ODIV_MIN		1
  37#define PLL_ODIV_MAX		5
  38
  39/* Peripheral Bus Clock Reg Fields */
  40#define PB_DIV_MASK		0x7f
  41#define PB_DIV_SHIFT		0
  42#define PB_DIV_READY		BIT(11)
  43#define PB_DIV_ENABLE		BIT(15)
  44#define PB_DIV_MAX		128
  45#define PB_DIV_MIN		0
  46
  47/* Reference Oscillator Control Reg fields */
  48#define REFO_SEL_MASK		0x0f
  49#define REFO_SEL_SHIFT		0
  50#define REFO_ACTIVE		BIT(8)
  51#define REFO_DIVSW_EN		BIT(9)
  52#define REFO_OE			BIT(12)
  53#define REFO_ON			BIT(15)
  54#define REFO_DIV_SHIFT		16
  55#define REFO_DIV_MASK		0x7fff
  56
  57/* Reference Oscillator Trim Register Fields */
  58#define REFO_TRIM_REG		0x10
  59#define REFO_TRIM_MASK		0x1ff
  60#define REFO_TRIM_SHIFT		23
  61#define REFO_TRIM_MAX		511
  62
  63/* Mux Slew Control Register fields */
  64#define SLEW_BUSY		BIT(0)
  65#define SLEW_DOWNEN		BIT(1)
  66#define SLEW_UPEN		BIT(2)
  67#define SLEW_DIV		0x07
  68#define SLEW_DIV_SHIFT		8
  69#define SLEW_SYSDIV		0x0f
  70#define SLEW_SYSDIV_SHIFT	20
  71
  72/* Clock Poll Timeout */
  73#define LOCK_TIMEOUT_US         USEC_PER_MSEC
  74
  75/* SoC specific clock needed during SPLL clock rate switch */
  76static struct clk_hw *pic32_sclk_hw;
  77
  78/* add instruction pipeline delay while CPU clock is in-transition. */
  79#define cpu_nop5()			\
  80do {					\
  81	__asm__ __volatile__("nop");	\
  82	__asm__ __volatile__("nop");	\
  83	__asm__ __volatile__("nop");	\
  84	__asm__ __volatile__("nop");	\
  85	__asm__ __volatile__("nop");	\
  86} while (0)
  87
  88/* Perpheral bus clocks */
  89struct pic32_periph_clk {
  90	struct clk_hw hw;
  91	void __iomem *ctrl_reg;
  92	struct pic32_clk_common *core;
  93};
  94
  95#define clkhw_to_pbclk(_hw)	container_of(_hw, struct pic32_periph_clk, hw)
  96
  97static int pbclk_is_enabled(struct clk_hw *hw)
  98{
  99	struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
 100
 101	return readl(pb->ctrl_reg) & PB_DIV_ENABLE;
 102}
 103
 104static int pbclk_enable(struct clk_hw *hw)
 105{
 106	struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
 107
 108	writel(PB_DIV_ENABLE, PIC32_SET(pb->ctrl_reg));
 109	return 0;
 110}
 111
 112static void pbclk_disable(struct clk_hw *hw)
 113{
 114	struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
 115
 116	writel(PB_DIV_ENABLE, PIC32_CLR(pb->ctrl_reg));
 117}
 118
 119static unsigned long calc_best_divided_rate(unsigned long rate,
 120					    unsigned long parent_rate,
 121					    u32 divider_max,
 122					    u32 divider_min)
 123{
 124	unsigned long divided_rate, divided_rate_down, best_rate;
 125	unsigned long div, div_up;
 126
 127	/* eq. clk_rate = parent_rate / divider.
 128	 *
 129	 * Find best divider to produce closest of target divided rate.
 130	 */
 131	div = parent_rate / rate;
 132	div = clamp_val(div, divider_min, divider_max);
 133	div_up = clamp_val(div + 1, divider_min, divider_max);
 134
 135	divided_rate = parent_rate / div;
 136	divided_rate_down = parent_rate / div_up;
 137	if (abs(rate - divided_rate_down) < abs(rate - divided_rate))
 138		best_rate = divided_rate_down;
 139	else
 140		best_rate = divided_rate;
 141
 142	return best_rate;
 143}
 144
 145static inline u32 pbclk_read_pbdiv(struct pic32_periph_clk *pb)
 146{
 147	return ((readl(pb->ctrl_reg) >> PB_DIV_SHIFT) & PB_DIV_MASK) + 1;
 148}
 149
 150static unsigned long pbclk_recalc_rate(struct clk_hw *hw,
 151				       unsigned long parent_rate)
 152{
 153	struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
 154
 155	return parent_rate / pbclk_read_pbdiv(pb);
 156}
 157
 158static int pbclk_determine_rate(struct clk_hw *hw,
 159				struct clk_rate_request *req)
 160{
 161	req->rate = calc_best_divided_rate(req->rate, req->best_parent_rate,
 162					   PB_DIV_MAX, PB_DIV_MIN);
 163
 164	return 0;
 165}
 166
 167static int pbclk_set_rate(struct clk_hw *hw, unsigned long rate,
 168			  unsigned long parent_rate)
 169{
 170	struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
 171	unsigned long flags;
 172	u32 v, div;
 173	int err;
 174
 175	/* check & wait for DIV_READY */
 176	err = readl_poll_timeout(pb->ctrl_reg, v, v & PB_DIV_READY,
 177				 1, LOCK_TIMEOUT_US);
 178	if (err)
 179		return err;
 180
 181	/* calculate clkdiv and best rate */
 182	div = DIV_ROUND_CLOSEST(parent_rate, rate);
 183
 184	spin_lock_irqsave(&pb->core->reg_lock, flags);
 185
 186	/* apply new div */
 187	v = readl(pb->ctrl_reg);
 188	v &= ~PB_DIV_MASK;
 189	v |= (div - 1);
 190
 191	pic32_syskey_unlock();
 192
 193	writel(v, pb->ctrl_reg);
 194
 195	spin_unlock_irqrestore(&pb->core->reg_lock, flags);
 196
 197	/* wait again for DIV_READY */
 198	err = readl_poll_timeout(pb->ctrl_reg, v, v & PB_DIV_READY,
 199				 1, LOCK_TIMEOUT_US);
 200	if (err)
 201		return err;
 202
 203	/* confirm that new div is applied correctly */
 204	return (pbclk_read_pbdiv(pb) == div) ? 0 : -EBUSY;
 205}
 206
 207const struct clk_ops pic32_pbclk_ops = {
 208	.enable		= pbclk_enable,
 209	.disable	= pbclk_disable,
 210	.is_enabled	= pbclk_is_enabled,
 211	.recalc_rate	= pbclk_recalc_rate,
 212	.determine_rate = pbclk_determine_rate,
 213	.set_rate	= pbclk_set_rate,
 214};
 215
 216struct clk *pic32_periph_clk_register(const struct pic32_periph_clk_data *desc,
 217				      struct pic32_clk_common *core)
 218{
 219	struct pic32_periph_clk *pbclk;
 220	struct clk *clk;
 221
 222	pbclk = devm_kzalloc(core->dev, sizeof(*pbclk), GFP_KERNEL);
 223	if (!pbclk)
 224		return ERR_PTR(-ENOMEM);
 225
 226	pbclk->hw.init = &desc->init_data;
 227	pbclk->core = core;
 228	pbclk->ctrl_reg = desc->ctrl_reg + core->iobase;
 229
 230	clk = devm_clk_register(core->dev, &pbclk->hw);
 231	if (IS_ERR(clk)) {
 232		dev_err(core->dev, "%s: clk_register() failed\n", __func__);
 233		devm_kfree(core->dev, pbclk);
 234	}
 235
 236	return clk;
 237}
 238
 239/* Reference oscillator operations */
 240struct pic32_ref_osc {
 241	struct clk_hw hw;
 242	void __iomem *ctrl_reg;
 243	const u32 *parent_map;
 244	struct pic32_clk_common *core;
 245};
 246
 247#define clkhw_to_refosc(_hw)	container_of(_hw, struct pic32_ref_osc, hw)
 248
 249static int roclk_is_enabled(struct clk_hw *hw)
 250{
 251	struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
 252
 253	return readl(refo->ctrl_reg) & REFO_ON;
 254}
 255
 256static int roclk_enable(struct clk_hw *hw)
 257{
 258	struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
 259
 260	writel(REFO_ON | REFO_OE, PIC32_SET(refo->ctrl_reg));
 261	return 0;
 262}
 263
 264static void roclk_disable(struct clk_hw *hw)
 265{
 266	struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
 267
 268	writel(REFO_ON | REFO_OE, PIC32_CLR(refo->ctrl_reg));
 269}
 270
 271static int roclk_init(struct clk_hw *hw)
 272{
 273	/* initialize clock in disabled state */
 274	roclk_disable(hw);
 275
 276	return 0;
 277}
 278
 279static u8 roclk_get_parent(struct clk_hw *hw)
 280{
 281	struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
 282	u32 v, i;
 283
 284	v = (readl(refo->ctrl_reg) >> REFO_SEL_SHIFT) & REFO_SEL_MASK;
 285
 286	if (refo->parent_map) {
 287		for (i = 0; i < clk_hw_get_num_parents(hw); i++)
 288			if (refo->parent_map[i] == v)
 289				return i;
 290	}
 291
 292	return v;
 293}
 294
 295static unsigned long roclk_calc_rate(unsigned long parent_rate,
 296				     u32 rodiv, u32 rotrim)
 297{
 298	u64 rate64;
 299
 300	/* fout = fin / [2 * {div + (trim / 512)}]
 301	 *	= fin * 512 / [1024 * div + 2 * trim]
 302	 *	= fin * 256 / (512 * div + trim)
 303	 *	= (fin << 8) / ((div << 9) + trim)
 304	 */
 305	if (rotrim) {
 306		rodiv = (rodiv << 9) + rotrim;
 307		rate64 = parent_rate;
 308		rate64 <<= 8;
 309		do_div(rate64, rodiv);
 310	} else if (rodiv) {
 311		rate64 = parent_rate / (rodiv << 1);
 312	} else {
 313		rate64 = parent_rate;
 314	}
 315	return rate64;
 316}
 317
 318static void roclk_calc_div_trim(unsigned long rate,
 319				unsigned long parent_rate,
 320				u32 *rodiv_p, u32 *rotrim_p)
 321{
 322	u32 div, rotrim, rodiv;
 323	u64 frac;
 324
 325	/* Find integer approximation of floating-point arithmetic.
 326	 *      fout = fin / [2 * {rodiv + (rotrim / 512)}] ... (1)
 327	 * i.e. fout = fin / 2 * DIV
 328	 *      whereas DIV = rodiv + (rotrim / 512)
 329	 *
 330	 * Since kernel does not perform floating-point arithmetic so
 331	 * (rotrim/512) will be zero. And DIV & rodiv will result same.
 332	 *
 333	 * ie. fout = (fin * 256) / [(512 * rodiv) + rotrim]  ... from (1)
 334	 * ie. rotrim = ((fin * 256) / fout) - (512 * DIV)
 335	 */
 336	if (parent_rate <= rate) {
 337		div = 0;
 338		frac = 0;
 339		rodiv = 0;
 340		rotrim = 0;
 341	} else {
 342		div = parent_rate / (rate << 1);
 343		frac = parent_rate;
 344		frac <<= 8;
 345		do_div(frac, rate);
 346		frac -= (u64)(div << 9);
 347
 348		rodiv = (div > REFO_DIV_MASK) ? REFO_DIV_MASK : div;
 349		rotrim = (frac >= REFO_TRIM_MAX) ? REFO_TRIM_MAX : frac;
 350	}
 351
 352	if (rodiv_p)
 353		*rodiv_p = rodiv;
 354
 355	if (rotrim_p)
 356		*rotrim_p = rotrim;
 357}
 358
 359static unsigned long roclk_recalc_rate(struct clk_hw *hw,
 360				       unsigned long parent_rate)
 361{
 362	struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
 363	u32 v, rodiv, rotrim;
 364
 365	/* get rodiv */
 366	v = readl(refo->ctrl_reg);
 367	rodiv = (v >> REFO_DIV_SHIFT) & REFO_DIV_MASK;
 368
 369	/* get trim */
 370	v = readl(refo->ctrl_reg + REFO_TRIM_REG);
 371	rotrim = (v >> REFO_TRIM_SHIFT) & REFO_TRIM_MASK;
 372
 373	return roclk_calc_rate(parent_rate, rodiv, rotrim);
 374}
 375
 376static int roclk_determine_rate(struct clk_hw *hw,
 377				struct clk_rate_request *req)
 378{
 379	struct clk_hw *parent_clk, *best_parent_clk = NULL;
 380	unsigned int i, delta, best_delta = -1;
 381	unsigned long parent_rate, best_parent_rate = 0;
 382	unsigned long best = 0, nearest_rate;
 383
 384	/* find a parent which can generate nearest clkrate >= rate */
 385	for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
 386		u32 rotrim, rodiv;
 387
 388		/* get parent */
 389		parent_clk = clk_hw_get_parent_by_index(hw, i);
 390		if (!parent_clk)
 391			continue;
 392
 393		/* skip if parent runs slower than target rate */
 394		parent_rate = clk_hw_get_rate(parent_clk);
 395		if (req->rate > parent_rate)
 396			continue;
 397
 398		/* calculate dividers for new rate */
 399		roclk_calc_div_trim(req->rate, req->best_parent_rate, &rodiv, &rotrim);
 400
 401		/* caclulate new rate (rounding) based on new rodiv & rotrim */
 402		nearest_rate = roclk_calc_rate(req->best_parent_rate, rodiv, rotrim);
 403
 404		delta = abs(nearest_rate - req->rate);
 405		if ((nearest_rate >= req->rate) && (delta < best_delta)) {
 406			best_parent_clk = parent_clk;
 407			best_parent_rate = parent_rate;
 408			best = nearest_rate;
 409			best_delta = delta;
 410
 411			if (delta == 0)
 412				break;
 413		}
 414	}
 415
 416	/* if no match found, retain old rate */
 417	if (!best_parent_clk) {
 418		pr_err("%s:%s, no parent found for rate %lu.\n",
 419		       __func__, clk_hw_get_name(hw), req->rate);
 420		return clk_hw_get_rate(hw);
 421	}
 422
 423	pr_debug("%s,rate %lu, best_parent(%s, %lu), best %lu, delta %d\n",
 424		 clk_hw_get_name(hw), req->rate,
 425		 clk_hw_get_name(best_parent_clk), best_parent_rate,
 426		 best, best_delta);
 427
 428	if (req->best_parent_rate)
 429		req->best_parent_rate = best_parent_rate;
 430
 431	if (req->best_parent_hw)
 432		req->best_parent_hw = best_parent_clk;
 433
 434	return best;
 435}
 436
 437static int roclk_set_parent(struct clk_hw *hw, u8 index)
 438{
 439	struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
 440	unsigned long flags;
 441	u32 v;
 442	int err;
 443
 444	if (refo->parent_map)
 445		index = refo->parent_map[index];
 446
 447	/* wait until ACTIVE bit is zero or timeout */
 448	err = readl_poll_timeout(refo->ctrl_reg, v, !(v & REFO_ACTIVE),
 449				 1, LOCK_TIMEOUT_US);
 450	if (err) {
 451		pr_err("%s: poll failed, clk active\n", clk_hw_get_name(hw));
 452		return err;
 453	}
 454
 455	spin_lock_irqsave(&refo->core->reg_lock, flags);
 456
 457	pic32_syskey_unlock();
 458
 459	/* calculate & apply new */
 460	v = readl(refo->ctrl_reg);
 461	v &= ~(REFO_SEL_MASK << REFO_SEL_SHIFT);
 462	v |= index << REFO_SEL_SHIFT;
 463
 464	writel(v, refo->ctrl_reg);
 465
 466	spin_unlock_irqrestore(&refo->core->reg_lock, flags);
 467
 468	return 0;
 469}
 470
 471static int roclk_set_rate_and_parent(struct clk_hw *hw,
 472				     unsigned long rate,
 473				     unsigned long parent_rate,
 474				     u8 index)
 475{
 476	struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
 477	unsigned long flags;
 478	u32 trim, rodiv, v;
 479	int err;
 480
 481	/* calculate new rodiv & rotrim for new rate */
 482	roclk_calc_div_trim(rate, parent_rate, &rodiv, &trim);
 483
 484	pr_debug("parent_rate = %lu, rate = %lu, div = %d, trim = %d\n",
 485		 parent_rate, rate, rodiv, trim);
 486
 487	/* wait till source change is active */
 488	err = readl_poll_timeout(refo->ctrl_reg, v,
 489				 !(v & (REFO_ACTIVE | REFO_DIVSW_EN)),
 490				 1, LOCK_TIMEOUT_US);
 491	if (err) {
 492		pr_err("%s: poll timedout, clock is still active\n", __func__);
 493		return err;
 494	}
 495
 496	spin_lock_irqsave(&refo->core->reg_lock, flags);
 497	v = readl(refo->ctrl_reg);
 498
 499	pic32_syskey_unlock();
 500
 501	/* apply parent, if required */
 502	if (refo->parent_map)
 503		index = refo->parent_map[index];
 504
 505	v &= ~(REFO_SEL_MASK << REFO_SEL_SHIFT);
 506	v |= index << REFO_SEL_SHIFT;
 507
 508	/* apply RODIV */
 509	v &= ~(REFO_DIV_MASK << REFO_DIV_SHIFT);
 510	v |= rodiv << REFO_DIV_SHIFT;
 511	writel(v, refo->ctrl_reg);
 512
 513	/* apply ROTRIM */
 514	v = readl(refo->ctrl_reg + REFO_TRIM_REG);
 515	v &= ~(REFO_TRIM_MASK << REFO_TRIM_SHIFT);
 516	v |= trim << REFO_TRIM_SHIFT;
 517	writel(v, refo->ctrl_reg + REFO_TRIM_REG);
 518
 519	/* enable & activate divider switching */
 520	writel(REFO_ON | REFO_DIVSW_EN, PIC32_SET(refo->ctrl_reg));
 521
 522	/* wait till divswen is in-progress */
 523	err = readl_poll_timeout_atomic(refo->ctrl_reg, v, !(v & REFO_DIVSW_EN),
 524					1, LOCK_TIMEOUT_US);
 525	/* leave the clk gated as it was */
 526	writel(REFO_ON, PIC32_CLR(refo->ctrl_reg));
 527
 528	spin_unlock_irqrestore(&refo->core->reg_lock, flags);
 529
 530	return err;
 531}
 532
 533static int roclk_set_rate(struct clk_hw *hw, unsigned long rate,
 534			  unsigned long parent_rate)
 535{
 536	u8 index = roclk_get_parent(hw);
 537
 538	return roclk_set_rate_and_parent(hw, rate, parent_rate, index);
 539}
 540
 541const struct clk_ops pic32_roclk_ops = {
 542	.enable			= roclk_enable,
 543	.disable		= roclk_disable,
 544	.is_enabled		= roclk_is_enabled,
 545	.get_parent		= roclk_get_parent,
 546	.set_parent		= roclk_set_parent,
 547	.determine_rate		= roclk_determine_rate,
 548	.recalc_rate		= roclk_recalc_rate,
 549	.set_rate_and_parent	= roclk_set_rate_and_parent,
 550	.set_rate		= roclk_set_rate,
 551	.init			= roclk_init,
 552};
 553
 554struct clk *pic32_refo_clk_register(const struct pic32_ref_osc_data *data,
 555				    struct pic32_clk_common *core)
 556{
 557	struct pic32_ref_osc *refo;
 558	struct clk *clk;
 559
 560	refo = devm_kzalloc(core->dev, sizeof(*refo), GFP_KERNEL);
 561	if (!refo)
 562		return ERR_PTR(-ENOMEM);
 563
 564	refo->core = core;
 565	refo->hw.init = &data->init_data;
 566	refo->ctrl_reg = data->ctrl_reg + core->iobase;
 567	refo->parent_map = data->parent_map;
 568
 569	clk = devm_clk_register(core->dev, &refo->hw);
 570	if (IS_ERR(clk))
 571		dev_err(core->dev, "%s: clk_register() failed\n", __func__);
 572
 573	return clk;
 574}
 575
 576struct pic32_sys_pll {
 577	struct clk_hw hw;
 578	void __iomem *ctrl_reg;
 579	void __iomem *status_reg;
 580	u32 lock_mask;
 581	u32 idiv; /* PLL iclk divider, treated fixed */
 582	struct pic32_clk_common *core;
 583};
 584
 585#define clkhw_to_spll(_hw)	container_of(_hw, struct pic32_sys_pll, hw)
 586
 587static inline u32 spll_odiv_to_divider(u32 odiv)
 588{
 589	odiv = clamp_val(odiv, PLL_ODIV_MIN, PLL_ODIV_MAX);
 590
 591	return 1 << odiv;
 592}
 593
 594static unsigned long spll_calc_mult_div(struct pic32_sys_pll *pll,
 595					unsigned long rate,
 596					unsigned long parent_rate,
 597					u32 *mult_p, u32 *odiv_p)
 598{
 599	u32 mul, div, best_mul = 1, best_div = 1;
 600	unsigned long new_rate, best_rate = rate;
 601	unsigned int best_delta = -1, delta, match_found = 0;
 602	u64 rate64;
 603
 604	parent_rate /= pll->idiv;
 605
 606	for (mul = 1; mul <= PLL_MULT_MAX; mul++) {
 607		for (div = PLL_ODIV_MIN; div <= PLL_ODIV_MAX; div++) {
 608			rate64 = parent_rate;
 609			rate64 *= mul;
 610			do_div(rate64, 1 << div);
 611			new_rate = rate64;
 612			delta = abs(rate - new_rate);
 613			if ((new_rate >= rate) && (delta < best_delta)) {
 614				best_delta = delta;
 615				best_rate = new_rate;
 616				best_mul = mul;
 617				best_div = div;
 618				match_found = 1;
 619			}
 620		}
 621	}
 622
 623	if (!match_found) {
 624		pr_warn("spll: no match found\n");
 625		return 0;
 626	}
 627
 628	pr_debug("rate %lu, par_rate %lu/mult %u, div %u, best_rate %lu\n",
 629		 rate, parent_rate, best_mul, best_div, best_rate);
 630
 631	if (mult_p)
 632		*mult_p = best_mul - 1;
 633
 634	if (odiv_p)
 635		*odiv_p = best_div;
 636
 637	return best_rate;
 638}
 639
 640static unsigned long spll_clk_recalc_rate(struct clk_hw *hw,
 641					  unsigned long parent_rate)
 642{
 643	struct pic32_sys_pll *pll = clkhw_to_spll(hw);
 644	unsigned long pll_in_rate;
 645	u32 mult, odiv, div, v;
 646	u64 rate64;
 647
 648	v = readl(pll->ctrl_reg);
 649	odiv = ((v >> PLL_ODIV_SHIFT) & PLL_ODIV_MASK);
 650	mult = ((v >> PLL_MULT_SHIFT) & PLL_MULT_MASK) + 1;
 651	div = spll_odiv_to_divider(odiv);
 652
 653	/* pll_in_rate = parent_rate / idiv
 654	 * pll_out_rate = pll_in_rate * mult / div;
 655	 */
 656	pll_in_rate = parent_rate / pll->idiv;
 657	rate64 = pll_in_rate;
 658	rate64 *= mult;
 659	do_div(rate64, div);
 660
 661	return rate64;
 662}
 663
 664static int spll_clk_determine_rate(struct clk_hw *hw,
 665				   struct clk_rate_request *req)
 666{
 667	struct pic32_sys_pll *pll = clkhw_to_spll(hw);
 668
 669	req->rate = spll_calc_mult_div(pll, req->rate, req->best_parent_rate,
 670				       NULL, NULL);
 671
 672	return 0;
 673}
 674
 675static int spll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 676			     unsigned long parent_rate)
 677{
 678	struct pic32_sys_pll *pll = clkhw_to_spll(hw);
 679	unsigned long ret, flags;
 680	u32 mult, odiv, v;
 681	int err;
 682
 683	ret = spll_calc_mult_div(pll, rate, parent_rate, &mult, &odiv);
 684	if (!ret)
 685		return -EINVAL;
 686
 687	/*
 688	 * We can't change SPLL counters when it is in-active use
 689	 * by SYSCLK. So check before applying new counters/rate.
 690	 */
 691
 692	/* Is spll_clk active parent of sys_clk ? */
 693	if (unlikely(clk_hw_get_parent(pic32_sclk_hw) == hw)) {
 694		pr_err("%s: failed, clk in-use\n", __func__);
 695		return -EBUSY;
 696	}
 697
 698	spin_lock_irqsave(&pll->core->reg_lock, flags);
 699
 700	/* apply new multiplier & divisor */
 701	v = readl(pll->ctrl_reg);
 702	v &= ~(PLL_MULT_MASK << PLL_MULT_SHIFT);
 703	v &= ~(PLL_ODIV_MASK << PLL_ODIV_SHIFT);
 704	v |= (mult << PLL_MULT_SHIFT) | (odiv << PLL_ODIV_SHIFT);
 705
 706	/* sys unlock before write */
 707	pic32_syskey_unlock();
 708
 709	writel(v, pll->ctrl_reg);
 710	cpu_relax();
 711
 712	/* insert few nops (5-stage) to ensure CPU does not hang */
 713	cpu_nop5();
 714	cpu_nop5();
 715
 716	/* Wait until PLL is locked (maximum 100 usecs). */
 717	err = readl_poll_timeout_atomic(pll->status_reg, v,
 718					v & pll->lock_mask, 1, 100);
 719	spin_unlock_irqrestore(&pll->core->reg_lock, flags);
 720
 721	return err;
 722}
 723
 724/* SPLL clock operation */
 725const struct clk_ops pic32_spll_ops = {
 726	.recalc_rate	= spll_clk_recalc_rate,
 727	.determine_rate = spll_clk_determine_rate,
 728	.set_rate	= spll_clk_set_rate,
 729};
 730
 731struct clk *pic32_spll_clk_register(const struct pic32_sys_pll_data *data,
 732				    struct pic32_clk_common *core)
 733{
 734	struct pic32_sys_pll *spll;
 735	struct clk *clk;
 736
 737	spll = devm_kzalloc(core->dev, sizeof(*spll), GFP_KERNEL);
 738	if (!spll)
 739		return ERR_PTR(-ENOMEM);
 740
 741	spll->core = core;
 742	spll->hw.init = &data->init_data;
 743	spll->ctrl_reg = data->ctrl_reg + core->iobase;
 744	spll->status_reg = data->status_reg + core->iobase;
 745	spll->lock_mask = data->lock_mask;
 746
 747	/* cache PLL idiv; PLL driver uses it as constant.*/
 748	spll->idiv = (readl(spll->ctrl_reg) >> PLL_IDIV_SHIFT) & PLL_IDIV_MASK;
 749	spll->idiv += 1;
 750
 751	clk = devm_clk_register(core->dev, &spll->hw);
 752	if (IS_ERR(clk))
 753		dev_err(core->dev, "sys_pll: clk_register() failed\n");
 754
 755	return clk;
 756}
 757
 758/* System mux clock(aka SCLK) */
 759
 760struct pic32_sys_clk {
 761	struct clk_hw hw;
 762	void __iomem *mux_reg;
 763	void __iomem *slew_reg;
 764	u32 slew_div;
 765	const u32 *parent_map;
 766	struct pic32_clk_common *core;
 767};
 768
 769#define clkhw_to_sys_clk(_hw)	container_of(_hw, struct pic32_sys_clk, hw)
 770
 771static unsigned long sclk_get_rate(struct clk_hw *hw, unsigned long parent_rate)
 772{
 773	struct pic32_sys_clk *sclk = clkhw_to_sys_clk(hw);
 774	u32 div;
 775
 776	div = (readl(sclk->slew_reg) >> SLEW_SYSDIV_SHIFT) & SLEW_SYSDIV;
 777	div += 1; /* sys-div to divider */
 778
 779	return parent_rate / div;
 780}
 781
 782static int sclk_set_rate(struct clk_hw *hw,
 783			 unsigned long rate, unsigned long parent_rate)
 784{
 785	struct pic32_sys_clk *sclk = clkhw_to_sys_clk(hw);
 786	unsigned long flags;
 787	u32 v, div;
 788	int err;
 789
 790	div = parent_rate / rate;
 791
 792	spin_lock_irqsave(&sclk->core->reg_lock, flags);
 793
 794	/* apply new div */
 795	v = readl(sclk->slew_reg);
 796	v &= ~(SLEW_SYSDIV << SLEW_SYSDIV_SHIFT);
 797	v |= (div - 1) << SLEW_SYSDIV_SHIFT;
 798
 799	pic32_syskey_unlock();
 800
 801	writel(v, sclk->slew_reg);
 802
 803	/* wait until BUSY is cleared */
 804	err = readl_poll_timeout_atomic(sclk->slew_reg, v,
 805					!(v & SLEW_BUSY), 1, LOCK_TIMEOUT_US);
 806
 807	spin_unlock_irqrestore(&sclk->core->reg_lock, flags);
 808
 809	return err;
 810}
 811
 812static u8 sclk_get_parent(struct clk_hw *hw)
 813{
 814	struct pic32_sys_clk *sclk = clkhw_to_sys_clk(hw);
 815	u32 i, v;
 816
 817	v = (readl(sclk->mux_reg) >> OSC_CUR_SHIFT) & OSC_CUR_MASK;
 818
 819	if (sclk->parent_map) {
 820		for (i = 0; i < clk_hw_get_num_parents(hw); i++)
 821			if (sclk->parent_map[i] == v)
 822				return i;
 823	}
 824
 825	return v;
 826}
 827
 828static int sclk_set_parent(struct clk_hw *hw, u8 index)
 829{
 830	struct pic32_sys_clk *sclk = clkhw_to_sys_clk(hw);
 831	unsigned long flags;
 832	u32 nosc, cosc, v;
 833	int err;
 834
 835	spin_lock_irqsave(&sclk->core->reg_lock, flags);
 836
 837	/* find new_osc */
 838	nosc = sclk->parent_map ? sclk->parent_map[index] : index;
 839
 840	/* set new parent */
 841	v = readl(sclk->mux_reg);
 842	v &= ~(OSC_NEW_MASK << OSC_NEW_SHIFT);
 843	v |= nosc << OSC_NEW_SHIFT;
 844
 845	pic32_syskey_unlock();
 846
 847	writel(v, sclk->mux_reg);
 848
 849	/* initate switch */
 850	writel(OSC_SWEN, PIC32_SET(sclk->mux_reg));
 851	cpu_relax();
 852
 853	/* add nop to flush pipeline (as cpu_clk is in-flux) */
 854	cpu_nop5();
 855
 856	/* wait for SWEN bit to clear */
 857	err = readl_poll_timeout_atomic(sclk->slew_reg, v,
 858					!(v & OSC_SWEN), 1, LOCK_TIMEOUT_US);
 859
 860	spin_unlock_irqrestore(&sclk->core->reg_lock, flags);
 861
 862	/*
 863	 * SCLK clock-switching logic might reject a clock switching request
 864	 * if pre-requisites (like new clk_src not present or unstable) are
 865	 * not met.
 866	 * So confirm before claiming success.
 867	 */
 868	cosc = (readl(sclk->mux_reg) >> OSC_CUR_SHIFT) & OSC_CUR_MASK;
 869	if (cosc != nosc) {
 870		pr_err("%s: err, failed to set_parent() to %d, current %d\n",
 871		       clk_hw_get_name(hw), nosc, cosc);
 872		err = -EBUSY;
 873	}
 874
 875	return err;
 876}
 877
 878static int sclk_init(struct clk_hw *hw)
 879{
 880	struct pic32_sys_clk *sclk = clkhw_to_sys_clk(hw);
 881	unsigned long flags;
 882	u32 v;
 883
 884	/* Maintain reference to this clk, required in spll_clk_set_rate() */
 885	pic32_sclk_hw = hw;
 886
 887	/* apply slew divider on both up and down scaling */
 888	if (sclk->slew_div) {
 889		spin_lock_irqsave(&sclk->core->reg_lock, flags);
 890		v = readl(sclk->slew_reg);
 891		v &= ~(SLEW_DIV << SLEW_DIV_SHIFT);
 892		v |= sclk->slew_div << SLEW_DIV_SHIFT;
 893		v |= SLEW_DOWNEN | SLEW_UPEN;
 894		writel(v, sclk->slew_reg);
 895		spin_unlock_irqrestore(&sclk->core->reg_lock, flags);
 896	}
 897
 898	return 0;
 899}
 900
 901/* sclk with post-divider */
 902const struct clk_ops pic32_sclk_ops = {
 903	.get_parent	= sclk_get_parent,
 904	.set_parent	= sclk_set_parent,
 905	.set_rate	= sclk_set_rate,
 906	.recalc_rate	= sclk_get_rate,
 907	.init		= sclk_init,
 908	.determine_rate = __clk_mux_determine_rate,
 909};
 910
 911/* sclk with no slew and no post-divider */
 912const struct clk_ops pic32_sclk_no_div_ops = {
 913	.get_parent	= sclk_get_parent,
 914	.set_parent	= sclk_set_parent,
 915	.init		= sclk_init,
 916	.determine_rate = __clk_mux_determine_rate,
 917};
 918
 919struct clk *pic32_sys_clk_register(const struct pic32_sys_clk_data *data,
 920				   struct pic32_clk_common *core)
 921{
 922	struct pic32_sys_clk *sclk;
 923	struct clk *clk;
 924
 925	sclk = devm_kzalloc(core->dev, sizeof(*sclk), GFP_KERNEL);
 926	if (!sclk)
 927		return ERR_PTR(-ENOMEM);
 928
 929	sclk->core = core;
 930	sclk->hw.init = &data->init_data;
 931	sclk->mux_reg = data->mux_reg + core->iobase;
 932	sclk->slew_reg = data->slew_reg + core->iobase;
 933	sclk->slew_div = data->slew_div;
 934	sclk->parent_map = data->parent_map;
 935
 936	clk = devm_clk_register(core->dev, &sclk->hw);
 937	if (IS_ERR(clk))
 938		dev_err(core->dev, "%s: clk register failed\n", __func__);
 939
 940	return clk;
 941}
 942
 943/* secondary oscillator */
 944struct pic32_sec_osc {
 945	struct clk_hw hw;
 946	void __iomem *enable_reg;
 947	void __iomem *status_reg;
 948	u32 enable_mask;
 949	u32 status_mask;
 950	unsigned long fixed_rate;
 951	struct pic32_clk_common *core;
 952};
 953
 954#define clkhw_to_sosc(_hw)	container_of(_hw, struct pic32_sec_osc, hw)
 955static int sosc_clk_enable(struct clk_hw *hw)
 956{
 957	struct pic32_sec_osc *sosc = clkhw_to_sosc(hw);
 958	u32 v;
 959
 960	/* enable SOSC */
 961	pic32_syskey_unlock();
 962	writel(sosc->enable_mask, PIC32_SET(sosc->enable_reg));
 963
 964	/* wait till warm-up period expires or ready-status is updated */
 965	return readl_poll_timeout_atomic(sosc->status_reg, v,
 966					 v & sosc->status_mask, 1, 100);
 967}
 968
 969static void sosc_clk_disable(struct clk_hw *hw)
 970{
 971	struct pic32_sec_osc *sosc = clkhw_to_sosc(hw);
 972
 973	pic32_syskey_unlock();
 974	writel(sosc->enable_mask, PIC32_CLR(sosc->enable_reg));
 975}
 976
 977static int sosc_clk_is_enabled(struct clk_hw *hw)
 978{
 979	struct pic32_sec_osc *sosc = clkhw_to_sosc(hw);
 980	u32 enabled, ready;
 981
 982	/* check enabled and ready status */
 983	enabled = readl(sosc->enable_reg) & sosc->enable_mask;
 984	ready = readl(sosc->status_reg) & sosc->status_mask;
 985
 986	return enabled && ready;
 987}
 988
 989static unsigned long sosc_clk_calc_rate(struct clk_hw *hw,
 990					unsigned long parent_rate)
 991{
 992	return clkhw_to_sosc(hw)->fixed_rate;
 993}
 994
 995const struct clk_ops pic32_sosc_ops = {
 996	.enable = sosc_clk_enable,
 997	.disable = sosc_clk_disable,
 998	.is_enabled = sosc_clk_is_enabled,
 999	.recalc_rate = sosc_clk_calc_rate,
1000};
1001
1002struct clk *pic32_sosc_clk_register(const struct pic32_sec_osc_data *data,
1003				    struct pic32_clk_common *core)
1004{
1005	struct pic32_sec_osc *sosc;
1006
1007	sosc = devm_kzalloc(core->dev, sizeof(*sosc), GFP_KERNEL);
1008	if (!sosc)
1009		return ERR_PTR(-ENOMEM);
1010
1011	sosc->core = core;
1012	sosc->hw.init = &data->init_data;
1013	sosc->fixed_rate = data->fixed_rate;
1014	sosc->enable_mask = data->enable_mask;
1015	sosc->status_mask = data->status_mask;
1016	sosc->enable_reg = data->enable_reg + core->iobase;
1017	sosc->status_reg = data->status_reg + core->iobase;
1018
1019	return devm_clk_register(core->dev, &sosc->hw);
1020}
~/ Read-only file preview.