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

x1830-cgu.c (11587B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * X1830 SoC CGU driver
      4 * Copyright (c) 2019 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
      5 */
      6
      7#include <linux/clk-provider.h>
      8#include <linux/delay.h>
      9#include <linux/io.h>
     10#include <linux/of.h>
     11
     12#include <dt-bindings/clock/ingenic,x1830-cgu.h>
     13
     14#include "cgu.h"
     15#include "pm.h"
     16
     17/* CGU register offsets */
     18#define CGU_REG_CPCCR		0x00
     19#define CGU_REG_CPPCR		0x0c
     20#define CGU_REG_APLL		0x10
     21#define CGU_REG_MPLL		0x14
     22#define CGU_REG_CLKGR0		0x20
     23#define CGU_REG_OPCR		0x24
     24#define CGU_REG_CLKGR1		0x28
     25#define CGU_REG_DDRCDR		0x2c
     26#define CGU_REG_USBPCR		0x3c
     27#define CGU_REG_USBRDT		0x40
     28#define CGU_REG_USBVBFIL	0x44
     29#define CGU_REG_USBPCR1		0x48
     30#define CGU_REG_MACCDR		0x54
     31#define CGU_REG_EPLL		0x58
     32#define CGU_REG_I2SCDR		0x60
     33#define CGU_REG_LPCDR		0x64
     34#define CGU_REG_MSC0CDR		0x68
     35#define CGU_REG_I2SCDR1		0x70
     36#define CGU_REG_SSICDR		0x74
     37#define CGU_REG_CIMCDR		0x7c
     38#define CGU_REG_MSC1CDR		0xa4
     39#define CGU_REG_CMP_INTR	0xb0
     40#define CGU_REG_CMP_INTRE	0xb4
     41#define CGU_REG_DRCG		0xd0
     42#define CGU_REG_CPCSR		0xd4
     43#define CGU_REG_VPLL		0xe0
     44#define CGU_REG_MACPHYC		0xe8
     45
     46/* bits within the OPCR register */
     47#define OPCR_GATE_USBPHYCLK	BIT(23)
     48#define OPCR_SPENDN0		BIT(7)
     49#define OPCR_SPENDN1		BIT(6)
     50
     51/* bits within the USBPCR register */
     52#define USBPCR_SIDDQ		BIT(21)
     53#define USBPCR_OTG_DISABLE	BIT(20)
     54
     55static struct ingenic_cgu *cgu;
     56
     57static int x1830_usb_phy_enable(struct clk_hw *hw)
     58{
     59	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
     60	void __iomem *reg_usbpcr	= cgu->base + CGU_REG_USBPCR;
     61
     62	writel((readl(reg_opcr) | OPCR_SPENDN0) & ~OPCR_GATE_USBPHYCLK, reg_opcr);
     63	writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, reg_usbpcr);
     64	return 0;
     65}
     66
     67static void x1830_usb_phy_disable(struct clk_hw *hw)
     68{
     69	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
     70	void __iomem *reg_usbpcr	= cgu->base + CGU_REG_USBPCR;
     71
     72	writel((readl(reg_opcr) & ~OPCR_SPENDN0) | OPCR_GATE_USBPHYCLK, reg_opcr);
     73	writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, reg_usbpcr);
     74}
     75
     76static int x1830_usb_phy_is_enabled(struct clk_hw *hw)
     77{
     78	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
     79	void __iomem *reg_usbpcr	= cgu->base + CGU_REG_USBPCR;
     80
     81	return (readl(reg_opcr) & OPCR_SPENDN0) &&
     82		!(readl(reg_usbpcr) & USBPCR_SIDDQ) &&
     83		!(readl(reg_usbpcr) & USBPCR_OTG_DISABLE);
     84}
     85
     86static const struct clk_ops x1830_otg_phy_ops = {
     87	.enable		= x1830_usb_phy_enable,
     88	.disable	= x1830_usb_phy_disable,
     89	.is_enabled	= x1830_usb_phy_is_enabled,
     90};
     91
     92static const s8 pll_od_encoding[64] = {
     93	0x0, 0x1,  -1, 0x2,  -1,  -1,  -1, 0x3,
     94	 -1,  -1,  -1,  -1,  -1,  -1,  -1, 0x4,
     95	 -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
     96	 -1,  -1,  -1,  -1,  -1,  -1,  -1, 0x5,
     97	 -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
     98	 -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
     99	 -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
    100	 -1,  -1,  -1,  -1,  -1,  -1,  -1, 0x6,
    101};
    102
    103static const struct ingenic_cgu_clk_info x1830_cgu_clocks[] = {
    104
    105	/* External clocks */
    106
    107	[X1830_CLK_EXCLK] = { "ext", CGU_CLK_EXT },
    108	[X1830_CLK_RTCLK] = { "rtc", CGU_CLK_EXT },
    109
    110	/* PLLs */
    111
    112	[X1830_CLK_APLL] = {
    113		"apll", CGU_CLK_PLL,
    114		.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
    115		.pll = {
    116			.reg = CGU_REG_APLL,
    117			.rate_multiplier = 2,
    118			.m_shift = 20,
    119			.m_bits = 9,
    120			.m_offset = 1,
    121			.n_shift = 14,
    122			.n_bits = 6,
    123			.n_offset = 1,
    124			.od_shift = 11,
    125			.od_bits = 3,
    126			.od_max = 64,
    127			.od_encoding = pll_od_encoding,
    128			.bypass_reg = CGU_REG_CPPCR,
    129			.bypass_bit = 30,
    130			.enable_bit = 0,
    131			.stable_bit = 3,
    132		},
    133	},
    134
    135	[X1830_CLK_MPLL] = {
    136		"mpll", CGU_CLK_PLL,
    137		.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
    138		.pll = {
    139			.reg = CGU_REG_MPLL,
    140			.rate_multiplier = 2,
    141			.m_shift = 20,
    142			.m_bits = 9,
    143			.m_offset = 1,
    144			.n_shift = 14,
    145			.n_bits = 6,
    146			.n_offset = 1,
    147			.od_shift = 11,
    148			.od_bits = 3,
    149			.od_max = 64,
    150			.od_encoding = pll_od_encoding,
    151			.bypass_reg = CGU_REG_CPPCR,
    152			.bypass_bit = 28,
    153			.enable_bit = 0,
    154			.stable_bit = 3,
    155		},
    156	},
    157
    158	[X1830_CLK_EPLL] = {
    159		"epll", CGU_CLK_PLL,
    160		.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
    161		.pll = {
    162			.reg = CGU_REG_EPLL,
    163			.rate_multiplier = 2,
    164			.m_shift = 20,
    165			.m_bits = 9,
    166			.m_offset = 1,
    167			.n_shift = 14,
    168			.n_bits = 6,
    169			.n_offset = 1,
    170			.od_shift = 11,
    171			.od_bits = 3,
    172			.od_max = 64,
    173			.od_encoding = pll_od_encoding,
    174			.bypass_reg = CGU_REG_CPPCR,
    175			.bypass_bit = 24,
    176			.enable_bit = 0,
    177			.stable_bit = 3,
    178		},
    179	},
    180
    181	[X1830_CLK_VPLL] = {
    182		"vpll", CGU_CLK_PLL,
    183		.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
    184		.pll = {
    185			.reg = CGU_REG_VPLL,
    186			.rate_multiplier = 2,
    187			.m_shift = 20,
    188			.m_bits = 9,
    189			.m_offset = 1,
    190			.n_shift = 14,
    191			.n_bits = 6,
    192			.n_offset = 1,
    193			.od_shift = 11,
    194			.od_bits = 3,
    195			.od_max = 64,
    196			.od_encoding = pll_od_encoding,
    197			.bypass_reg = CGU_REG_CPPCR,
    198			.bypass_bit = 26,
    199			.enable_bit = 0,
    200			.stable_bit = 3,
    201		},
    202	},
    203
    204	/* Custom (SoC-specific) OTG PHY */
    205
    206	[X1830_CLK_OTGPHY] = {
    207		"otg_phy", CGU_CLK_CUSTOM,
    208		.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
    209		.custom = { &x1830_otg_phy_ops },
    210	},
    211
    212	/* Muxes & dividers */
    213
    214	[X1830_CLK_SCLKA] = {
    215		"sclk_a", CGU_CLK_MUX,
    216		.parents = { -1, X1830_CLK_EXCLK, X1830_CLK_APLL, -1 },
    217		.mux = { CGU_REG_CPCCR, 30, 2 },
    218	},
    219
    220	[X1830_CLK_CPUMUX] = {
    221		"cpu_mux", CGU_CLK_MUX,
    222		.parents = { -1, X1830_CLK_SCLKA, X1830_CLK_MPLL, -1 },
    223		.mux = { CGU_REG_CPCCR, 28, 2 },
    224	},
    225
    226	[X1830_CLK_CPU] = {
    227		"cpu", CGU_CLK_DIV | CGU_CLK_GATE,
    228		.flags = CLK_IS_CRITICAL,
    229		.parents = { X1830_CLK_CPUMUX, -1, -1, -1 },
    230		.div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
    231		.gate = { CGU_REG_CLKGR1, 15 },
    232	},
    233
    234	[X1830_CLK_L2CACHE] = {
    235		"l2cache", CGU_CLK_DIV,
    236		/*
    237		 * The L2 cache clock is critical if caches are enabled and
    238		 * disabling it or any parent clocks will hang the system.
    239		 */
    240		.flags = CLK_IS_CRITICAL,
    241		.parents = { X1830_CLK_CPUMUX, -1, -1, -1 },
    242		.div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 },
    243	},
    244
    245	[X1830_CLK_AHB0] = {
    246		"ahb0", CGU_CLK_MUX | CGU_CLK_DIV,
    247		.parents = { -1, X1830_CLK_SCLKA, X1830_CLK_MPLL, -1 },
    248		.mux = { CGU_REG_CPCCR, 26, 2 },
    249		.div = { CGU_REG_CPCCR, 8, 1, 4, 21, -1, -1 },
    250	},
    251
    252	[X1830_CLK_AHB2PMUX] = {
    253		"ahb2_apb_mux", CGU_CLK_MUX,
    254		.parents = { -1, X1830_CLK_SCLKA, X1830_CLK_MPLL, -1 },
    255		.mux = { CGU_REG_CPCCR, 24, 2 },
    256	},
    257
    258	[X1830_CLK_AHB2] = {
    259		"ahb2", CGU_CLK_DIV,
    260		.parents = { X1830_CLK_AHB2PMUX, -1, -1, -1 },
    261		.div = { CGU_REG_CPCCR, 12, 1, 4, 20, -1, -1 },
    262	},
    263
    264	[X1830_CLK_PCLK] = {
    265		"pclk", CGU_CLK_DIV | CGU_CLK_GATE,
    266		.parents = { X1830_CLK_AHB2PMUX, -1, -1, -1 },
    267		.div = { CGU_REG_CPCCR, 16, 1, 4, 20, -1, -1 },
    268		.gate = { CGU_REG_CLKGR1, 14 },
    269	},
    270
    271	[X1830_CLK_DDR] = {
    272		"ddr", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
    273		/*
    274		 * Disabling DDR clock or its parents will render DRAM
    275		 * inaccessible; mark it critical.
    276		 */
    277		.flags = CLK_IS_CRITICAL,
    278		.parents = { -1, X1830_CLK_SCLKA, X1830_CLK_MPLL, -1 },
    279		.mux = { CGU_REG_DDRCDR, 30, 2 },
    280		.div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 },
    281		.gate = { CGU_REG_CLKGR0, 31 },
    282	},
    283
    284	[X1830_CLK_MAC] = {
    285		"mac", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
    286		.parents = { X1830_CLK_SCLKA, X1830_CLK_MPLL,
    287					 X1830_CLK_VPLL, X1830_CLK_EPLL },
    288		.mux = { CGU_REG_MACCDR, 30, 2 },
    289		.div = { CGU_REG_MACCDR, 0, 1, 8, 29, 28, 27 },
    290		.gate = { CGU_REG_CLKGR1, 4 },
    291	},
    292
    293	[X1830_CLK_LCD] = {
    294		"lcd", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
    295		.parents = { X1830_CLK_SCLKA, X1830_CLK_MPLL,
    296					 X1830_CLK_VPLL, X1830_CLK_EPLL },
    297		.mux = { CGU_REG_LPCDR, 30, 2 },
    298		.div = { CGU_REG_LPCDR, 0, 1, 8, 28, 27, 26 },
    299		.gate = { CGU_REG_CLKGR1, 9 },
    300	},
    301
    302	[X1830_CLK_MSCMUX] = {
    303		"msc_mux", CGU_CLK_MUX,
    304		.parents = { X1830_CLK_SCLKA, X1830_CLK_MPLL,
    305					 X1830_CLK_VPLL, X1830_CLK_EPLL },
    306		.mux = { CGU_REG_MSC0CDR, 30, 2 },
    307	},
    308
    309	[X1830_CLK_MSC0] = {
    310		"msc0", CGU_CLK_DIV | CGU_CLK_GATE,
    311		.parents = { X1830_CLK_MSCMUX, -1, -1, -1 },
    312		.div = { CGU_REG_MSC0CDR, 0, 2, 8, 29, 28, 27 },
    313		.gate = { CGU_REG_CLKGR0, 4 },
    314	},
    315
    316	[X1830_CLK_MSC1] = {
    317		"msc1", CGU_CLK_DIV | CGU_CLK_GATE,
    318		.parents = { X1830_CLK_MSCMUX, -1, -1, -1 },
    319		.div = { CGU_REG_MSC1CDR, 0, 2, 8, 29, 28, 27 },
    320		.gate = { CGU_REG_CLKGR0, 5 },
    321	},
    322
    323	[X1830_CLK_SSIPLL] = {
    324		"ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV,
    325		.parents = { X1830_CLK_SCLKA, X1830_CLK_MPLL,
    326					 X1830_CLK_VPLL, X1830_CLK_EPLL },
    327		.mux = { CGU_REG_SSICDR, 30, 2 },
    328		.div = { CGU_REG_SSICDR, 0, 1, 8, 28, 27, 26 },
    329	},
    330
    331	[X1830_CLK_SSIPLL_DIV2] = {
    332		"ssi_pll_div2", CGU_CLK_FIXDIV,
    333		.parents = { X1830_CLK_SSIPLL },
    334		.fixdiv = { 2 },
    335	},
    336
    337	[X1830_CLK_SSIMUX] = {
    338		"ssi_mux", CGU_CLK_MUX,
    339		.parents = { X1830_CLK_EXCLK, X1830_CLK_SSIPLL_DIV2, -1, -1 },
    340		.mux = { CGU_REG_SSICDR, 29, 1 },
    341	},
    342
    343	[X1830_CLK_EXCLK_DIV512] = {
    344		"exclk_div512", CGU_CLK_FIXDIV,
    345		.parents = { X1830_CLK_EXCLK },
    346		.fixdiv = { 512 },
    347	},
    348
    349	[X1830_CLK_RTC] = {
    350		"rtc_ercs", CGU_CLK_MUX | CGU_CLK_GATE,
    351		.parents = { X1830_CLK_EXCLK_DIV512, X1830_CLK_RTCLK },
    352		.mux = { CGU_REG_OPCR, 2, 1},
    353		.gate = { CGU_REG_CLKGR0, 29 },
    354	},
    355
    356	/* Gate-only clocks */
    357
    358	[X1830_CLK_EMC] = {
    359		"emc", CGU_CLK_GATE,
    360		.parents = { X1830_CLK_AHB2, -1, -1, -1 },
    361		.gate = { CGU_REG_CLKGR0, 0 },
    362	},
    363
    364	[X1830_CLK_EFUSE] = {
    365		"efuse", CGU_CLK_GATE,
    366		.parents = { X1830_CLK_AHB2, -1, -1, -1 },
    367		.gate = { CGU_REG_CLKGR0, 1 },
    368	},
    369
    370	[X1830_CLK_OTG] = {
    371		"otg", CGU_CLK_GATE,
    372		.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
    373		.gate = { CGU_REG_CLKGR0, 3 },
    374	},
    375
    376	[X1830_CLK_SSI0] = {
    377		"ssi0", CGU_CLK_GATE,
    378		.parents = { X1830_CLK_SSIMUX, -1, -1, -1 },
    379		.gate = { CGU_REG_CLKGR0, 6 },
    380	},
    381
    382	[X1830_CLK_SMB0] = {
    383		"smb0", CGU_CLK_GATE,
    384		.parents = { X1830_CLK_PCLK, -1, -1, -1 },
    385		.gate = { CGU_REG_CLKGR0, 7 },
    386	},
    387
    388	[X1830_CLK_SMB1] = {
    389		"smb1", CGU_CLK_GATE,
    390		.parents = { X1830_CLK_PCLK, -1, -1, -1 },
    391		.gate = { CGU_REG_CLKGR0, 8 },
    392	},
    393
    394	[X1830_CLK_SMB2] = {
    395		"smb2", CGU_CLK_GATE,
    396		.parents = { X1830_CLK_PCLK, -1, -1, -1 },
    397		.gate = { CGU_REG_CLKGR0, 9 },
    398	},
    399
    400	[X1830_CLK_UART0] = {
    401		"uart0", CGU_CLK_GATE,
    402		.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
    403		.gate = { CGU_REG_CLKGR0, 14 },
    404	},
    405
    406	[X1830_CLK_UART1] = {
    407		"uart1", CGU_CLK_GATE,
    408		.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
    409		.gate = { CGU_REG_CLKGR0, 15 },
    410	},
    411
    412	[X1830_CLK_SSI1] = {
    413		"ssi1", CGU_CLK_GATE,
    414		.parents = { X1830_CLK_SSIMUX, -1, -1, -1 },
    415		.gate = { CGU_REG_CLKGR0, 19 },
    416	},
    417
    418	[X1830_CLK_SFC] = {
    419		"sfc", CGU_CLK_GATE,
    420		.parents = { X1830_CLK_SSIPLL, -1, -1, -1 },
    421		.gate = { CGU_REG_CLKGR0, 20 },
    422	},
    423
    424	[X1830_CLK_PDMA] = {
    425		"pdma", CGU_CLK_GATE,
    426		.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
    427		.gate = { CGU_REG_CLKGR0, 21 },
    428	},
    429
    430	[X1830_CLK_TCU] = {
    431		"tcu", CGU_CLK_GATE,
    432		.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
    433		.gate = { CGU_REG_CLKGR0, 30 },
    434	},
    435
    436	[X1830_CLK_DTRNG] = {
    437		"dtrng", CGU_CLK_GATE,
    438		.parents = { X1830_CLK_PCLK, -1, -1, -1 },
    439		.gate = { CGU_REG_CLKGR1, 1 },
    440	},
    441
    442	[X1830_CLK_OST] = {
    443		"ost", CGU_CLK_GATE,
    444		.parents = { X1830_CLK_EXCLK, -1, -1, -1 },
    445		.gate = { CGU_REG_CLKGR1, 11 },
    446	},
    447};
    448
    449static void __init x1830_cgu_init(struct device_node *np)
    450{
    451	int retval;
    452
    453	cgu = ingenic_cgu_new(x1830_cgu_clocks,
    454			      ARRAY_SIZE(x1830_cgu_clocks), np);
    455	if (!cgu) {
    456		pr_err("%s: failed to initialise CGU\n", __func__);
    457		return;
    458	}
    459
    460	retval = ingenic_cgu_register_clocks(cgu);
    461	if (retval) {
    462		pr_err("%s: failed to register CGU Clocks\n", __func__);
    463		return;
    464	}
    465
    466	ingenic_cgu_register_syscore_ops(cgu);
    467}
    468/*
    469 * CGU has some children devices, this is useful for probing children devices
    470 * in the case where the device node is compatible with "simple-mfd".
    471 */
    472CLK_OF_DECLARE_DRIVER(x1830_cgu, "ingenic,x1830-cgu", x1830_cgu_init);