clk.c 14.9 KB
Newer Older
1 2 3 4
/*
 * Copyright (c) 2014 MundoReader S.L.
 * Author: Heiko Stuebner <heiko@sntech.de>
 *
5 6 7
 * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
 * Author: Xing Zheng <zhengxing@rock-chips.com>
 *
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
 * based on
 *
 * samsung/clk.c
 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
 * Copyright (c) 2013 Linaro Ltd.
 * Author: Thomas Abraham <thomas.ab@samsung.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
29 30
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
31
#include <linux/reboot.h>
32 33 34 35 36 37 38 39 40 41 42 43
#include "clk.h"

/**
 * Register a clock branch.
 * Most clock branches have a form like
 *
 * src1 --|--\
 *        |M |--[GATE]-[DIV]-
 * src2 --|--/
 *
 * sometimes without one of those components.
 */
44
static struct clk *rockchip_clk_register_branch(const char *name,
45 46
		const char *const *parent_names, u8 num_parents,
		void __iomem *base,
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
		int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags,
		u8 div_shift, u8 div_width, u8 div_flags,
		struct clk_div_table *div_table, int gate_offset,
		u8 gate_shift, u8 gate_flags, unsigned long flags,
		spinlock_t *lock)
{
	struct clk *clk;
	struct clk_mux *mux = NULL;
	struct clk_gate *gate = NULL;
	struct clk_divider *div = NULL;
	const struct clk_ops *mux_ops = NULL, *div_ops = NULL,
			     *gate_ops = NULL;

	if (num_parents > 1) {
		mux = kzalloc(sizeof(*mux), GFP_KERNEL);
		if (!mux)
			return ERR_PTR(-ENOMEM);

		mux->reg = base + muxdiv_offset;
		mux->shift = mux_shift;
		mux->mask = BIT(mux_width) - 1;
		mux->flags = mux_flags;
		mux->lock = lock;
		mux_ops = (mux_flags & CLK_MUX_READ_ONLY) ? &clk_mux_ro_ops
							: &clk_mux_ops;
	}

	if (gate_offset >= 0) {
		gate = kzalloc(sizeof(*gate), GFP_KERNEL);
		if (!gate)
77
			goto err_gate;
78 79 80 81 82 83 84 85 86 87 88

		gate->flags = gate_flags;
		gate->reg = base + gate_offset;
		gate->bit_idx = gate_shift;
		gate->lock = lock;
		gate_ops = &clk_gate_ops;
	}

	if (div_width > 0) {
		div = kzalloc(sizeof(*div), GFP_KERNEL);
		if (!div)
89
			goto err_div;
90 91 92 93 94 95 96

		div->flags = div_flags;
		div->reg = base + muxdiv_offset;
		div->shift = div_shift;
		div->width = div_width;
		div->lock = lock;
		div->table = div_table;
97 98 99
		div_ops = (div_flags & CLK_DIVIDER_READ_ONLY)
						? &clk_divider_ro_ops
						: &clk_divider_ops;
100 101 102 103 104 105 106 107 108
	}

	clk = clk_register_composite(NULL, name, parent_names, num_parents,
				     mux ? &mux->hw : NULL, mux_ops,
				     div ? &div->hw : NULL, div_ops,
				     gate ? &gate->hw : NULL, gate_ops,
				     flags);

	return clk;
109 110 111 112 113
err_div:
	kfree(gate);
err_gate:
	kfree(mux);
	return ERR_PTR(-ENOMEM);
114 115
}

116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
struct rockchip_clk_frac {
	struct notifier_block			clk_nb;
	struct clk_fractional_divider		div;
	struct clk_gate				gate;

	struct clk_mux				mux;
	const struct clk_ops			*mux_ops;
	int					mux_frac_idx;

	bool					rate_change_remuxed;
	int					rate_change_idx;
};

#define to_rockchip_clk_frac_nb(nb) \
			container_of(nb, struct rockchip_clk_frac, clk_nb)

