File Index
Files and directories
Sign in
FILE

clk-r8a7778.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/renesas/clk-r8a7778.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * r8a7778 Core CPG Clocks
  4 *
  5 * Copyright (C) 2014  Ulrich Hecht
  6 */
  7
  8#include <linux/clk-provider.h>
  9#include <linux/clk/renesas.h>
 10#include <linux/of_address.h>
 11#include <linux/slab.h>
 12#include <linux/soc/renesas/rcar-rst.h>
 13
 14/* PLL multipliers per bits 11, 12, and 18 of MODEMR */
 15static const struct {
 16	unsigned long plla_mult;
 17	unsigned long pllb_mult;
 18} r8a7778_rates[] __initconst = {
 19	[0] = { 21, 21 },
 20	[1] = { 24, 24 },
 21	[2] = { 28, 28 },
 22	[3] = { 32, 32 },
 23	[5] = { 24, 21 },
 24	[6] = { 28, 21 },
 25	[7] = { 32, 24 },
 26};
 27
 28/* Clock dividers per bits 1 and 2 of MODEMR */
 29static const struct {
 30	const char *name;
 31	unsigned int div[4];
 32} r8a7778_divs[6] __initconst = {
 33	{ "b",   { 12, 12, 16, 18 } },
 34	{ "out", { 12, 12, 16, 18 } },
 35	{ "p",   { 16, 12, 16, 12 } },
 36	{ "s",   { 4,  3,  4,  3  } },
 37	{ "s1",  { 8,  6,  8,  6  } },
 38};
 39
 40static u32 cpg_mode_rates __initdata;
 41static u32 cpg_mode_divs __initdata;
 42
 43static struct clk * __init
 44r8a7778_cpg_register_clock(struct device_node *np, const char *name)
 45{
 46	if (!strcmp(name, "plla")) {
 47		return clk_register_fixed_factor(NULL, "plla",
 48			of_clk_get_parent_name(np, 0), 0,
 49			r8a7778_rates[cpg_mode_rates].plla_mult, 1);
 50	} else if (!strcmp(name, "pllb")) {
 51		return clk_register_fixed_factor(NULL, "pllb",
 52			of_clk_get_parent_name(np, 0), 0,
 53			r8a7778_rates[cpg_mode_rates].pllb_mult, 1);
 54	} else {
 55		unsigned int i;
 56
 57		for (i = 0; i < ARRAY_SIZE(r8a7778_divs); i++) {
 58			if (!strcmp(name, r8a7778_divs[i].name)) {
 59				return clk_register_fixed_factor(NULL,
 60					r8a7778_divs[i].name,
 61					"plla", 0, 1,
 62					r8a7778_divs[i].div[cpg_mode_divs]);
 63			}
 64		}
 65	}
 66
 67	return ERR_PTR(-EINVAL);
 68}
 69
 70static void __init r8a7778_cpg_clocks_init(struct device_node *np)
 71{
 72	struct clk_onecell_data *data;
 73	struct clk **clks;
 74	unsigned int i;
 75	int num_clks;
 76	u32 mode;
 77
 78	if (rcar_rst_read_mode_pins(&mode))
 79		return;
 80
 81	BUG_ON(!(mode & BIT(19)));
 82
 83	cpg_mode_rates = (!!(mode & BIT(18)) << 2) |
 84			 (!!(mode & BIT(12)) << 1) |
 85			 (!!(mode & BIT(11)));
 86	cpg_mode_divs = (!!(mode & BIT(2)) << 1) |
 87			(!!(mode & BIT(1)));
 88
 89	num_clks = of_property_count_strings(np, "clock-output-names");
 90	if (num_clks < 0) {
 91		pr_err("%s: failed to count clocks\n", __func__);
 92		return;
 93	}
 94
 95	data = kzalloc(sizeof(*data), GFP_KERNEL);
 96	clks = kcalloc(num_clks, sizeof(*clks), GFP_KERNEL);
 97	if (data == NULL || clks == NULL) {
 98		/* We're leaking memory on purpose, there's no point in cleaning
 99		 * up as the system won't boot anyway.
100		 */
101		return;
102	}
103
104	data->clks = clks;
105	data->clk_num = num_clks;
106
107	for (i = 0; i < num_clks; ++i) {
108		const char *name;
109		struct clk *clk;
110
111		of_property_read_string_index(np, "clock-output-names", i,
112					      &name);
113
114		clk = r8a7778_cpg_register_clock(np, name);
115		if (IS_ERR(clk))
116			pr_err("%s: failed to register %pOFn %s clock (%ld)\n",
117			       __func__, np, name, PTR_ERR(clk));
118		else
119			data->clks[i] = clk;
120	}
121
122	of_clk_add_provider(np, of_clk_src_onecell_get, data);
123
124	cpg_mstp_add_clk_domain(np);
125}
126
127CLK_OF_DECLARE(r8a7778_cpg_clks, "renesas,r8a7778-cpg-clocks",
128	       r8a7778_cpg_clocks_init);
~/ Read-only file preview.