brintos

brintos / linux-shallow public Read only

0
0
Text · 5.9 KiB · a85227c Raw
227 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * R7S9210 Clock Pulse Generator / Module Standby4 *5 * Based on r8a7795-cpg-mssr.c6 *7 * Copyright (C) 2018 Chris Brandt8 * Copyright (C) 2018 Renesas Electronics Corp.9 *10 */11 12#include <linux/clk.h>13#include <linux/clk-provider.h>14#include <linux/io.h>15#include <dt-bindings/clock/r7s9210-cpg-mssr.h>16#include "renesas-cpg-mssr.h"17 18#define CPG_FRQCR	0x0019 20static u8 cpg_mode;21 22/* Internal Clock ratio table */23static const struct {24	unsigned int i;25	unsigned int g;26	unsigned int b;27	unsigned int p1;28	/* p0 is always 32 */;29} ratio_tab[5] = {	/* I,  G,  B, P1 */30			{  2,  4,  8, 16},	/* FRQCR = 0x012 */31			{  4,  4,  8, 16},	/* FRQCR = 0x112 */32			{  8,  4,  8, 16},	/* FRQCR = 0x212 */33			{ 16,  8, 16, 16},	/* FRQCR = 0x322 */34			{ 16, 16, 32, 32},	/* FRQCR = 0x333 */35			};36 37enum rz_clk_types {38	CLK_TYPE_RZA_MAIN = CLK_TYPE_CUSTOM,39	CLK_TYPE_RZA_PLL,40};41 42enum clk_ids {43	/* Core Clock Outputs exported to DT */44	LAST_DT_CORE_CLK = R7S9210_CLK_P0,45 46	/* External Input Clocks */47	CLK_EXTAL,48 49	/* Internal Core Clocks */50	CLK_MAIN,51	CLK_PLL,52 53	/* Module Clocks */54	MOD_CLK_BASE55};56 57static struct cpg_core_clk r7s9210_early_core_clks[] = {58	/* External Clock Inputs */59	DEF_INPUT("extal",     CLK_EXTAL),60 61	/* Internal Core Clocks */62	DEF_BASE(".main",       CLK_MAIN, CLK_TYPE_RZA_MAIN, CLK_EXTAL),63	DEF_BASE(".pll",       CLK_PLL, CLK_TYPE_RZA_PLL, CLK_MAIN),64 65	/* Core Clock Outputs */66	DEF_FIXED("p1c",    R7S9210_CLK_P1C,   CLK_PLL,         16, 1),67};68 69static const struct mssr_mod_clk r7s9210_early_mod_clks[] __initconst = {70	DEF_MOD_STB("ostm2",	 34,	R7S9210_CLK_P1C),71	DEF_MOD_STB("ostm1",	 35,	R7S9210_CLK_P1C),72	DEF_MOD_STB("ostm0",	 36,	R7S9210_CLK_P1C),73};74 75static struct cpg_core_clk r7s9210_core_clks[] = {76	/* Core Clock Outputs */77	DEF_FIXED("i",      R7S9210_CLK_I,     CLK_PLL,          2, 1),78	DEF_FIXED("g",      R7S9210_CLK_G,     CLK_PLL,          4, 1),79	DEF_FIXED("b",      R7S9210_CLK_B,     CLK_PLL,          8, 1),80	DEF_FIXED("p1",     R7S9210_CLK_P1,    CLK_PLL,         16, 1),81	DEF_FIXED("p0",     R7S9210_CLK_P0,    CLK_PLL,         32, 1),82};83 84static const struct mssr_mod_clk r7s9210_mod_clks[] __initconst = {85	DEF_MOD_STB("scif4",	 43,	R7S9210_CLK_P1C),86	DEF_MOD_STB("scif3",	 44,	R7S9210_CLK_P1C),87	DEF_MOD_STB("scif2",	 45,	R7S9210_CLK_P1C),88	DEF_MOD_STB("scif1",	 46,	R7S9210_CLK_P1C),89	DEF_MOD_STB("scif0",	 47,	R7S9210_CLK_P1C),90 91	DEF_MOD_STB("usb1",	 60,	R7S9210_CLK_B),92	DEF_MOD_STB("usb0",	 61,	R7S9210_CLK_B),93	DEF_MOD_STB("ether1",	 64,	R7S9210_CLK_B),94	DEF_MOD_STB("ether0",	 65,	R7S9210_CLK_B),95 96	DEF_MOD_STB("spibsc",	 83,	R7S9210_CLK_P1),97	DEF_MOD_STB("i2c3",	 84,	R7S9210_CLK_P1),98	DEF_MOD_STB("i2c2",	 85,	R7S9210_CLK_P1),99	DEF_MOD_STB("i2c1",	 86,	R7S9210_CLK_P1),100	DEF_MOD_STB("i2c0",	 87,	R7S9210_CLK_P1),101 102	DEF_MOD_STB("spi2",	 95,	R7S9210_CLK_P1),103	DEF_MOD_STB("spi1",	 96,	R7S9210_CLK_P1),104	DEF_MOD_STB("spi0",	 97,	R7S9210_CLK_P1),105 106	DEF_MOD_STB("sdhi11",	100,	R7S9210_CLK_B),107	DEF_MOD_STB("sdhi10",	101,	R7S9210_CLK_B),108	DEF_MOD_STB("sdhi01",	102,	R7S9210_CLK_B),109	DEF_MOD_STB("sdhi00",	103,	R7S9210_CLK_B),110};111 112/* The clock dividers in the table vary based on DT and register settings */113static void __init r7s9210_update_clk_table(struct clk *extal_clk,114					    void __iomem *base)115{116	int i;117	u16 frqcr;118	u8 index;119 120	/* If EXTAL is above 12MHz, then we know it is Mode 1 */121	if (clk_get_rate(extal_clk) > 12000000)122		cpg_mode = 1;123 124	frqcr = readl(base + CPG_FRQCR) & 0xFFF;125	if (frqcr == 0x012)126		index = 0;127	else if (frqcr == 0x112)128		index = 1;129	else if (frqcr == 0x212)130		index = 2;131	else if (frqcr == 0x322)132		index = 3;133	else if (frqcr == 0x333)134		index = 4;135	else136		BUG_ON(1);	/* Illegal FRQCR value */137 138	for (i = 0; i < ARRAY_SIZE(r7s9210_core_clks); i++) {139		switch (r7s9210_core_clks[i].id) {140		case R7S9210_CLK_I:141			r7s9210_core_clks[i].div = ratio_tab[index].i;142			break;143		case R7S9210_CLK_G:144			r7s9210_core_clks[i].div = ratio_tab[index].g;145			break;146		case R7S9210_CLK_B:147			r7s9210_core_clks[i].div = ratio_tab[index].b;148			break;149		case R7S9210_CLK_P1:150		case R7S9210_CLK_P1C:151			r7s9210_core_clks[i].div = ratio_tab[index].p1;152			break;153		case R7S9210_CLK_P0:154			r7s9210_core_clks[i].div = 32;155			break;156		}157	}158}159 160static struct clk * __init rza2_cpg_clk_register(struct device *dev,161	const struct cpg_core_clk *core, const struct cpg_mssr_info *info,162	struct clk **clks, void __iomem *base,163	struct raw_notifier_head *notifiers)164{165	struct clk *parent;166	unsigned int mult = 1;167	unsigned int div = 1;168 169	parent = clks[core->parent];170	if (IS_ERR(parent))171		return ERR_CAST(parent);172 173	switch (core->id) {174	case CLK_MAIN:175		break;176 177	case CLK_PLL:178		if (cpg_mode)179			mult = 44;	/* Divider 1 is 1/2 */180		else181			mult = 88;	/* Divider 1 is 1 */182		break;183 184	default:185		return ERR_PTR(-EINVAL);186	}187 188	if (core->id == CLK_MAIN)189		r7s9210_update_clk_table(parent, base);190 191	return clk_register_fixed_factor(NULL, core->name,192					 __clk_get_name(parent), 0, mult, div);193}194 195const struct cpg_mssr_info r7s9210_cpg_mssr_info __initconst = {196	/* Early Clocks */197	.early_core_clks = r7s9210_early_core_clks,198	.num_early_core_clks = ARRAY_SIZE(r7s9210_early_core_clks),199	.early_mod_clks = r7s9210_early_mod_clks,200	.num_early_mod_clks = ARRAY_SIZE(r7s9210_early_mod_clks),201 202	/* Core Clocks */203	.core_clks = r7s9210_core_clks,204	.num_core_clks = ARRAY_SIZE(r7s9210_core_clks),205	.last_dt_core_clk = LAST_DT_CORE_CLK,206	.num_total_core_clks = MOD_CLK_BASE,207 208	/* Module Clocks */209	.mod_clks = r7s9210_mod_clks,210	.num_mod_clks = ARRAY_SIZE(r7s9210_mod_clks),211	.num_hw_mod_clks = 11 * 32, /* includes STBCR0 which doesn't exist */212 213	/* Callbacks */214	.cpg_clk_register = rza2_cpg_clk_register,215 216	/* RZ/A2 has Standby Control Registers */217	.reg_layout = CLK_REG_LAYOUT_RZ_A,218};219 220static void __init r7s9210_cpg_mssr_early_init(struct device_node *np)221{222	cpg_mssr_early_init(np, &r7s9210_cpg_mssr_info);223}224 225CLK_OF_DECLARE_DRIVER(cpg_mstp_clks, "renesas,r7s9210-cpg-mssr",226		      r7s9210_cpg_mssr_early_init);227