static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb,
					 unsigned long event, void *data)
{
	struct clk_notifier_data *ndata = data;
	struct rockchip_clk_frac *frac = to_rockchip_clk_frac_nb(nb);
	struct clk_mux *frac_mux = &frac->mux;
	int ret = 0;

	pr_debug("%s: event %lu, old_rate %lu, new_rate: %lu\n",
		 __func__, event, ndata->old_rate, ndata->new_rate);
	if (event == PRE_RATE_CHANGE) {
143 144
		frac->rate_change_idx =
				frac->mux_ops->get_parent(&frac_mux->hw);
145
		if (frac->rate_change_idx != frac->mux_frac_idx) {
146 147
			frac->mux_ops->set_parent(&frac_mux->hw,
						  frac->mux_frac_idx);
148 149 150 151 152 153 154 155 156 157
			frac->rate_change_remuxed = 1;
		}
	} else if (event == POST_RATE_CHANGE) {
		/*
		 * The POST_RATE_CHANGE notifier runs directly after the
		 * divider clock is set in clk_change_rate, so we'll have
		 * remuxed back to the original parent before clk_change_rate
		 * reaches the mux itself.
		 */
		if (frac->rate_change_remuxed) {
158 159
			frac->mux_ops->set_parent(&frac_mux->hw,
						  frac->rate_change_idx);
160 161 162 163 164 165 166
			frac->rate_change_remuxed = 0;
		}
	}

	return notifier_from_errno(ret);
}

167 168
static struct clk *rockchip_clk_register_frac_branch(
		struct rockchip_clk_provider *ctx, const char *name,
169 170
		const char *const *parent_names, u8 num_parents,
		void __iomem *base, int muxdiv_offset, u8 div_flags,
171
		int gate_offset, u8 gate_shift, u8 gate_flags,
172 173
		unsigned long flags, struct rockchip_clk_branch *child,
		spinlock_t *lock)
174
{
175
	struct rockchip_clk_frac *frac;
176 177 178 179 180
	struct clk *clk;
	struct clk_gate *gate = NULL;
	struct clk_fractional_divider *div = NULL;
	const struct clk_ops *div_ops = NULL, *gate_ops = NULL;

181 182 183 184 185 186 187 188
	if (muxdiv_offset < 0)
		return ERR_PTR(-EINVAL);

	if (child && child->branch_type != branch_mux) {
		pr_err("%s: fractional child clock for %s can only be a mux\n",
		       __func__, name);
		return ERR_PTR(-EINVAL);
	}
189

190 191 192 193 194 195
	frac = kzalloc(sizeof(*frac), GFP_KERNEL);
	if (!frac)
		return ERR_PTR(-ENOMEM);

	if (gate_offset >= 0) {
		gate = &frac->gate;
196 197 198 199 200 201 202
		gate->flags = gate_flags;
		gate->reg = base + gate_offset;
		gate->bit_idx = gate_shift;
		gate->lock = lock;
		gate_ops = &clk_gate_ops;
	}

203
	div = &frac->div;
204 205 206
	div->flags = div_flags;
	div->reg = base + muxdiv_offset;
	div->mshift = 16;
207 208
	div->mwidth = 16;
	div->mmask = GENMASK(div->mwidth - 1, 0) << div->mshift;
209
	div->nshift = 0;
210 211
	div->nwidth = 16;
	div->nmask = GENMASK(div->nwidth - 1, 0) << div->nshift;
212 213 214 215 216 217 218
	div->lock = lock;
	div_ops = &clk_fractional_divider_ops;

	clk = clk_register_composite(NULL, name, parent_names, num_parents,
				     NULL, NULL,
				     &div->hw, div_ops,
				     gate ? &gate->hw : NULL, gate_ops,
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
				     flags | CLK_SET_RATE_UNGATE);
	if (IS_ERR(clk)) {
		kfree(frac);
		return clk;
	}

	if (child) {
		struct clk_mux *frac_mux = &frac->mux;
		struct clk_init_data init;
		struct clk *mux_clk;
		int i, ret;

		frac->mux_frac_idx = -1;
		for (i = 0; i < child->num_parents; i++) {
			if (!strcmp(name, child->parent_names[i])) {
				pr_debug("%s: found fractional parent in mux at pos %d\n",
					 __func__, i);
				frac->mux_frac_idx = i;
				break;
			}
		}

		frac->mux_ops = &clk_mux_ops;
		frac->clk_nb.notifier_call = rockchip_clk_frac_notifier_cb;

		frac_mux->reg = base + child->muxdiv_offset;
		frac_mux->shift = child->mux_shift;
		frac_mux->mask = BIT(child->mux_width) - 1;
		frac_mux->flags = child->mux_flags;
		frac_mux->lock = lock;
		frac_mux->hw.init = &init;

		init.name = child->name;
		init.flags = child->flags | CLK_SET_RATE_PARENT;
		init.ops = frac->mux_ops;
		init.parent_names = child->parent_names;
		init.num_parents = child->num_parents;

		mux_clk = clk_register(NULL, &frac_mux->hw);
		if (IS_ERR(mux_clk))
			return clk;

261
		rockchip_clk_add_lookup(ctx, mux_clk, child->id);
262 263 264 265 266 267 268 269 270 271 272 273

		/* notifier on the fraction divider to catch rate changes */
		if (frac->mux_frac_idx >= 0) {
			ret = clk_notifier_register(clk, &frac->clk_nb);
			if (ret)
				pr_err("%s: failed to register clock notifier for %s\n",
						__func__, name);
		} else {
			pr_warn("%s: could not find %s as parent of %s, rate changes may not work\n",
				__func__, name, child->name);
		}
	}
274 275 276 277

	return clk;
}

