brintos

brintos / linux-shallow public Read only

0
0
Text · 6.2 KiB · 3e0a305 Raw
272 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Ingenic JZ4740 SoC CGU driver4 *5 * Copyright (c) 2015 Imagination Technologies6 * Author: Paul Burton <paul.burton@mips.com>7 */8 9#include <linux/clk-provider.h>10#include <linux/delay.h>11#include <linux/io.h>12#include <linux/of.h>13 14#include <dt-bindings/clock/ingenic,jz4740-cgu.h>15 16#include "cgu.h"17#include "pm.h"18 19/* CGU register offsets */20#define CGU_REG_CPCCR		0x0021#define CGU_REG_LCR		0x0422#define CGU_REG_CPPCR		0x1023#define CGU_REG_CLKGR		0x2024#define CGU_REG_SCR		0x2425#define CGU_REG_I2SCDR		0x6026#define CGU_REG_LPCDR		0x6427#define CGU_REG_MSCCDR		0x6828#define CGU_REG_UHCCDR		0x6c29#define CGU_REG_SSICDR		0x7430 31/* bits within a PLL control register */32#define PLLCTL_M_SHIFT		2333#define PLLCTL_M_MASK		(0x1ff << PLLCTL_M_SHIFT)34#define PLLCTL_N_SHIFT		1835#define PLLCTL_N_MASK		(0x1f << PLLCTL_N_SHIFT)36#define PLLCTL_OD_SHIFT		1637#define PLLCTL_OD_MASK		(0x3 << PLLCTL_OD_SHIFT)38#define PLLCTL_STABLE		(1 << 10)39#define PLLCTL_BYPASS		(1 << 9)40#define PLLCTL_ENABLE		(1 << 8)41 42/* bits within the LCR register */43#define LCR_SLEEP		(1 << 0)44 45/* bits within the CLKGR register */46#define CLKGR_UDC		(1 << 11)47 48static struct ingenic_cgu *cgu;49 50static const s8 pll_od_encoding[4] = {51	0x0, 0x1, -1, 0x3,52};53 54static const u8 jz4740_cgu_cpccr_div_table[] = {55	1, 2, 3, 4, 6, 8, 12, 16, 24, 32,56};57 58static const u8 jz4740_cgu_pll_half_div_table[] = {59	2, 1,60};61 62static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {63 64	/* External clocks */65 66	[JZ4740_CLK_EXT] = { "ext", CGU_CLK_EXT },67	[JZ4740_CLK_RTC] = { "rtc", CGU_CLK_EXT },68 69	[JZ4740_CLK_PLL] = {70		"pll", CGU_CLK_PLL,71		.parents = { JZ4740_CLK_EXT, -1, -1, -1 },72		.pll = {73			.reg = CGU_REG_CPPCR,74			.rate_multiplier = 1,75			.m_shift = 23,76			.m_bits = 9,77			.m_offset = 2,78			.n_shift = 18,79			.n_bits = 5,80			.n_offset = 2,81			.od_shift = 16,82			.od_bits = 2,83			.od_max = 4,84			.od_encoding = pll_od_encoding,85			.stable_bit = 10,86			.bypass_reg = CGU_REG_CPPCR,87			.bypass_bit = 9,88			.enable_bit = 8,89		},90	},91 92	/* Muxes & dividers */93 94	[JZ4740_CLK_PLL_HALF] = {95		"pll half", CGU_CLK_DIV,96		.parents = { JZ4740_CLK_PLL, -1, -1, -1 },97		.div = {98			CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, 0,99			jz4740_cgu_pll_half_div_table,100		},101	},102 103	[JZ4740_CLK_CCLK] = {104		"cclk", CGU_CLK_DIV,105		/*106		 * Disabling the CPU clock or any parent clocks will hang the107		 * system; mark it critical.108		 */109		.flags = CLK_IS_CRITICAL,110		.parents = { JZ4740_CLK_PLL, -1, -1, -1 },111		.div = {112			CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0,113			jz4740_cgu_cpccr_div_table,114		},115	},116 117	[JZ4740_CLK_HCLK] = {118		"hclk", CGU_CLK_DIV,119		.parents = { JZ4740_CLK_PLL, -1, -1, -1 },120		.div = {121			CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0,122			jz4740_cgu_cpccr_div_table,123		},124	},125 126	[JZ4740_CLK_PCLK] = {127		"pclk", CGU_CLK_DIV,128		.parents = { JZ4740_CLK_PLL, -1, -1, -1 },129		.div = {130			CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0,131			jz4740_cgu_cpccr_div_table,132		},133	},134 135	[JZ4740_CLK_MCLK] = {136		"mclk", CGU_CLK_DIV,137		/*138		 * Disabling MCLK or its parents will render DRAM139		 * inaccessible; mark it critical.140		 */141		.flags = CLK_IS_CRITICAL,142		.parents = { JZ4740_CLK_PLL, -1, -1, -1 },143		.div = {144			CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0,145			jz4740_cgu_cpccr_div_table,146		},147	},148 149	[JZ4740_CLK_LCD] = {150		"lcd", CGU_CLK_DIV | CGU_CLK_GATE,151		.parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 },152		.div = {153			CGU_REG_CPCCR, 16, 1, 5, 22, -1, -1, 0,154			jz4740_cgu_cpccr_div_table,155		},156		.gate = { CGU_REG_CLKGR, 10 },157	},158 159	[JZ4740_CLK_LCD_PCLK] = {160		"lcd_pclk", CGU_CLK_DIV,161		.parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 },162		.div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },163	},164 165	[JZ4740_CLK_I2S] = {166		"i2s", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,167		.parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1, -1 },168		.mux = { CGU_REG_CPCCR, 31, 1 },169		.div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 },170		.gate = { CGU_REG_CLKGR, 6 },171	},172 173	[JZ4740_CLK_SPI] = {174		"spi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,175		.parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL, -1, -1 },176		.mux = { CGU_REG_SSICDR, 31, 1 },177		.div = { CGU_REG_SSICDR, 0, 1, 4, -1, -1, -1 },178		.gate = { CGU_REG_CLKGR, 4 },179	},180 181	[JZ4740_CLK_MMC] = {182		"mmc", CGU_CLK_DIV | CGU_CLK_GATE,183		.parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 },184		.div = { CGU_REG_MSCCDR, 0, 1, 5, -1, -1, -1 },185		.gate = { CGU_REG_CLKGR, 7 },186	},187 188	[JZ4740_CLK_UHC] = {189		"uhc", CGU_CLK_DIV | CGU_CLK_GATE,190		.parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 },191		.div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 },192		.gate = { CGU_REG_CLKGR, 14 },193	},194 195	[JZ4740_CLK_UDC] = {196		"udc", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,197		.parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1, -1 },198		.mux = { CGU_REG_CPCCR, 29, 1 },199		.div = { CGU_REG_CPCCR, 23, 1, 6, -1, -1, -1 },200		.gate = { CGU_REG_SCR, 6, true },201	},202 203	/* Gate-only clocks */204 205	[JZ4740_CLK_UART0] = {206		"uart0", CGU_CLK_GATE,207		.parents = { JZ4740_CLK_EXT, -1, -1, -1 },208		.gate = { CGU_REG_CLKGR, 0 },209	},210 211	[JZ4740_CLK_UART1] = {212		"uart1", CGU_CLK_GATE,213		.parents = { JZ4740_CLK_EXT, -1, -1, -1 },214		.gate = { CGU_REG_CLKGR, 15 },215	},216 217	[JZ4740_CLK_DMA] = {218		"dma", CGU_CLK_GATE,219		.parents = { JZ4740_CLK_PCLK, -1, -1, -1 },220		.gate = { CGU_REG_CLKGR, 12 },221	},222 223	[JZ4740_CLK_IPU] = {224		"ipu", CGU_CLK_GATE,225		.parents = { JZ4740_CLK_PCLK, -1, -1, -1 },226		.gate = { CGU_REG_CLKGR, 13 },227	},228 229	[JZ4740_CLK_ADC] = {230		"adc", CGU_CLK_GATE,231		.parents = { JZ4740_CLK_EXT, -1, -1, -1 },232		.gate = { CGU_REG_CLKGR, 8 },233	},234 235	[JZ4740_CLK_I2C] = {236		"i2c", CGU_CLK_GATE,237		.parents = { JZ4740_CLK_EXT, -1, -1, -1 },238		.gate = { CGU_REG_CLKGR, 3 },239	},240 241	[JZ4740_CLK_AIC] = {242		"aic", CGU_CLK_GATE,243		.parents = { JZ4740_CLK_EXT, -1, -1, -1 },244		.gate = { CGU_REG_CLKGR, 5 },245	},246 247	[JZ4740_CLK_TCU] = {248		"tcu", CGU_CLK_GATE,249		.parents = { JZ4740_CLK_EXT, -1, -1, -1 },250		.gate = { CGU_REG_CLKGR, 1 },251	},252};253 254static void __init jz4740_cgu_init(struct device_node *np)255{256	int retval;257 258	cgu = ingenic_cgu_new(jz4740_cgu_clocks,259			      ARRAY_SIZE(jz4740_cgu_clocks), np);260	if (!cgu) {261		pr_err("%s: failed to initialise CGU\n", __func__);262		return;263	}264 265	retval = ingenic_cgu_register_clocks(cgu);266	if (retval)267		pr_err("%s: failed to register CGU Clocks\n", __func__);268 269	ingenic_cgu_register_syscore_ops(cgu);270}271CLK_OF_DECLARE_DRIVER(jz4740_cgu, "ingenic,jz4740-cgu", jz4740_cgu_init);272