brintos

brintos / linux-shallow public Read only

0
0
Text · 6.1 KiB · 590e9c8 Raw
274 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Ingenic JZ4725B SoC CGU driver4 *5 * Copyright (C) 2018 Paul Cercueil6 * Author: Paul Cercueil <paul@crapouillou.net>7 */8 9#include <linux/clk-provider.h>10#include <linux/delay.h>11#include <linux/of.h>12 13#include <dt-bindings/clock/ingenic,jz4725b-cgu.h>14 15#include "cgu.h"16#include "pm.h"17 18/* CGU register offsets */19#define CGU_REG_CPCCR		0x0020#define CGU_REG_LCR		0x0421#define CGU_REG_CPPCR		0x1022#define CGU_REG_CLKGR		0x2023#define CGU_REG_OPCR		0x2424#define CGU_REG_I2SCDR		0x6025#define CGU_REG_LPCDR		0x6426#define CGU_REG_MSCCDR		0x6827#define CGU_REG_SSICDR		0x7428#define CGU_REG_CIMCDR		0x7829 30/* bits within the LCR register */31#define LCR_SLEEP		BIT(0)32 33static struct ingenic_cgu *cgu;34 35static const s8 pll_od_encoding[4] = {36	0x0, 0x1, -1, 0x3,37};38 39static const u8 jz4725b_cgu_cpccr_div_table[] = {40	1, 2, 3, 4, 6, 8,41};42 43static const u8 jz4725b_cgu_pll_half_div_table[] = {44	2, 1,45};46 47static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {48 49	/* External clocks */50 51	[JZ4725B_CLK_EXT] = { "ext", CGU_CLK_EXT },52	[JZ4725B_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT },53 54	[JZ4725B_CLK_PLL] = {55		"pll", CGU_CLK_PLL,56		.parents = { JZ4725B_CLK_EXT, -1, -1, -1 },57		.pll = {58			.reg = CGU_REG_CPPCR,59			.rate_multiplier = 1,60			.m_shift = 23,61			.m_bits = 9,62			.m_offset = 2,63			.n_shift = 18,64			.n_bits = 5,65			.n_offset = 2,66			.od_shift = 16,67			.od_bits = 2,68			.od_max = 4,69			.od_encoding = pll_od_encoding,70			.stable_bit = 10,71			.bypass_reg = CGU_REG_CPPCR,72			.bypass_bit = 9,73			.enable_bit = 8,74		},75	},76 77	/* Muxes & dividers */78 79	[JZ4725B_CLK_PLL_HALF] = {80		"pll half", CGU_CLK_DIV,81		.parents = { JZ4725B_CLK_PLL, -1, -1, -1 },82		.div = {83			CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, 0,84			jz4725b_cgu_pll_half_div_table,85		},86	},87 88	[JZ4725B_CLK_CCLK] = {89		"cclk", CGU_CLK_DIV,90		/*91		 * Disabling the CPU clock or any parent clocks will hang the92		 * system; mark it critical.93		 */94		.flags = CLK_IS_CRITICAL,95		.parents = { JZ4725B_CLK_PLL, -1, -1, -1 },96		.div = {97			CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0,98			jz4725b_cgu_cpccr_div_table,99		},100	},101 102	[JZ4725B_CLK_HCLK] = {103		"hclk", CGU_CLK_DIV,104		.parents = { JZ4725B_CLK_PLL, -1, -1, -1 },105		.div = {106			CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0,107			jz4725b_cgu_cpccr_div_table,108		},109	},110 111	[JZ4725B_CLK_PCLK] = {112		"pclk", CGU_CLK_DIV,113		.parents = { JZ4725B_CLK_PLL, -1, -1, -1 },114		.div = {115			CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0,116			jz4725b_cgu_cpccr_div_table,117		},118	},119 120	[JZ4725B_CLK_MCLK] = {121		"mclk", CGU_CLK_DIV,122		/*123		 * Disabling MCLK or its parents will render DRAM124		 * inaccessible; mark it critical.125		 */126		.flags = CLK_IS_CRITICAL,127		.parents = { JZ4725B_CLK_PLL, -1, -1, -1 },128		.div = {129			CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0,130			jz4725b_cgu_cpccr_div_table,131		},132	},133 134	[JZ4725B_CLK_IPU] = {135		"ipu", CGU_CLK_DIV | CGU_CLK_GATE,136		.parents = { JZ4725B_CLK_PLL, -1, -1, -1 },137		.div = {138			CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0,139			jz4725b_cgu_cpccr_div_table,140		},141		.gate = { CGU_REG_CLKGR, 13 },142	},143 144	[JZ4725B_CLK_LCD] = {145		"lcd", CGU_CLK_DIV | CGU_CLK_GATE,146		.parents = { JZ4725B_CLK_PLL_HALF, -1, -1, -1 },147		.div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },148		.gate = { CGU_REG_CLKGR, 9 },149	},150 151	[JZ4725B_CLK_I2S] = {152		"i2s", CGU_CLK_MUX | CGU_CLK_DIV,153		.parents = { JZ4725B_CLK_EXT, JZ4725B_CLK_PLL_HALF, -1, -1 },154		.mux = { CGU_REG_CPCCR, 31, 1 },155		.div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 },156	},157 158	[JZ4725B_CLK_SPI] = {159		"spi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,160		.parents = { JZ4725B_CLK_EXT, JZ4725B_CLK_PLL, -1, -1 },161		.mux = { CGU_REG_SSICDR, 31, 1 },162		.div = { CGU_REG_SSICDR, 0, 1, 4, -1, -1, -1 },163		.gate = { CGU_REG_CLKGR, 4 },164	},165 166	[JZ4725B_CLK_MMC_MUX] = {167		"mmc_mux", CGU_CLK_DIV,168		.parents = { JZ4725B_CLK_PLL_HALF, -1, -1, -1 },169		.div = { CGU_REG_MSCCDR, 0, 1, 5, -1, -1, -1 },170	},171 172	[JZ4725B_CLK_UDC] = {173		"udc", CGU_CLK_MUX | CGU_CLK_DIV,174		.parents = { JZ4725B_CLK_EXT, JZ4725B_CLK_PLL_HALF, -1, -1 },175		.mux = { CGU_REG_CPCCR, 29, 1 },176		.div = { CGU_REG_CPCCR, 23, 1, 6, -1, -1, -1 },177	},178 179	/* Gate-only clocks */180 181	[JZ4725B_CLK_UART] = {182		"uart", CGU_CLK_GATE,183		.parents = { JZ4725B_CLK_EXT, -1, -1, -1 },184		.gate = { CGU_REG_CLKGR, 0 },185	},186 187	[JZ4725B_CLK_DMA] = {188		"dma", CGU_CLK_GATE,189		.parents = { JZ4725B_CLK_PCLK, -1, -1, -1 },190		.gate = { CGU_REG_CLKGR, 12 },191	},192 193	[JZ4725B_CLK_ADC] = {194		"adc", CGU_CLK_GATE,195		.parents = { JZ4725B_CLK_EXT, -1, -1, -1 },196		.gate = { CGU_REG_CLKGR, 7 },197	},198 199	[JZ4725B_CLK_I2C] = {200		"i2c", CGU_CLK_GATE,201		.parents = { JZ4725B_CLK_EXT, -1, -1, -1 },202		.gate = { CGU_REG_CLKGR, 3 },203	},204 205	[JZ4725B_CLK_AIC] = {206		"aic", CGU_CLK_GATE,207		.parents = { JZ4725B_CLK_EXT, -1, -1, -1 },208		.gate = { CGU_REG_CLKGR, 5 },209	},210 211	[JZ4725B_CLK_MMC0] = {212		"mmc0", CGU_CLK_GATE,213		.parents = { JZ4725B_CLK_MMC_MUX, -1, -1, -1 },214		.gate = { CGU_REG_CLKGR, 6 },215	},216 217	[JZ4725B_CLK_MMC1] = {218		"mmc1", CGU_CLK_GATE,219		.parents = { JZ4725B_CLK_MMC_MUX, -1, -1, -1 },220		.gate = { CGU_REG_CLKGR, 16 },221	},222 223	[JZ4725B_CLK_BCH] = {224		"bch", CGU_CLK_GATE,225		.parents = { JZ4725B_CLK_MCLK/* not sure */, -1, -1, -1 },226		.gate = { CGU_REG_CLKGR, 11 },227	},228 229	[JZ4725B_CLK_TCU] = {230		"tcu", CGU_CLK_GATE,231		.parents = { JZ4725B_CLK_EXT/* not sure */, -1, -1, -1 },232		.gate = { CGU_REG_CLKGR, 1 },233	},234 235	[JZ4725B_CLK_EXT512] = {236		"ext/512", CGU_CLK_FIXDIV,237		.parents = { JZ4725B_CLK_EXT },238 239		/* Doc calls it EXT512, but it seems to be /256... */240		.fixdiv = { 256 },241	},242 243	[JZ4725B_CLK_RTC] = {244		"rtc", CGU_CLK_MUX,245		.parents = { JZ4725B_CLK_EXT512, JZ4725B_CLK_OSC32K, -1, -1 },246		.mux = { CGU_REG_OPCR, 2, 1},247	},248 249	[JZ4725B_CLK_UDC_PHY] = {250		"udc_phy", CGU_CLK_GATE,251		.parents = { JZ4725B_CLK_EXT, -1, -1, -1 },252		.gate = { CGU_REG_OPCR, 6, true },253	},254};255 256static void __init jz4725b_cgu_init(struct device_node *np)257{258	int retval;259 260	cgu = ingenic_cgu_new(jz4725b_cgu_clocks,261			      ARRAY_SIZE(jz4725b_cgu_clocks), np);262	if (!cgu) {263		pr_err("%s: failed to initialise CGU\n", __func__);264		return;265	}266 267	retval = ingenic_cgu_register_clocks(cgu);268	if (retval)269		pr_err("%s: failed to register CGU Clocks\n", __func__);270 271	ingenic_cgu_register_syscore_ops(cgu);272}273CLK_OF_DECLARE_DRIVER(jz4725b_cgu, "ingenic,jz4725b-cgu", jz4725b_cgu_init);274