278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
static struct clk *rockchip_clk_register_factor_branch(const char *name,
		const char *const *parent_names, u8 num_parents,
		void __iomem *base, unsigned int mult, unsigned int div,
		int gate_offset, u8 gate_shift, u8 gate_flags,
		unsigned long flags, spinlock_t *lock)
{
	struct clk *clk;
	struct clk_gate *gate = NULL;
	struct clk_fixed_factor *fix = NULL;

	/* without gate, register a simple factor clock */
	if (gate_offset == 0) {
		return clk_register_fixed_factor(NULL, name,
				parent_names[0], flags, mult,
				div);
	}

	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
	if (!gate)
		return ERR_PTR(-ENOMEM);

	gate->flags = gate_flags;
	gate->reg = base + gate_offset;
	gate->bit_idx = gate_shift;
	gate->lock = lock;

	fix = kzalloc(sizeof(*fix), GFP_KERNEL);
	if (!fix) {
		kfree(gate);
		return ERR_PTR(-ENOMEM);
	}

	fix->mult = mult;
	fix->div = div;

	clk = clk_register_composite(NULL, name, parent_names, num_parents,
				     NULL, NULL,
				     &fix->hw, &clk_fixed_factor_ops,
				     &gate->hw, &clk_gate_ops, flags);
	if (IS_ERR(clk)) {
		kfree(fix);
		kfree(gate);
	}

	return clk;
}

325 326
struct rockchip_clk_provider * __init rockchip_clk_init(struct device_node *np,
			void __iomem *base, unsigned long nr_clks)
327
{
328 329 330 331 332
	struct rockchip_clk_provider *ctx;
	struct clk **clk_table;
	int i;

	ctx = kzalloc(sizeof(struct rockchip_clk_provider), GFP_KERNEL);
333
	if (!ctx)
334
		return ERR_PTR(-ENOMEM);
335 336

	clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
337
	if (!clk_table)
338 339 340 341
		goto err_free;

	for (i = 0; i < nr_clks; ++i)
		clk_table[i] = ERR_PTR(-ENOENT);
342

343 344 345 346 347 348 349
	ctx->reg_base = base;
	ctx->clk_data.clks = clk_table;
	ctx->clk_data.clk_num = nr_clks;
	ctx->cru_node = np;
	ctx->grf = ERR_PTR(-EPROBE_DEFER);
	spin_lock_init(&ctx->lock);

350 351 352
	ctx->grf = syscon_regmap_lookup_by_phandle(ctx->cru_node,
						   "rockchip,grf");

353 354 355 356 357 358 359 360 361 362
	return ctx;

err_free:
	kfree(ctx);
	return ERR_PTR(-ENOMEM);
}

