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

jz4770-cgu.c (11979B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * JZ4770 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 <dt-bindings/clock/ingenic,jz4770-cgu.h>
     14
     15#include "cgu.h"
     16#include "pm.h"
     17
     18/*
     19 * CPM registers offset address definition
     20 */
     21#define CGU_REG_CPCCR		0x00
     22#define CGU_REG_LCR		0x04
     23#define CGU_REG_CPPCR0		0x10
     24#define CGU_REG_CLKGR0		0x20
     25#define CGU_REG_OPCR		0x24
     26#define CGU_REG_CLKGR1		0x28
     27#define CGU_REG_CPPCR1		0x30
     28#define CGU_REG_USBPCR1		0x48
     29#define CGU_REG_USBCDR		0x50
     30#define CGU_REG_I2SCDR		0x60
     31#define CGU_REG_LPCDR		0x64
     32#define CGU_REG_MSC0CDR		0x68
     33#define CGU_REG_UHCCDR		0x6c
     34#define CGU_REG_SSICDR		0x74
     35#define CGU_REG_CIMCDR		0x7c
     36#define CGU_REG_GPSCDR		0x80
     37#define CGU_REG_PCMCDR		0x84
     38#define CGU_REG_GPUCDR		0x88
     39#define CGU_REG_MSC1CDR		0xA4
     40#define CGU_REG_MSC2CDR		0xA8
     41#define CGU_REG_BCHCDR		0xAC
     42
     43/* bits within the OPCR register */
     44#define OPCR_SPENDH		BIT(5)		/* UHC PHY suspend */
     45
     46/* bits within the USBPCR1 register */
     47#define USBPCR1_UHC_POWER	BIT(5)		/* UHC PHY power down */
     48
     49static struct ingenic_cgu *cgu;
     50
     51static int jz4770_uhc_phy_enable(struct clk_hw *hw)
     52{
     53	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
     54	void __iomem *reg_usbpcr1	= cgu->base + CGU_REG_USBPCR1;
     55
     56	writel(readl(reg_opcr) & ~OPCR_SPENDH, reg_opcr);
     57	writel(readl(reg_usbpcr1) | USBPCR1_UHC_POWER, reg_usbpcr1);
     58	return 0;
     59}
     60
     61static void jz4770_uhc_phy_disable(struct clk_hw *hw)
     62{
     63	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
     64	void __iomem *reg_usbpcr1	= cgu->base + CGU_REG_USBPCR1;
     65
     66	writel(readl(reg_usbpcr1) & ~USBPCR1_UHC_POWER, reg_usbpcr1);
     67	writel(readl(reg_opcr) | OPCR_SPENDH, reg_opcr);
     68}
     69
     70static int jz4770_uhc_phy_is_enabled(struct clk_hw *hw)
     71{
     72	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
     73	void __iomem *reg_usbpcr1	= cgu->base + CGU_REG_USBPCR1;
     74
     75	return !(readl(reg_opcr) & OPCR_SPENDH) &&
     76		(readl(reg_usbpcr1) & USBPCR1_UHC_POWER);
     77}
     78
     79static const struct clk_ops jz4770_uhc_phy_ops = {
     80	.enable = jz4770_uhc_phy_enable,
     81	.disable = jz4770_uhc_phy_disable,
     82	.is_enabled = jz4770_uhc_phy_is_enabled,
     83};
     84
     85static const s8 pll_od_encoding[8] = {
     86	0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
     87};
     88
     89static const u8 jz4770_cgu_cpccr_div_table[] = {
     90	1, 2, 3, 4, 6, 8, 12,
     91};
     92
     93static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
     94
     95	/* External clocks */
     96
     97	[JZ4770_CLK_EXT] = { "ext", CGU_CLK_EXT },
     98	[JZ4770_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT },
     99
    100	/* PLLs */
    101
    102	[JZ4770_CLK_PLL0] = {
    103		"pll0", CGU_CLK_PLL,
    104		.parents = { JZ4770_CLK_EXT },
    105		.pll = {
    106			.reg = CGU_REG_CPPCR0,
    107			.rate_multiplier = 1,
    108			.m_shift = 24,
    109			.m_bits = 7,
    110			.m_offset = 1,
    111			.n_shift = 18,
    112			.n_bits = 5,
    113			.n_offset = 1,
    114			.od_shift = 16,
    115			.od_bits = 2,
    116			.od_max = 8,
    117			.od_encoding = pll_od_encoding,
    118			.bypass_reg = CGU_REG_CPPCR0,
    119			.bypass_bit = 9,
    120			.enable_bit = 8,
    121			.stable_bit = 10,
    122		},
    123	},
    124
    125	[JZ4770_CLK_PLL1] = {
    126		/* TODO: PLL1 can depend on PLL0 */
    127		"pll1", CGU_CLK_PLL,
    128		.parents = { JZ4770_CLK_EXT },
    129		.pll = {
    130			.reg = CGU_REG_CPPCR1,
    131			.rate_multiplier = 1,
    132			.m_shift = 24,
    133			.m_bits = 7,
    134			.m_offset = 1,
    135			.n_shift = 18,
    136			.n_bits = 5,
    137			.n_offset = 1,
    138			.od_shift = 16,
    139			.od_bits = 2,
    140			.od_max = 8,
    141			.od_encoding = pll_od_encoding,
    142			.bypass_bit = -1,
    143			.enable_bit = 7,
    144			.stable_bit = 6,
    145		},
    146	},
    147
    148	/* Main clocks */
    149
    150	[JZ4770_CLK_CCLK] = {
    151		"cclk", CGU_CLK_DIV,
    152		/*
    153		 * Disabling the CPU clock or any parent clocks will hang the
    154		 * system; mark it critical.
    155		 */
    156		.flags = CLK_IS_CRITICAL,
    157		.parents = { JZ4770_CLK_PLL0, },
    158		.div = {
    159			CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0,
    160			jz4770_cgu_cpccr_div_table,
    161		},
    162	},
    163	[JZ4770_CLK_H0CLK] = {
    164		"h0clk", CGU_CLK_DIV,
    165		.parents = { JZ4770_CLK_PLL0, },
    166		.div = {
    167			CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0,
    168			jz4770_cgu_cpccr_div_table,
    169		},
    170	},
    171	[JZ4770_CLK_H1CLK] = {
    172		"h1clk", CGU_CLK_DIV | CGU_CLK_GATE,
    173		.parents = { JZ4770_CLK_PLL0, },
    174		.div = {
    175			CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1, 0,
    176			jz4770_cgu_cpccr_div_table,
    177		},
    178		.gate = { CGU_REG_CLKGR1, 7 },
    179	},
    180	[JZ4770_CLK_H2CLK] = {
    181		"h2clk", CGU_CLK_DIV,
    182		.parents = { JZ4770_CLK_PLL0, },
    183		.div = {
    184			CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0,
    185			jz4770_cgu_cpccr_div_table,
    186		},
    187	},
    188	[JZ4770_CLK_C1CLK] = {
    189		"c1clk", CGU_CLK_DIV | CGU_CLK_GATE,
    190		.parents = { JZ4770_CLK_PLL0, },
    191		.div = {
    192			CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0,
    193			jz4770_cgu_cpccr_div_table,
    194		},
    195		.gate = { CGU_REG_OPCR, 31, true }, // disable CCLK stop on idle
    196	},
    197	[JZ4770_CLK_PCLK] = {
    198		"pclk", CGU_CLK_DIV,
    199		.parents = { JZ4770_CLK_PLL0, },
    200		.div = {
    201			CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0,
    202			jz4770_cgu_cpccr_div_table,
    203		},
    204	},
    205
    206	/* Those divided clocks can connect to PLL0 or PLL1 */
    207
    208	[JZ4770_CLK_MMC0_MUX] = {
    209		"mmc0_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
    210		.parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
    211		.mux = { CGU_REG_MSC0CDR, 30, 1 },
    212		.div = { CGU_REG_MSC0CDR, 0, 1, 7, -1, -1, 31 },
    213		.gate = { CGU_REG_MSC0CDR, 31 },
    214	},
    215	[JZ4770_CLK_MMC1_MUX] = {
    216		"mmc1_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
    217		.parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
    218		.mux = { CGU_REG_MSC1CDR, 30, 1 },
    219		.div = { CGU_REG_MSC1CDR, 0, 1, 7, -1, -1, 31 },
    220		.gate = { CGU_REG_MSC1CDR, 31 },
    221	},
    222	[JZ4770_CLK_MMC2_MUX] = {
    223		"mmc2_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
    224		.parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
    225		.mux = { CGU_REG_MSC2CDR, 30, 1 },
    226		.div = { CGU_REG_MSC2CDR, 0, 1, 7, -1, -1, 31 },
    227		.gate = { CGU_REG_MSC2CDR, 31 },
    228	},
    229	[JZ4770_CLK_CIM] = {
    230		"cim", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
    231		.parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
    232		.mux = { CGU_REG_CIMCDR, 31, 1 },
    233		.div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 },
    234		.gate = { CGU_REG_CLKGR0, 26 },
    235	},
    236	[JZ4770_CLK_UHC] = {
    237		"uhc", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
    238		.parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
    239		.mux = { CGU_REG_UHCCDR, 29, 1 },
    240		.div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 },
    241		.gate = { CGU_REG_CLKGR0, 24 },
    242	},
    243	[JZ4770_CLK_GPU] = {
    244		"gpu", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
    245		.parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, -1 },
    246		.mux = { CGU_REG_GPUCDR, 31, 1 },
    247		.div = { CGU_REG_GPUCDR, 0, 1, 3, -1, -1, -1 },
    248		.gate = { CGU_REG_CLKGR1, 9 },
    249	},
    250	[JZ4770_CLK_BCH] = {
    251		"bch", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
    252		.parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
    253		.mux = { CGU_REG_BCHCDR, 31, 1 },
    254		.div = { CGU_REG_BCHCDR, 0, 1, 3, -1, -1, -1 },
    255		.gate = { CGU_REG_CLKGR0, 1 },
    256	},
    257	[JZ4770_CLK_LPCLK_MUX] = {
    258		"lpclk", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
    259		.parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
    260		.mux = { CGU_REG_LPCDR, 29, 1 },
    261		.div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },
    262		.gate = { CGU_REG_CLKGR0, 28 },
    263	},
    264	[JZ4770_CLK_GPS] = {
    265		"gps", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
    266		.parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
    267		.mux = { CGU_REG_GPSCDR, 31, 1 },
    268		.div = { CGU_REG_GPSCDR, 0, 1, 4, -1, -1, -1 },
    269		.gate = { CGU_REG_CLKGR0, 22 },
    270	},
    271
    272	/* Those divided clocks can connect to EXT, PLL0 or PLL1 */
    273
    274	[JZ4770_CLK_SSI_MUX] = {
    275		"ssi_mux", CGU_CLK_DIV | CGU_CLK_MUX,
    276		.parents = { JZ4770_CLK_EXT, -1,
    277			JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
    278		.mux = { CGU_REG_SSICDR, 30, 2 },
    279		.div = { CGU_REG_SSICDR, 0, 1, 6, -1, -1, -1 },
    280	},
    281	[JZ4770_CLK_PCM_MUX] = {
    282		"pcm_mux", CGU_CLK_DIV | CGU_CLK_MUX,
    283		.parents = { JZ4770_CLK_EXT, -1,
    284			JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
    285		.mux = { CGU_REG_PCMCDR, 30, 2 },
    286		.div = { CGU_REG_PCMCDR, 0, 1, 9, -1, -1, -1 },
    287	},
    288	[JZ4770_CLK_I2S] = {
    289		"i2s", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
    290		.parents = { JZ4770_CLK_EXT, -1,
    291			JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
    292		.mux = { CGU_REG_I2SCDR, 30, 2 },
    293		.div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 },
    294		.gate = { CGU_REG_CLKGR1, 13 },
    295	},
    296	[JZ4770_CLK_OTG] = {
    297		"usb", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
    298		.parents = { JZ4770_CLK_EXT, -1,
    299			JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
    300		.mux = { CGU_REG_USBCDR, 30, 2 },
    301		.div = { CGU_REG_USBCDR, 0, 1, 8, -1, -1, -1 },
    302		.gate = { CGU_REG_CLKGR0, 2 },
    303	},
    304
    305	/* Gate-only clocks */
    306
    307	[JZ4770_CLK_SSI0] = {
    308		"ssi0", CGU_CLK_GATE,
    309		.parents = { JZ4770_CLK_SSI_MUX, },
    310		.gate = { CGU_REG_CLKGR0, 4 },
    311	},
    312	[JZ4770_CLK_SSI1] = {
    313		"ssi1", CGU_CLK_GATE,
    314		.parents = { JZ4770_CLK_SSI_MUX, },
    315		.gate = { CGU_REG_CLKGR0, 19 },
    316	},
    317	[JZ4770_CLK_SSI2] = {
    318		"ssi2", CGU_CLK_GATE,
    319		.parents = { JZ4770_CLK_SSI_MUX, },
    320		.gate = { CGU_REG_CLKGR0, 20 },
    321	},
    322	[JZ4770_CLK_PCM0] = {
    323		"pcm0", CGU_CLK_GATE,
    324		.parents = { JZ4770_CLK_PCM_MUX, },
    325		.gate = { CGU_REG_CLKGR1, 8 },
    326	},
    327	[JZ4770_CLK_PCM1] = {
    328		"pcm1", CGU_CLK_GATE,
    329		.parents = { JZ4770_CLK_PCM_MUX, },
    330		.gate = { CGU_REG_CLKGR1, 10 },
    331	},
    332	[JZ4770_CLK_DMA] = {
    333		"dma", CGU_CLK_GATE,
    334		.parents = { JZ4770_CLK_H2CLK, },
    335		.gate = { CGU_REG_CLKGR0, 21 },
    336	},
    337	[JZ4770_CLK_BDMA] = {
    338		"bdma", CGU_CLK_GATE,
    339		.parents = { JZ4770_CLK_H2CLK, },
    340		.gate = { CGU_REG_CLKGR1, 0 },
    341	},
    342	[JZ4770_CLK_I2C0] = {
    343		"i2c0", CGU_CLK_GATE,
    344		.parents = { JZ4770_CLK_EXT, },
    345		.gate = { CGU_REG_CLKGR0, 5 },
    346	},
    347	[JZ4770_CLK_I2C1] = {
    348		"i2c1", CGU_CLK_GATE,
    349		.parents = { JZ4770_CLK_EXT, },
    350		.gate = { CGU_REG_CLKGR0, 6 },
    351	},
    352	[JZ4770_CLK_I2C2] = {
    353		"i2c2", CGU_CLK_GATE,
    354		.parents = { JZ4770_CLK_EXT, },
    355		.gate = { CGU_REG_CLKGR1, 15 },
    356	},
    357	[JZ4770_CLK_UART0] = {
    358		"uart0", CGU_CLK_GATE,
    359		.parents = { JZ4770_CLK_EXT, },
    360		.gate = { CGU_REG_CLKGR0, 15 },
    361	},
    362	[JZ4770_CLK_UART1] = {
    363		"uart1", CGU_CLK_GATE,
    364		.parents = { JZ4770_CLK_EXT, },
    365		.gate = { CGU_REG_CLKGR0, 16 },
    366	},
    367	[JZ4770_CLK_UART2] = {
    368		"uart2", CGU_CLK_GATE,
    369		.parents = { JZ4770_CLK_EXT, },
    370		.gate = { CGU_REG_CLKGR0, 17 },
    371	},
    372	[JZ4770_CLK_UART3] = {
    373		"uart3", CGU_CLK_GATE,
    374		.parents = { JZ4770_CLK_EXT, },
    375		.gate = { CGU_REG_CLKGR0, 18 },
    376	},
    377	[JZ4770_CLK_IPU] = {
    378		"ipu", CGU_CLK_GATE,
    379		.parents = { JZ4770_CLK_H0CLK, },
    380		.gate = { CGU_REG_CLKGR0, 29 },
    381	},
    382	[JZ4770_CLK_ADC] = {
    383		"adc", CGU_CLK_GATE,
    384		.parents = { JZ4770_CLK_EXT, },
    385		.gate = { CGU_REG_CLKGR0, 14 },
    386	},
    387	[JZ4770_CLK_AIC] = {
    388		"aic", CGU_CLK_GATE,
    389		.parents = { JZ4770_CLK_EXT, },
    390		.gate = { CGU_REG_CLKGR0, 8 },
    391	},
    392	[JZ4770_CLK_AUX] = {
    393		"aux", CGU_CLK_GATE,
    394		.parents = { JZ4770_CLK_C1CLK, },
    395		.gate = { CGU_REG_CLKGR1, 14 },
    396	},
    397	[JZ4770_CLK_VPU] = {
    398		"vpu", CGU_CLK_GATE,
    399		.parents = { JZ4770_CLK_H1CLK, },
    400		.gate = { CGU_REG_LCR, 30, false, 150 },
    401	},
    402	[JZ4770_CLK_MMC0] = {
    403		"mmc0", CGU_CLK_GATE,
    404		.parents = { JZ4770_CLK_MMC0_MUX, },
    405		.gate = { CGU_REG_CLKGR0, 3 },
    406	},
    407	[JZ4770_CLK_MMC1] = {
    408		"mmc1", CGU_CLK_GATE,
    409		.parents = { JZ4770_CLK_MMC1_MUX, },
    410		.gate = { CGU_REG_CLKGR0, 11 },
    411	},
    412	[JZ4770_CLK_MMC2] = {
    413		"mmc2", CGU_CLK_GATE,
    414		.parents = { JZ4770_CLK_MMC2_MUX, },
    415		.gate = { CGU_REG_CLKGR0, 12 },
    416	},
    417	[JZ4770_CLK_OTG_PHY] = {
    418		"usb_phy", CGU_CLK_GATE,
    419		.parents = { JZ4770_CLK_OTG },
    420		.gate = { CGU_REG_OPCR, 7, true, 50 },
    421	},
    422
    423	/* Custom clocks */
    424
    425	[JZ4770_CLK_UHC_PHY] = {
    426		"uhc_phy", CGU_CLK_CUSTOM,
    427		.parents = { JZ4770_CLK_UHC, -1, -1, -1 },
    428		.custom = { &jz4770_uhc_phy_ops },
    429	},
    430
    431	[JZ4770_CLK_EXT512] = {
    432		"ext/512", CGU_CLK_FIXDIV,
    433		.parents = { JZ4770_CLK_EXT },
    434		.fixdiv = { 512 },
    435	},
    436
    437	[JZ4770_CLK_RTC] = {
    438		"rtc", CGU_CLK_MUX,
    439		.parents = { JZ4770_CLK_EXT512, JZ4770_CLK_OSC32K, },
    440		.mux = { CGU_REG_OPCR, 2, 1},
    441	},
    442};
    443
    444static void __init jz4770_cgu_init(struct device_node *np)
    445{
    446	int retval;
    447
    448	cgu = ingenic_cgu_new(jz4770_cgu_clocks,
    449			      ARRAY_SIZE(jz4770_cgu_clocks), np);
    450	if (!cgu) {
    451		pr_err("%s: failed to initialise CGU\n", __func__);
    452		return;
    453	}
    454
    455	retval = ingenic_cgu_register_clocks(cgu);
    456	if (retval)
    457		pr_err("%s: failed to register CGU Clocks\n", __func__);
    458
    459	ingenic_cgu_register_syscore_ops(cgu);
    460}
    461
    462/* We only probe via devicetree, no need for a platform driver */
    463CLK_OF_DECLARE_DRIVER(jz4770_cgu, "ingenic,jz4770-cgu", jz4770_cgu_init);