cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

jz4760-cgu.c (11139B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * JZ4760 SoC CGU driver
      4 * Copyright 2018, Paul Cercueil <paul@crapouillou.net>
      5 */
      6
      7#include <linux/bitops.h>
      8#include <linux/clk-provider.h>
      9#include <linux/delay.h>
     10#include <linux/io.h>
     11#include <linux/of.h>
     12
     13#include <linux/clk.h>
     14
     15#include <dt-bindings/clock/ingenic,jz4760-cgu.h>
     16
     17#include "cgu.h"
     18#include "pm.h"
     19
     20#define MHZ (1000 * 1000)
     21
     22/*
     23 * CPM registers offset address definition
     24 */
     25#define CGU_REG_CPCCR		0x00
     26#define CGU_REG_LCR		0x04
     27#define CGU_REG_CPPCR0		0x10
     28#define CGU_REG_CLKGR0		0x20
     29#define CGU_REG_OPCR		0x24
     30#define CGU_REG_CLKGR1		0x28
     31#define CGU_REG_CPPCR1		0x30
     32#define CGU_REG_USBPCR		0x3c
     33#define CGU_REG_USBCDR		0x50
     34#define CGU_REG_I2SCDR		0x60
     35#define CGU_REG_LPCDR		0x64
     36#define CGU_REG_MSCCDR		0x68
     37#define CGU_REG_UHCCDR		0x6c
     38#define CGU_REG_SSICDR		0x74
     39#define CGU_REG_CIMCDR		0x7c
     40#define CGU_REG_GPSCDR		0x80
     41#define CGU_REG_PCMCDR		0x84
     42#define CGU_REG_GPUCDR		0x88
     43
     44static const s8 pll_od_encoding[8] = {
     45	0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
     46};
     47
     48static const u8 jz4760_cgu_cpccr_div_table[] = {
     49	1, 2, 3, 4, 6, 8,
     50};
     51
     52static const u8 jz4760_cgu_pll_half_div_table[] = {
     53	2, 1,
     54};
     55
     56static void
     57jz4760_cgu_calc_m_n_od(const struct ingenic_cgu_pll_info *pll_info,
     58		       unsigned long rate, unsigned long parent_rate,
     59		       unsigned int *pm, unsigned int *pn, unsigned int *pod)
     60{
     61	unsigned int m, n, od, m_max = (1 << pll_info->m_bits) - 2;
     62
     63	/* The frequency after the N divider must be between 1 and 50 MHz. */
     64	n = parent_rate / (1 * MHZ);
     65
     66	/* The N divider must be >= 2. */
     67	n = clamp_val(n, 2, 1 << pll_info->n_bits);
     68
     69	for (;; n >>= 1) {
     70		od = (unsigned int)-1;
     71
     72		do {
     73			m = (rate / MHZ) * (1 << ++od) * n / (parent_rate / MHZ);
     74		} while ((m > m_max || m & 1) && (od < 4));
     75
     76		if (od < 4 && m >= 4 && m <= m_max)
     77			break;
     78	}
     79
     80	*pm = m;
     81	*pn = n;
     82	*pod = 1 << od;
     83}
     84
     85static const struct ingenic_cgu_clk_info jz4760_cgu_clocks[] = {
     86
     87	/* External clocks */
     88
     89	[JZ4760_CLK_EXT] = { "ext", CGU_CLK_EXT },
     90	[JZ4760_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT },
     91
     92	/* PLLs */
     93
     94	[JZ4760_CLK_PLL0] = {
     95		"pll0", CGU_CLK_PLL,
     96		.parents = { JZ4760_CLK_EXT },
     97		.pll = {
     98			.reg = CGU_REG_CPPCR0,
     99			.rate_multiplier = 1,
    100			.m_shift = 23,
    101			.m_bits = 8,
    102			.m_offset = 0,
    103			.n_shift = 18,
    104			.n_bits = 4,
    105			.n_offset = 0,
    106			.od_shift = 16,
    107			.od_bits = 2,
    108			.od_max = 8,
    109			.od_encoding = pll_od_encoding,
    110			.bypass_reg = CGU_REG_CPPCR0,
    111			.bypass_bit = 9,
    112			.enable_bit = 8,
    113			.stable_bit = 10,
    114			.calc_m_n_od = jz4760_cgu_calc_m_n_od,
    115		},
    116	},
    117
    118	[JZ4760_CLK_PLL1] = {
    119		/* TODO: PLL1 can depend on PLL0 */
    120		"pll1", CGU_CLK_PLL,
    121		.parents = { JZ4760_CLK_EXT },
    122		.pll = {
    123			.reg = CGU_REG_CPPCR1,
    124			.rate_multiplier = 1,
    125			.m_shift = 23,
    126			.m_bits = 8,
    127			.m_offset = 0,
    128			.n_shift = 18,
    129			.n_bits = 4,
    130			.n_offset = 0,
    131			.od_shift = 16,
    132			.od_bits = 2,
    133			.od_max = 8,
    134			.od_encoding = pll_od_encoding,
    135			.bypass_bit = -1,
    136			.enable_bit = 7,
    137			.stable_bit = 6,
    138			.calc_m_n_od = jz4760_cgu_calc_m_n_od,
    139		},
    140	},
    141
    142	/* Main clocks */
    143
    144	[JZ4760_CLK_CCLK] = {
    145		"cclk", CGU_CLK_DIV,
    146		/*
    147		 * Disabling the CPU clock or any parent clocks will hang the
    148		 * system; mark it critical.
    149		 */
    150		.flags = CLK_IS_CRITICAL,
    151		.parents = { JZ4760_CLK_PLL0, },
    152		.div = {
    153			CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0,
    154			jz4760_cgu_cpccr_div_table,
    155		},
    156	},
    157	[JZ4760_CLK_HCLK] = {
    158		"hclk", CGU_CLK_DIV,
    159		.parents = { JZ4760_CLK_PLL0, },
    160		.div = {
    161			CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0,
    162			jz4760_cgu_cpccr_div_table,
    163		},
    164	},
    165	[JZ4760_CLK_SCLK] = {
    166		"sclk", CGU_CLK_DIV,
    167		.parents = { JZ4760_CLK_PLL0, },
    168		.div = {
    169			CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1, 0,
    170			jz4760_cgu_cpccr_div_table,
    171		},
    172	},
    173	[JZ4760_CLK_H2CLK] = {
    174		"h2clk", CGU_CLK_DIV,
    175		.parents = { JZ4760_CLK_PLL0, },
    176		.div = {
    177			CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0,
    178			jz4760_cgu_cpccr_div_table,
    179		},
    180	},
    181	[JZ4760_CLK_MCLK] = {
    182		"mclk", CGU_CLK_DIV,
    183		/*
    184		 * Disabling MCLK or its parents will render DRAM
    185		 * inaccessible; mark it critical.
    186		 */
    187		.flags = CLK_IS_CRITICAL,
    188		.parents = { JZ4760_CLK_PLL0, },
    189		.div = {
    190			CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0,
    191			jz4760_cgu_cpccr_div_table,
    192		},
    193	},
    194	[JZ4760_CLK_PCLK] = {
    195		"pclk", CGU_CLK_DIV,
    196		.parents = { JZ4760_CLK_PLL0, },
    197		.div = {
    198			CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0,
    199			jz4760_cgu_cpccr_div_table,
    200		},
    201	},
    202
    203	/* Divided clocks */
    204
    205	[JZ4760_CLK_PLL0_HALF] = {
    206		"pll0_half", CGU_CLK_DIV,
    207		.parents = { JZ4760_CLK_PLL0 },
    208		.div = {
    209			CGU_REG_CPCCR, 21, 1, 1, 22, -1, -1, 0,
    210			jz4760_cgu_pll_half_div_table,
    211		},
    212	},
    213
    214	/* Those divided clocks can connect to PLL0 or PLL1 */
    215
    216	[JZ4760_CLK_UHC] = {
    217		"uhc", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
    218		.parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, },
    219		.mux = { CGU_REG_UHCCDR, 31, 1 },
    220		.div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 },
    221		.gate = { CGU_REG_CLKGR0, 24 },
    222	},
    223	[JZ4760_CLK_GPU] = {
    224		"gpu", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
    225		.parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, },
    226		.mux = { CGU_REG_GPUCDR, 31, 1 },
    227		.div = { CGU_REG_GPUCDR, 0, 1, 3, -1, -1, -1 },
    228		.gate = { CGU_REG_CLKGR1, 9 },
    229	},
    230	[JZ4760_CLK_LPCLK_DIV] = {
    231		"lpclk_div", CGU_CLK_DIV | CGU_CLK_MUX,
    232		.parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, },
    233		.mux = { CGU_REG_LPCDR, 29, 1 },
    234		.div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },
    235	},
    236	[JZ4760_CLK_TVE] = {
    237		"tve", CGU_CLK_GATE | CGU_CLK_MUX,
    238		.parents = { JZ4760_CLK_LPCLK_DIV, JZ4760_CLK_EXT, },
    239		.mux = { CGU_REG_LPCDR, 31, 1 },
    240		.gate = { CGU_REG_CLKGR0, 27 },
    241	},
    242	[JZ4760_CLK_LPCLK] = {
    243		"lpclk", CGU_CLK_GATE | CGU_CLK_MUX,
    244		.parents = { JZ4760_CLK_LPCLK_DIV, JZ4760_CLK_TVE, },
    245		.mux = { CGU_REG_LPCDR, 30, 1 },
    246		.gate = { CGU_REG_CLKGR0, 28 },
    247	},
    248	[JZ4760_CLK_GPS] = {
    249		"gps", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
    250		.parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, },
    251		.mux = { CGU_REG_GPSCDR, 31, 1 },
    252		.div = { CGU_REG_GPSCDR, 0, 1, 4, -1, -1, -1 },
    253		.gate = { CGU_REG_CLKGR0, 22 },
    254	},
    255
    256	/* Those divided clocks can connect to EXT, PLL0 or PLL1 */
    257
    258	[JZ4760_CLK_PCM] = {
    259		"pcm", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
    260		.parents = { JZ4760_CLK_EXT, -1,
    261			JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 },
    262		.mux = { CGU_REG_PCMCDR, 30, 2 },
    263		.div = { CGU_REG_PCMCDR, 0, 1, 9, -1, -1, -1, BIT(0) },
    264		.gate = { CGU_REG_CLKGR1, 8 },
    265	},
    266	[JZ4760_CLK_I2S] = {
    267		"i2s", CGU_CLK_DIV | CGU_CLK_MUX,
    268		.parents = { JZ4760_CLK_EXT, -1,
    269			JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 },
    270		.mux = { CGU_REG_I2SCDR, 30, 2 },
    271		.div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1, BIT(0) },
    272	},
    273	[JZ4760_CLK_OTG] = {
    274		"usb", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
    275		.parents = { JZ4760_CLK_EXT, -1,
    276			JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 },
    277		.mux = { CGU_REG_USBCDR, 30, 2 },
    278		.div = { CGU_REG_USBCDR, 0, 1, 8, -1, -1, -1 },
    279		.gate = { CGU_REG_CLKGR0, 2 },
    280	},
    281
    282	/* Those divided clocks can connect to EXT or PLL0 */
    283	[JZ4760_CLK_MMC_MUX] = {
    284		"mmc_mux", CGU_CLK_MUX | CGU_CLK_DIV,
    285		.parents = { JZ4760_CLK_EXT, JZ4760_CLK_PLL0_HALF, },
    286		.mux = { CGU_REG_MSCCDR, 31, 1 },
    287		.div = { CGU_REG_MSCCDR, 0, 1, 6, -1, -1, -1, BIT(0) },
    288	},
    289	[JZ4760_CLK_SSI_MUX] = {
    290		"ssi_mux", CGU_CLK_DIV | CGU_CLK_MUX,
    291		.parents = { JZ4760_CLK_EXT, JZ4760_CLK_PLL0_HALF, },
    292		.mux = { CGU_REG_SSICDR, 31, 1 },
    293		.div = { CGU_REG_SSICDR, 0, 1, 6, -1, -1, -1, BIT(0) },
    294	},
    295
    296	/* These divided clock can connect to PLL0 only */
    297	[JZ4760_CLK_CIM] = {
    298		"cim", CGU_CLK_DIV | CGU_CLK_GATE,
    299		.parents = { JZ4760_CLK_PLL0_HALF },
    300		.div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 },
    301		.gate = { CGU_REG_CLKGR0, 26 },
    302	},
    303
    304	/* Gate-only clocks */
    305
    306	[JZ4760_CLK_SSI0] = {
    307		"ssi0", CGU_CLK_GATE,
    308		.parents = { JZ4760_CLK_SSI_MUX, },
    309		.gate = { CGU_REG_CLKGR0, 4 },
    310	},
    311	[JZ4760_CLK_SSI1] = {
    312		"ssi1", CGU_CLK_GATE,
    313		.parents = { JZ4760_CLK_SSI_MUX, },
    314		.gate = { CGU_REG_CLKGR0, 19 },
    315	},
    316	[JZ4760_CLK_SSI2] = {
    317		"ssi2", CGU_CLK_GATE,
    318		.parents = { JZ4760_CLK_SSI_MUX, },
    319		.gate = { CGU_REG_CLKGR0, 20 },
    320	},
    321	[JZ4760_CLK_DMA] = {
    322		"dma", CGU_CLK_GATE,
    323		.parents = { JZ4760_CLK_H2CLK, },
    324		.gate = { CGU_REG_CLKGR0, 21 },
    325	},
    326	[JZ4760_CLK_MDMA] = {
    327		"mdma", CGU_CLK_GATE,
    328		.parents = { JZ4760_CLK_HCLK, },
    329		.gate = { CGU_REG_CLKGR0, 25 },
    330	},
    331	[JZ4760_CLK_BDMA] = {
    332		"bdma", CGU_CLK_GATE,
    333		.parents = { JZ4760_CLK_HCLK, },
    334		.gate = { CGU_REG_CLKGR1, 0 },
    335	},
    336	[JZ4760_CLK_I2C0] = {
    337		"i2c0", CGU_CLK_GATE,
    338		.parents = { JZ4760_CLK_EXT, },
    339		.gate = { CGU_REG_CLKGR0, 5 },
    340	},
    341	[JZ4760_CLK_I2C1] = {
    342		"i2c1", CGU_CLK_GATE,
    343		.parents = { JZ4760_CLK_EXT, },
    344		.gate = { CGU_REG_CLKGR0, 6 },
    345	},
    346	[JZ4760_CLK_UART0] = {
    347		"uart0", CGU_CLK_GATE,
    348		.parents = { JZ4760_CLK_EXT, },
    349		.gate = { CGU_REG_CLKGR0, 15 },
    350	},
    351	[JZ4760_CLK_UART1] = {
    352		"uart1", CGU_CLK_GATE,
    353		.parents = { JZ4760_CLK_EXT, },
    354		.gate = { CGU_REG_CLKGR0, 16 },
    355	},
    356	[JZ4760_CLK_UART2] = {
    357		"uart2", CGU_CLK_GATE,
    358		.parents = { JZ4760_CLK_EXT, },
    359		.gate = { CGU_REG_CLKGR0, 17 },
    360	},
    361	[JZ4760_CLK_UART3] = {
    362		"uart3", CGU_CLK_GATE,
    363		.parents = { JZ4760_CLK_EXT, },
    364		.gate = { CGU_REG_CLKGR0, 18 },
    365	},
    366	[JZ4760_CLK_IPU] = {
    367		"ipu", CGU_CLK_GATE,
    368		.parents = { JZ4760_CLK_HCLK, },
    369		.gate = { CGU_REG_CLKGR0, 29 },
    370	},
    371	[JZ4760_CLK_ADC] = {
    372		"adc", CGU_CLK_GATE,
    373		.parents = { JZ4760_CLK_EXT, },
    374		.gate = { CGU_REG_CLKGR0, 14 },
    375	},
    376	[JZ4760_CLK_AIC] = {
    377		"aic", CGU_CLK_GATE,
    378		.parents = { JZ4760_CLK_EXT, },
    379		.gate = { CGU_REG_CLKGR0, 8 },
    380	},
    381	[JZ4760_CLK_VPU] = {
    382		"vpu", CGU_CLK_GATE,
    383		.parents = { JZ4760_CLK_HCLK, },
    384		.gate = { CGU_REG_LCR, 30, false, 150 },
    385	},
    386	[JZ4760_CLK_MMC0] = {
    387		"mmc0", CGU_CLK_GATE,
    388		.parents = { JZ4760_CLK_MMC_MUX, },
    389		.gate = { CGU_REG_CLKGR0, 3 },
    390	},
    391	[JZ4760_CLK_MMC1] = {
    392		"mmc1", CGU_CLK_GATE,
    393		.parents = { JZ4760_CLK_MMC_MUX, },
    394		.gate = { CGU_REG_CLKGR0, 11 },
    395	},
    396	[JZ4760_CLK_MMC2] = {
    397		"mmc2", CGU_CLK_GATE,
    398		.parents = { JZ4760_CLK_MMC_MUX, },
    399		.gate = { CGU_REG_CLKGR0, 12 },
    400	},
    401	[JZ4760_CLK_UHC_PHY] = {
    402		"uhc_phy", CGU_CLK_GATE,
    403		.parents = { JZ4760_CLK_UHC, },
    404		.gate = { CGU_REG_OPCR, 5 },
    405	},
    406	[JZ4760_CLK_OTG_PHY] = {
    407		"usb_phy", CGU_CLK_GATE,
    408		.parents = { JZ4760_CLK_OTG },
    409		.gate = { CGU_REG_OPCR, 7, true, 50 },
    410	},
    411
    412	/* Custom clocks */
    413	[JZ4760_CLK_EXT512] = {
    414		"ext/512", CGU_CLK_FIXDIV,
    415		.parents = { JZ4760_CLK_EXT },
    416		.fixdiv = { 512 },
    417	},
    418	[JZ4760_CLK_RTC] = {
    419		"rtc", CGU_CLK_MUX,
    420		.parents = { JZ4760_CLK_EXT512, JZ4760_CLK_OSC32K, },
    421		.mux = { CGU_REG_OPCR, 2, 1},
    422	},
    423};
    424
    425static void __init jz4760_cgu_init(struct device_node *np)
    426{
    427	struct ingenic_cgu *cgu;
    428	int retval;
    429
    430	cgu = ingenic_cgu_new(jz4760_cgu_clocks,
    431			      ARRAY_SIZE(jz4760_cgu_clocks), np);
    432	if (!cgu) {
    433		pr_err("%s: failed to initialise CGU\n", __func__);
    434		return;
    435	}
    436
    437	retval = ingenic_cgu_register_clocks(cgu);
    438	if (retval)
    439		pr_err("%s: failed to register CGU Clocks\n", __func__);
    440
    441	ingenic_cgu_register_syscore_ops(cgu);
    442}
    443
    444/* We only probe via devicetree, no need for a platform driver */
    445CLK_OF_DECLARE_DRIVER(jz4760_cgu, "ingenic,jz4760-cgu", jz4760_cgu_init);
    446
    447/* JZ4760B has some small differences, but we don't implement them. */
    448CLK_OF_DECLARE_DRIVER(jz4760b_cgu, "ingenic,jz4760b-cgu", jz4760_cgu_init);