void __init rockchip_clk_of_add_provider(struct device_node *np,
				struct rockchip_clk_provider *ctx)
{
363 364 365
	if (of_clk_add_provider(np, of_clk_src_onecell_get,
				&ctx->clk_data))
		pr_err("%s: could not register clk provider\n", __func__);
366 367
}

368 369
void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx,
			     struct clk *clk, unsigned int id)
370
{
371 372
	if (ctx->clk_data.clks && id)
		ctx->clk_data.clks[id] = clk;
373 374
}

375 376
void __init rockchip_clk_register_plls(struct rockchip_clk_provider *ctx,
				struct rockchip_pll_clock *list,
377 378 379 380 381 382
				unsigned int nr_pll, int grf_lock_offset)
{
	struct clk *clk;
	int idx;

	for (idx = 0; idx < nr_pll; idx++, list++) {
383
		clk = rockchip_clk_register_pll(ctx, list->type, list->name,
384
				list->parent_names, list->num_parents,
385
				list->con_offset, grf_lock_offset,
386
				list->lock_shift, list->mode_offset,
387
				list->mode_shift, list->rate_table,
388
				list->flags, list->pll_flags);
389 390 391 392 393 394
		if (IS_ERR(clk)) {
			pr_err("%s: failed to register clock %s\n", __func__,
				list->name);
			continue;
		}

395
		rockchip_clk_add_lookup(ctx, clk, list->id);
396 397 398
	}
}

399
void __init rockchip_clk_register_branches(
400
				      struct rockchip_clk_provider *ctx,
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
				      struct rockchip_clk_branch *list,
				      unsigned int nr_clk)
{
	struct clk *clk = NULL;
	unsigned int idx;
	unsigned long flags;

	for (idx = 0; idx < nr_clk; idx++, list++) {
		flags = list->flags;

		/* catch simple muxes */
		switch (list->branch_type) {
		case branch_mux:
			clk = clk_register_mux(NULL, list->name,
				list->parent_names, list->num_parents,
416
				flags, ctx->reg_base + list->muxdiv_offset,
417
				list->mux_shift, list->mux_width,
418
				list->mux_flags, &ctx->lock);
419 420 421 422 423
			break;
		case branch_divider:
			if (list->div_table)
				clk = clk_register_divider_table(NULL,
					list->name, list->parent_names[0],
424 425
					flags,
					ctx->reg_base + list->muxdiv_offset,
426 427
					list->div_shift, list->div_width,
					list->div_flags, list->div_table,
428
					&ctx->lock);
429 430 431
			else
				clk = clk_register_divider(NULL, list->name,
					list->parent_names[0], flags,
432
					ctx->reg_base + list->muxdiv_offset,
433
					list->div_shift, list->div_width,
434
					list->div_flags, &ctx->lock);
435 436
			break;
		case branch_fraction_divider:
437
			clk = rockchip_clk_register_frac_branch(ctx, list->name,
438
				list->parent_names, list->num_parents,
439 440
				ctx->reg_base, list->muxdiv_offset,
				list->div_flags,
441
				list->gate_offset, list->gate_shift,
442
				list->gate_flags, flags, list->child,
443
				&ctx->lock);
444 445 446 447 448 449
			break;
		case branch_gate:
			flags |= CLK_SET_RATE_PARENT;

			clk = clk_register_gate(NULL, list->name,
				list->parent_names[0], flags,
450 451
				ctx->reg_base + list->gate_offset,
				list->gate_shift, list->gate_flags, &ctx->lock);
452 453 454 455
			break;
		case branch_composite:
			clk = rockchip_clk_register_branch(list->name,
				list->parent_names, list->num_parents,
456 457
				ctx->reg_base, list->muxdiv_offset,
				list->mux_shift,
458 459 460 461
				list->mux_width, list->mux_flags,
				list->div_shift, list->div_width,
				list->div_flags, list->div_table,
				list->gate_offset, list->gate_shift,
462
				list->gate_flags, flags, &ctx->lock);
463
			break;
464 465 466 467
		case branch_mmc:
			clk = rockchip_clk_register_mmc(
				list->name,
				list->parent_names, list->num_parents,
468
				ctx->reg_base + list->muxdiv_offset,
469 470 471
				list->div_shift
			);
			break;
472 473 474 475
		case branch_inverter:
			clk = rockchip_clk_register_inverter(
				list->name, list->parent_names,
				list->num_parents,
476 477
				ctx->reg_base + list->muxdiv_offset,
				list->div_shift, list->div_flags, &ctx->lock);
478
			break;
479 480 481
		case branch_factor:
			clk = rockchip_clk_register_factor_branch(
				list->name, list->parent_names,
482
				list->num_parents, ctx->reg_base,
483 484
				list->div_shift, list->div_width,
				list->gate_offset, list->gate_shift,
485
				list->gate_flags, flags, &ctx->lock);
486
			break;
487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
		}

		/* none of the cases above matched */
		if (!clk) {
			pr_err("%s: unknown clock type %d\n",
			       __func__, list->branch_type);
			continue;
		}

		if (IS_ERR(clk)) {
			pr_err("%s: failed to register clock %s: %ld\n",
			       __func__, list->name, PTR_ERR(clk));
			continue;
		}

502
		rockchip_clk_add_lookup(ctx, clk, list->id);
503 504
	}
}
505

