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

bg2q.c (10490B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2014 Marvell Technology Group Ltd.
      4 *
      5 * Alexandre Belloni <alexandre.belloni@free-electrons.com>
      6 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
      7 */
      8
      9#include <linux/clk.h>
     10#include <linux/clk-provider.h>
     11#include <linux/io.h>
     12#include <linux/kernel.h>
     13#include <linux/of.h>
     14#include <linux/of_address.h>
     15#include <linux/slab.h>
     16
     17#include <dt-bindings/clock/berlin2q.h>
     18
     19#include "berlin2-div.h"
     20#include "berlin2-pll.h"
     21#include "common.h"
     22
     23#define REG_PINMUX0		0x0018
     24#define REG_PINMUX5		0x002c
     25#define REG_SYSPLLCTL0		0x0030
     26#define REG_SYSPLLCTL4		0x0040
     27#define REG_CLKENABLE		0x00e8
     28#define REG_CLKSELECT0		0x00ec
     29#define REG_CLKSELECT1		0x00f0
     30#define REG_CLKSELECT2		0x00f4
     31#define REG_CLKSWITCH0		0x00f8
     32#define REG_CLKSWITCH1		0x00fc
     33#define REG_SW_GENERIC0		0x0110
     34#define REG_SW_GENERIC3		0x011c
     35#define REG_SDIO0XIN_CLKCTL	0x0158
     36#define REG_SDIO1XIN_CLKCTL	0x015c
     37
     38#define	MAX_CLKS 28
     39static struct clk_hw_onecell_data *clk_data;
     40static DEFINE_SPINLOCK(lock);
     41static void __iomem *gbase;
     42static void __iomem *cpupll_base;
     43
     44enum {
     45	REFCLK,
     46	SYSPLL, CPUPLL,
     47	AVPLL_B1, AVPLL_B2, AVPLL_B3, AVPLL_B4,
     48	AVPLL_B5, AVPLL_B6, AVPLL_B7, AVPLL_B8,
     49};
     50
     51static const char *clk_names[] = {
     52	[REFCLK]		= "refclk",
     53	[SYSPLL]		= "syspll",
     54	[CPUPLL]		= "cpupll",
     55	[AVPLL_B1]		= "avpll_b1",
     56	[AVPLL_B2]		= "avpll_b2",
     57	[AVPLL_B3]		= "avpll_b3",
     58	[AVPLL_B4]		= "avpll_b4",
     59	[AVPLL_B5]		= "avpll_b5",
     60	[AVPLL_B6]		= "avpll_b6",
     61	[AVPLL_B7]		= "avpll_b7",
     62	[AVPLL_B8]		= "avpll_b8",
     63};
     64
     65static const struct berlin2_pll_map bg2q_pll_map __initconst = {
     66	.vcodiv		= {1, 0, 2, 0, 3, 4, 0, 6, 8},
     67	.mult		= 1,
     68	.fbdiv_shift	= 7,
     69	.rfdiv_shift	= 2,
     70	.divsel_shift	= 9,
     71};
     72
     73static const u8 default_parent_ids[] = {
     74	SYSPLL, AVPLL_B4, AVPLL_B5, AVPLL_B6, AVPLL_B7, SYSPLL
     75};
     76
     77static const struct berlin2_div_data bg2q_divs[] __initconst = {
     78	{
     79		.name = "sys",
     80		.parent_ids = default_parent_ids,
     81		.num_parents = ARRAY_SIZE(default_parent_ids),
     82		.map = {
     83			BERLIN2_DIV_GATE(REG_CLKENABLE, 0),
     84			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 0),
     85			BERLIN2_DIV_SELECT(REG_CLKSELECT0, 3),
     86			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 3),
     87			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 4),
     88			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 5),
     89		},
     90		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
     91		.flags = CLK_IGNORE_UNUSED,
     92	},
     93	{
     94		.name = "drmfigo",
     95		.parent_ids = default_parent_ids,
     96		.num_parents = ARRAY_SIZE(default_parent_ids),
     97		.map = {
     98			BERLIN2_DIV_GATE(REG_CLKENABLE, 17),
     99			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 6),
    100			BERLIN2_DIV_SELECT(REG_CLKSELECT0, 9),
    101			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 6),
    102			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 7),
    103			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 8),
    104		},
    105		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    106		.flags = 0,
    107	},
    108	{
    109		.name = "cfg",
    110		.parent_ids = default_parent_ids,
    111		.num_parents = ARRAY_SIZE(default_parent_ids),
    112		.map = {
    113			BERLIN2_DIV_GATE(REG_CLKENABLE, 1),
    114			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 12),
    115			BERLIN2_DIV_SELECT(REG_CLKSELECT0, 15),
    116			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 9),
    117			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 10),
    118			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 11),
    119		},
    120		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    121		.flags = 0,
    122	},
    123	{
    124		.name = "gfx2d",
    125		.parent_ids = default_parent_ids,
    126		.num_parents = ARRAY_SIZE(default_parent_ids),
    127		.map = {
    128			BERLIN2_DIV_GATE(REG_CLKENABLE, 4),
    129			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 18),
    130			BERLIN2_DIV_SELECT(REG_CLKSELECT0, 21),
    131			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 12),
    132			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 13),
    133			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 14),
    134		},
    135		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    136		.flags = 0,
    137	},
    138	{
    139		.name = "zsp",
    140		.parent_ids = default_parent_ids,
    141		.num_parents = ARRAY_SIZE(default_parent_ids),
    142		.map = {
    143			BERLIN2_DIV_GATE(REG_CLKENABLE, 6),
    144			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 24),
    145			BERLIN2_DIV_SELECT(REG_CLKSELECT0, 27),
    146			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 15),
    147			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 16),
    148			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 17),
    149		},
    150		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    151		.flags = 0,
    152	},
    153	{
    154		.name = "perif",
    155		.parent_ids = default_parent_ids,
    156		.num_parents = ARRAY_SIZE(default_parent_ids),
    157		.map = {
    158			BERLIN2_DIV_GATE(REG_CLKENABLE, 7),
    159			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 0),
    160			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 3),
    161			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 18),
    162			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 19),
    163			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 20),
    164		},
    165		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    166		.flags = CLK_IGNORE_UNUSED,
    167	},
    168	{
    169		.name = "pcube",
    170		.parent_ids = default_parent_ids,
    171		.num_parents = ARRAY_SIZE(default_parent_ids),
    172		.map = {
    173			BERLIN2_DIV_GATE(REG_CLKENABLE, 2),
    174			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 6),
    175			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 9),
    176			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 21),
    177			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 22),
    178			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 23),
    179		},
    180		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    181		.flags = 0,
    182	},
    183	{
    184		.name = "vscope",
    185		.parent_ids = default_parent_ids,
    186		.num_parents = ARRAY_SIZE(default_parent_ids),
    187		.map = {
    188			BERLIN2_DIV_GATE(REG_CLKENABLE, 3),
    189			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 12),
    190			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 15),
    191			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 24),
    192			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 25),
    193			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 26),
    194		},
    195		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    196		.flags = 0,
    197	},
    198	{
    199		.name = "nfc_ecc",
    200		.parent_ids = default_parent_ids,
    201		.num_parents = ARRAY_SIZE(default_parent_ids),
    202		.map = {
    203			BERLIN2_DIV_GATE(REG_CLKENABLE, 19),
    204			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 18),
    205			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 21),
    206			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 27),
    207			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 28),
    208			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 29),
    209		},
    210		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    211		.flags = 0,
    212	},
    213	{
    214		.name = "vpp",
    215		.parent_ids = default_parent_ids,
    216		.num_parents = ARRAY_SIZE(default_parent_ids),
    217		.map = {
    218			BERLIN2_DIV_GATE(REG_CLKENABLE, 21),
    219			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 24),
    220			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 27),
    221			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 30),
    222			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 31),
    223			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 0),
    224		},
    225		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    226		.flags = 0,
    227	},
    228	{
    229		.name = "app",
    230		.parent_ids = default_parent_ids,
    231		.num_parents = ARRAY_SIZE(default_parent_ids),
    232		.map = {
    233			BERLIN2_DIV_GATE(REG_CLKENABLE, 20),
    234			BERLIN2_PLL_SELECT(REG_CLKSELECT2, 0),
    235			BERLIN2_DIV_SELECT(REG_CLKSELECT2, 3),
    236			BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 1),
    237			BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 2),
    238			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 3),
    239		},
    240		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    241		.flags = 0,
    242	},
    243	{
    244		.name = "sdio0xin",
    245		.parent_ids = default_parent_ids,
    246		.num_parents = ARRAY_SIZE(default_parent_ids),
    247		.map = {
    248			BERLIN2_SINGLE_DIV(REG_SDIO0XIN_CLKCTL),
    249		},
    250		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    251		.flags = 0,
    252	},
    253	{
    254		.name = "sdio1xin",
    255		.parent_ids = default_parent_ids,
    256		.num_parents = ARRAY_SIZE(default_parent_ids),
    257		.map = {
    258			BERLIN2_SINGLE_DIV(REG_SDIO1XIN_CLKCTL),
    259		},
    260		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    261		.flags = 0,
    262	},
    263};
    264
    265static const struct berlin2_gate_data bg2q_gates[] __initconst = {
    266	{ "gfx2daxi",	"perif",	5 },
    267	{ "geth0",	"perif",	8 },
    268	{ "sata",	"perif",	9 },
    269	{ "ahbapb",	"perif",	10, CLK_IGNORE_UNUSED },
    270	{ "usb0",	"perif",	11 },
    271	{ "usb1",	"perif",	12 },
    272	{ "usb2",	"perif",	13 },
    273	{ "usb3",	"perif",	14 },
    274	{ "pbridge",	"perif",	15, CLK_IGNORE_UNUSED },
    275	{ "sdio",	"perif",	16 },
    276	{ "nfc",	"perif",	18 },
    277	{ "pcie",	"perif",	22 },
    278};
    279
    280static void __init berlin2q_clock_setup(struct device_node *np)
    281{
    282	struct device_node *parent_np = of_get_parent(np);
    283	const char *parent_names[9];
    284	struct clk *clk;
    285	struct clk_hw **hws;
    286	int n, ret;
    287
    288	clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL);
    289	if (!clk_data)
    290		return;
    291	clk_data->num = MAX_CLKS;
    292	hws = clk_data->hws;
    293
    294	gbase = of_iomap(parent_np, 0);
    295	if (!gbase) {
    296		pr_err("%pOF: Unable to map global base\n", np);
    297		return;
    298	}
    299
    300	/* BG2Q CPU PLL is not part of global registers */
    301	cpupll_base = of_iomap(parent_np, 1);
    302	if (!cpupll_base) {
    303		pr_err("%pOF: Unable to map cpupll base\n", np);
    304		iounmap(gbase);
    305		return;
    306	}
    307
    308	/* overwrite default clock names with DT provided ones */
    309	clk = of_clk_get_by_name(np, clk_names[REFCLK]);
    310	if (!IS_ERR(clk)) {
    311		clk_names[REFCLK] = __clk_get_name(clk);
    312		clk_put(clk);
    313	}
    314
    315	/* simple register PLLs */
    316	ret = berlin2_pll_register(&bg2q_pll_map, gbase + REG_SYSPLLCTL0,
    317				   clk_names[SYSPLL], clk_names[REFCLK], 0);
    318	if (ret)
    319		goto bg2q_fail;
    320
    321	ret = berlin2_pll_register(&bg2q_pll_map, cpupll_base,
    322				   clk_names[CPUPLL], clk_names[REFCLK], 0);
    323	if (ret)
    324		goto bg2q_fail;
    325
    326	/* TODO: add BG2Q AVPLL */
    327
    328	/*
    329	 * TODO: add reference clock bypass switches:
    330	 * memPLLSWBypass, cpuPLLSWBypass, and sysPLLSWBypass
    331	 */
    332
    333	/* clock divider cells */
    334	for (n = 0; n < ARRAY_SIZE(bg2q_divs); n++) {
    335		const struct berlin2_div_data *dd = &bg2q_divs[n];
    336		int k;
    337
    338		for (k = 0; k < dd->num_parents; k++)
    339			parent_names[k] = clk_names[dd->parent_ids[k]];
    340
    341		hws[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase,
    342				dd->name, dd->div_flags, parent_names,
    343				dd->num_parents, dd->flags, &lock);
    344	}
    345
    346	/* clock gate cells */
    347	for (n = 0; n < ARRAY_SIZE(bg2q_gates); n++) {
    348		const struct berlin2_gate_data *gd = &bg2q_gates[n];
    349
    350		hws[CLKID_GFX2DAXI + n] = clk_hw_register_gate(NULL, gd->name,
    351			    gd->parent_name, gd->flags, gbase + REG_CLKENABLE,
    352			    gd->bit_idx, 0, &lock);
    353	}
    354
    355	/* cpuclk divider is fixed to 1 */
    356	hws[CLKID_CPU] =
    357		clk_hw_register_fixed_factor(NULL, "cpu", clk_names[CPUPLL],
    358					  0, 1, 1);
    359	/* twdclk is derived from cpu/3 */
    360	hws[CLKID_TWD] =
    361		clk_hw_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3);
    362
    363	/* check for errors on leaf clocks */
    364	for (n = 0; n < MAX_CLKS; n++) {
    365		if (!IS_ERR(hws[n]))
    366			continue;
    367
    368		pr_err("%pOF: Unable to register leaf clock %d\n", np, n);
    369		goto bg2q_fail;
    370	}
    371
    372	/* register clk-provider */
    373	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
    374
    375	return;
    376
    377bg2q_fail:
    378	iounmap(cpupll_base);
    379	iounmap(gbase);
    380}
    381CLK_OF_DECLARE(berlin2q_clk, "marvell,berlin2q-clk",
    382	       berlin2q_clock_setup);