// SPDX-License-Identifier: GPL-2.0
/*
* r8a7778 Core CPG Clocks
*
* Copyright ( C ) 2014 Ulrich Hecht
*/
#include <linux/clk-provider.h>
#include <linux/clk/renesas.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/soc/renesas/rcar-rst.h>
/* PLL multipliers per bits 11, 12, and 18 of MODEMR */
static const struct {
unsigned long plla_mult;
unsigned long pllb_mult;
} r8a7778_rates[] __initconst = {
[0 ] = { 21 , 21 },
[1 ] = { 24 , 24 },
[2 ] = { 28 , 28 },
[3 ] = { 32 , 32 },
[5 ] = { 24 , 21 },
[6 ] = { 28 , 21 },
[7 ] = { 32 , 24 },
};
/* Clock dividers per bits 1 and 2 of MODEMR */
static const struct {
const char *name;
unsigned int div[4 ];
} r8a7778_divs[6 ] __initconst = {
{ "b" , { 12 , 12 , 16 , 18 } },
{ "out" , { 12 , 12 , 16 , 18 } },
{ "p" , { 16 , 12 , 16 , 12 } },
{ "s" , { 4 , 3 , 4 , 3 } },
{ "s1" , { 8 , 6 , 8 , 6 } },
};
static u32 cpg_mode_rates __initdata;
static u32 cpg_mode_divs __initdata;
static struct clk * __init
r8a7778_cpg_register_clock(struct device_node *np, const char *name)
{
if (!strcmp(name, "plla" )) {
return clk_register_fixed_factor(NULL, "plla" ,
of_clk_get_parent_name(np, 0 ), 0 ,
r8a7778_rates[cpg_mode_rates].plla_mult, 1 );
} else if (!strcmp(name, "pllb" )) {
return clk_register_fixed_factor(NULL, "pllb" ,
of_clk_get_parent_name(np, 0 ), 0 ,
r8a7778_rates[cpg_mode_rates].pllb_mult, 1 );
} else {
unsigned int i;
for (i = 0 ; i < ARRAY_SIZE(r8a7778_divs); i++) {
if (!strcmp(name, r8a7778_divs[i].name)) {
return clk_register_fixed_factor(NULL,
r8a7778_divs[i].name,
"plla" , 0 , 1 ,
r8a7778_divs[i].div[cpg_mode_divs]);
}
}
}
return ERR_PTR(-EINVAL);
}
static void __init r8a7778_cpg_clocks_init(struct device_node *np)
{
struct clk_onecell_data *data;
struct clk **clks;
unsigned int i;
int num_clks;
u32 mode;
if (rcar_rst_read_mode_pins(&mode))
return ;
BUG_ON(!(mode & BIT(19 )));
cpg_mode_rates = (!!(mode & BIT(18 )) << 2 ) |
(!!(mode & BIT(12 )) << 1 ) |
(!!(mode & BIT(11 )));
cpg_mode_divs = (!!(mode & BIT(2 )) << 1 ) |
(!!(mode & BIT(1 )));
num_clks = of_property_count_strings(np, "clock-output-names" );
if (num_clks < 0 ) {
pr_err("%s: failed to count clocks\n" , __func__);
return ;
}
data = kzalloc(sizeof (*data), GFP_KERNEL);
clks = kcalloc(num_clks, sizeof (*clks), GFP_KERNEL);
if (data == NULL || clks == NULL) {
/* We're leaking memory on purpose, there's no point in cleaning
* up as the system won ' t boot anyway .
*/
return ;
}
data->clks = clks;
data->clk_num = num_clks;
for (i = 0 ; i < num_clks; ++i) {
const char *name;
struct clk *clk;
of_property_read_string_index(np, "clock-output-names" , i,
&name);
clk = r8a7778_cpg_register_clock(np, name);
if (IS_ERR(clk))
pr_err("%s: failed to register %pOFn %s clock (%ld)\n" ,
__func__, np, name, PTR_ERR(clk));
else
data->clks[i] = clk;
}
of_clk_add_provider(np, of_clk_src_onecell_get, data);
cpg_mstp_add_clk_domain(np);
}
CLK_OF_DECLARE(r8a7778_cpg_clks, "renesas,r8a7778-cpg-clocks" ,
r8a7778_cpg_clocks_init);
Messung V0.5 in Prozent C=97 H=97 G=96
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-09-28)
¤
*© Formatika GbR, Deutschland