506 507
void __init rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx,
			unsigned int lookup_id,
508
			const char *name, const char *const *parent_names,
509 510 511 512 513 514 515 516
			u8 num_parents,
			const struct rockchip_cpuclk_reg_data *reg_data,
			const struct rockchip_cpuclk_rate_table *rates,
			int nrates)
{
	struct clk *clk;

	clk = rockchip_clk_register_cpuclk(name, parent_names, num_parents,
517 518
					   reg_data, rates, nrates,
					   ctx->reg_base, &ctx->lock);
519 520 521 522 523 524
	if (IS_ERR(clk)) {
		pr_err("%s: failed to register clock %s: %ld\n",
		       __func__, name, PTR_ERR(clk));
		return;
	}

525
	rockchip_clk_add_lookup(ctx, clk, lookup_id);
526 527
}

528 529
void __init rockchip_clk_protect_critical(const char *const clocks[],
					  int nclocks)
530 531 532 533 534 535 536 537 538 539 540
{
	int i;

	/* Protect the clocks that needs to stay on */
	for (i = 0; i < nclocks; i++) {
		struct clk *clk = __clk_lookup(clocks[i]);

		if (clk)
			clk_prepare_enable(clk);
	}
}
541

542
static void __iomem *rst_base;
543
static unsigned int reg_restart;
544
static void (*cb_restart)(void);
545 546 547
static int rockchip_restart_notify(struct notifier_block *this,
				   unsigned long mode, void *cmd)
{
548 549 550
	if (cb_restart)
		cb_restart();

551
	writel(0xfdb9, rst_base + reg_restart);
552 553 554 555 556 557 558 559
	return NOTIFY_DONE;
}

static struct notifier_block rockchip_restart_handler = {
	.notifier_call = rockchip_restart_notify,
	.priority = 128,
};

560 561 562 563
void __init
rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx,
					       unsigned int reg,
					       void (*cb)(void))
564 565 566
{
	int ret;

567
	rst_base = ctx->reg_base;
568
	reg_restart = reg;
569
	cb_restart = cb;
570 571 572 573 574
	ret = register_restart_handler(&rockchip_restart_handler);
	if (ret)
		pr_err("%s: cannot register restart handler, %d\n",
		       __func__, ret);
}