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

bg2.c (19032B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2014 Marvell Technology Group Ltd.
      4 *
      5 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
      6 * Alexandre Belloni <alexandre.belloni@free-electrons.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/berlin2.h>
     18
     19#include "berlin2-avpll.h"
     20#include "berlin2-div.h"
     21#include "berlin2-pll.h"
     22#include "common.h"
     23
     24#define REG_PINMUX0		0x0000
     25#define REG_PINMUX1		0x0004
     26#define REG_SYSPLLCTL0		0x0014
     27#define REG_SYSPLLCTL4		0x0024
     28#define REG_MEMPLLCTL0		0x0028
     29#define REG_MEMPLLCTL4		0x0038
     30#define REG_CPUPLLCTL0		0x003c
     31#define REG_CPUPLLCTL4		0x004c
     32#define REG_AVPLLCTL0		0x0050
     33#define REG_AVPLLCTL31		0x00cc
     34#define REG_AVPLLCTL62		0x0148
     35#define REG_PLLSTATUS		0x014c
     36#define REG_CLKENABLE		0x0150
     37#define REG_CLKSELECT0		0x0154
     38#define REG_CLKSELECT1		0x0158
     39#define REG_CLKSELECT2		0x015c
     40#define REG_CLKSELECT3		0x0160
     41#define REG_CLKSWITCH0		0x0164
     42#define REG_CLKSWITCH1		0x0168
     43#define REG_RESET_TRIGGER	0x0178
     44#define REG_RESET_STATUS0	0x017c
     45#define REG_RESET_STATUS1	0x0180
     46#define REG_SW_GENERIC0		0x0184
     47#define REG_SW_GENERIC3		0x0190
     48#define REG_PRODUCTID		0x01cc
     49#define REG_PRODUCTID_EXT	0x01d0
     50#define REG_GFX3DCORE_CLKCTL	0x022c
     51#define REG_GFX3DSYS_CLKCTL	0x0230
     52#define REG_ARC_CLKCTL		0x0234
     53#define REG_VIP_CLKCTL		0x0238
     54#define REG_SDIO0XIN_CLKCTL	0x023c
     55#define REG_SDIO1XIN_CLKCTL	0x0240
     56#define REG_GFX3DEXTRA_CLKCTL	0x0244
     57#define REG_GFX3D_RESET		0x0248
     58#define REG_GC360_CLKCTL	0x024c
     59#define REG_SDIO_DLLMST_CLKCTL	0x0250
     60
     61/*
     62 * BG2/BG2CD SoCs have the following audio/video I/O units:
     63 *
     64 * audiohd: HDMI TX audio
     65 * audio0:  7.1ch TX
     66 * audio1:  2ch TX
     67 * audio2:  2ch RX
     68 * audio3:  SPDIF TX
     69 * video0:  HDMI video
     70 * video1:  Secondary video
     71 * video2:  SD auxiliary video
     72 *
     73 * There are no external audio clocks (ACLKI0, ACLKI1) and
     74 * only one external video clock (VCLKI0).
     75 *
     76 * Currently missing bits and pieces:
     77 * - audio_fast_pll is unknown
     78 * - audiohd_pll is unknown
     79 * - video0_pll is unknown
     80 * - audio[023], audiohd parent pll is assumed to be audio_fast_pll
     81 *
     82 */
     83
     84#define	MAX_CLKS 41
     85static struct clk_hw_onecell_data *clk_data;
     86static DEFINE_SPINLOCK(lock);
     87static void __iomem *gbase;
     88
     89enum {
     90	REFCLK, VIDEO_EXT0,
     91	SYSPLL, MEMPLL, CPUPLL,
     92	AVPLL_A1, AVPLL_A2, AVPLL_A3, AVPLL_A4,
     93	AVPLL_A5, AVPLL_A6, AVPLL_A7, AVPLL_A8,
     94	AVPLL_B1, AVPLL_B2, AVPLL_B3, AVPLL_B4,
     95	AVPLL_B5, AVPLL_B6, AVPLL_B7, AVPLL_B8,
     96	AUDIO1_PLL, AUDIO_FAST_PLL,
     97	VIDEO0_PLL, VIDEO0_IN,
     98	VIDEO1_PLL, VIDEO1_IN,
     99	VIDEO2_PLL, VIDEO2_IN,
    100};
    101
    102static const char *clk_names[] = {
    103	[REFCLK]		= "refclk",
    104	[VIDEO_EXT0]		= "video_ext0",
    105	[SYSPLL]		= "syspll",
    106	[MEMPLL]		= "mempll",
    107	[CPUPLL]		= "cpupll",
    108	[AVPLL_A1]		= "avpll_a1",
    109	[AVPLL_A2]		= "avpll_a2",
    110	[AVPLL_A3]		= "avpll_a3",
    111	[AVPLL_A4]		= "avpll_a4",
    112	[AVPLL_A5]		= "avpll_a5",
    113	[AVPLL_A6]		= "avpll_a6",
    114	[AVPLL_A7]		= "avpll_a7",
    115	[AVPLL_A8]		= "avpll_a8",
    116	[AVPLL_B1]		= "avpll_b1",
    117	[AVPLL_B2]		= "avpll_b2",
    118	[AVPLL_B3]		= "avpll_b3",
    119	[AVPLL_B4]		= "avpll_b4",
    120	[AVPLL_B5]		= "avpll_b5",
    121	[AVPLL_B6]		= "avpll_b6",
    122	[AVPLL_B7]		= "avpll_b7",
    123	[AVPLL_B8]		= "avpll_b8",
    124	[AUDIO1_PLL]		= "audio1_pll",
    125	[AUDIO_FAST_PLL]	= "audio_fast_pll",
    126	[VIDEO0_PLL]		= "video0_pll",
    127	[VIDEO0_IN]		= "video0_in",
    128	[VIDEO1_PLL]		= "video1_pll",
    129	[VIDEO1_IN]		= "video1_in",
    130	[VIDEO2_PLL]		= "video2_pll",
    131	[VIDEO2_IN]		= "video2_in",
    132};
    133
    134static const struct berlin2_pll_map bg2_pll_map __initconst = {
    135	.vcodiv		= {10, 15, 20, 25, 30, 40, 50, 60, 80},
    136	.mult		= 10,
    137	.fbdiv_shift	= 6,
    138	.rfdiv_shift	= 1,
    139	.divsel_shift	= 7,
    140};
    141
    142static const u8 default_parent_ids[] = {
    143	SYSPLL, AVPLL_B4, AVPLL_A5, AVPLL_B6, AVPLL_B7, SYSPLL
    144};
    145
    146static const struct berlin2_div_data bg2_divs[] __initconst = {
    147	{
    148		.name = "sys",
    149		.parent_ids = (const u8 []){
    150			SYSPLL, AVPLL_B4, AVPLL_B5, AVPLL_B6, AVPLL_B7, SYSPLL
    151		},
    152		.num_parents = 6,
    153		.map = {
    154			BERLIN2_DIV_GATE(REG_CLKENABLE, 0),
    155			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 0),
    156			BERLIN2_DIV_SELECT(REG_CLKSELECT0, 3),
    157			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 3),
    158			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 4),
    159			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 5),
    160		},
    161		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    162		.flags = CLK_IGNORE_UNUSED,
    163	},
    164	{
    165		.name = "cpu",
    166		.parent_ids = (const u8 []){
    167			CPUPLL, MEMPLL, MEMPLL, MEMPLL, MEMPLL
    168		},
    169		.num_parents = 5,
    170		.map = {
    171			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 6),
    172			BERLIN2_DIV_SELECT(REG_CLKSELECT0, 9),
    173			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 6),
    174			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 7),
    175			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 8),
    176		},
    177		.div_flags = BERLIN2_DIV_HAS_MUX,
    178		.flags = 0,
    179	},
    180	{
    181		.name = "drmfigo",
    182		.parent_ids = default_parent_ids,
    183		.num_parents = ARRAY_SIZE(default_parent_ids),
    184		.map = {
    185			BERLIN2_DIV_GATE(REG_CLKENABLE, 16),
    186			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 17),
    187			BERLIN2_DIV_SELECT(REG_CLKSELECT0, 20),
    188			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 12),
    189			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 13),
    190			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 14),
    191		},
    192		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    193		.flags = 0,
    194	},
    195	{
    196		.name = "cfg",
    197		.parent_ids = default_parent_ids,
    198		.num_parents = ARRAY_SIZE(default_parent_ids),
    199		.map = {
    200			BERLIN2_DIV_GATE(REG_CLKENABLE, 1),
    201			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 23),
    202			BERLIN2_DIV_SELECT(REG_CLKSELECT0, 26),
    203			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 15),
    204			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 16),
    205			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 17),
    206		},
    207		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    208		.flags = 0,
    209	},
    210	{
    211		.name = "gfx",
    212		.parent_ids = default_parent_ids,
    213		.num_parents = ARRAY_SIZE(default_parent_ids),
    214		.map = {
    215			BERLIN2_DIV_GATE(REG_CLKENABLE, 4),
    216			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 29),
    217			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 0),
    218			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 18),
    219			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 19),
    220			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 20),
    221		},
    222		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    223		.flags = 0,
    224	},
    225	{
    226		.name = "zsp",
    227		.parent_ids = default_parent_ids,
    228		.num_parents = ARRAY_SIZE(default_parent_ids),
    229		.map = {
    230			BERLIN2_DIV_GATE(REG_CLKENABLE, 5),
    231			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 3),
    232			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 6),
    233			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 21),
    234			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 22),
    235			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 23),
    236		},
    237		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    238		.flags = 0,
    239	},
    240	{
    241		.name = "perif",
    242		.parent_ids = default_parent_ids,
    243		.num_parents = ARRAY_SIZE(default_parent_ids),
    244		.map = {
    245			BERLIN2_DIV_GATE(REG_CLKENABLE, 6),
    246			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 9),
    247			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 12),
    248			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 24),
    249			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 25),
    250			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 26),
    251		},
    252		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    253		.flags = CLK_IGNORE_UNUSED,
    254	},
    255	{
    256		.name = "pcube",
    257		.parent_ids = default_parent_ids,
    258		.num_parents = ARRAY_SIZE(default_parent_ids),
    259		.map = {
    260			BERLIN2_DIV_GATE(REG_CLKENABLE, 2),
    261			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 15),
    262			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 18),
    263			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 27),
    264			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 28),
    265			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 29),
    266		},
    267		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    268		.flags = 0,
    269	},
    270	{
    271		.name = "vscope",
    272		.parent_ids = default_parent_ids,
    273		.num_parents = ARRAY_SIZE(default_parent_ids),
    274		.map = {
    275			BERLIN2_DIV_GATE(REG_CLKENABLE, 3),
    276			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 21),
    277			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 24),
    278			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 30),
    279			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 31),
    280			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 0),
    281		},
    282		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    283		.flags = 0,
    284	},
    285	{
    286		.name = "nfc_ecc",
    287		.parent_ids = default_parent_ids,
    288		.num_parents = ARRAY_SIZE(default_parent_ids),
    289		.map = {
    290			BERLIN2_DIV_GATE(REG_CLKENABLE, 18),
    291			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 27),
    292			BERLIN2_DIV_SELECT(REG_CLKSELECT2, 0),
    293			BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 1),
    294			BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 2),
    295			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 3),
    296		},
    297		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    298		.flags = 0,
    299	},
    300	{
    301		.name = "vpp",
    302		.parent_ids = default_parent_ids,
    303		.num_parents = ARRAY_SIZE(default_parent_ids),
    304		.map = {
    305			BERLIN2_DIV_GATE(REG_CLKENABLE, 21),
    306			BERLIN2_PLL_SELECT(REG_CLKSELECT2, 3),
    307			BERLIN2_DIV_SELECT(REG_CLKSELECT2, 6),
    308			BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 4),
    309			BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 5),
    310			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 6),
    311		},
    312		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    313		.flags = 0,
    314	},
    315	{
    316		.name = "app",
    317		.parent_ids = default_parent_ids,
    318		.num_parents = ARRAY_SIZE(default_parent_ids),
    319		.map = {
    320			BERLIN2_DIV_GATE(REG_CLKENABLE, 20),
    321			BERLIN2_PLL_SELECT(REG_CLKSELECT2, 9),
    322			BERLIN2_DIV_SELECT(REG_CLKSELECT2, 12),
    323			BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 7),
    324			BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 8),
    325			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 9),
    326		},
    327		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    328		.flags = 0,
    329	},
    330	{
    331		.name = "audio0",
    332		.parent_ids = (const u8 []){ AUDIO_FAST_PLL },
    333		.num_parents = 1,
    334		.map = {
    335			BERLIN2_DIV_GATE(REG_CLKENABLE, 22),
    336			BERLIN2_DIV_SELECT(REG_CLKSELECT2, 17),
    337			BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 10),
    338			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 11),
    339		},
    340		.div_flags = BERLIN2_DIV_HAS_GATE,
    341		.flags = 0,
    342	},
    343	{
    344		.name = "audio2",
    345		.parent_ids = (const u8 []){ AUDIO_FAST_PLL },
    346		.num_parents = 1,
    347		.map = {
    348			BERLIN2_DIV_GATE(REG_CLKENABLE, 24),
    349			BERLIN2_DIV_SELECT(REG_CLKSELECT2, 20),
    350			BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 14),
    351			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 15),
    352		},
    353		.div_flags = BERLIN2_DIV_HAS_GATE,
    354		.flags = 0,
    355	},
    356	{
    357		.name = "audio3",
    358		.parent_ids = (const u8 []){ AUDIO_FAST_PLL },
    359		.num_parents = 1,
    360		.map = {
    361			BERLIN2_DIV_GATE(REG_CLKENABLE, 25),
    362			BERLIN2_DIV_SELECT(REG_CLKSELECT2, 23),
    363			BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 16),
    364			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 17),
    365		},
    366		.div_flags = BERLIN2_DIV_HAS_GATE,
    367		.flags = 0,
    368	},
    369	{
    370		.name = "audio1",
    371		.parent_ids = (const u8 []){ AUDIO1_PLL },
    372		.num_parents = 1,
    373		.map = {
    374			BERLIN2_DIV_GATE(REG_CLKENABLE, 23),
    375			BERLIN2_DIV_SELECT(REG_CLKSELECT3, 0),
    376			BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 12),
    377			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 13),
    378		},
    379		.div_flags = BERLIN2_DIV_HAS_GATE,
    380		.flags = 0,
    381	},
    382	{
    383		.name = "gfx3d_core",
    384		.parent_ids = default_parent_ids,
    385		.num_parents = ARRAY_SIZE(default_parent_ids),
    386		.map = {
    387			BERLIN2_SINGLE_DIV(REG_GFX3DCORE_CLKCTL),
    388		},
    389		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    390		.flags = 0,
    391	},
    392	{
    393		.name = "gfx3d_sys",
    394		.parent_ids = default_parent_ids,
    395		.num_parents = ARRAY_SIZE(default_parent_ids),
    396		.map = {
    397			BERLIN2_SINGLE_DIV(REG_GFX3DSYS_CLKCTL),
    398		},
    399		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    400		.flags = 0,
    401	},
    402	{
    403		.name = "arc",
    404		.parent_ids = default_parent_ids,
    405		.num_parents = ARRAY_SIZE(default_parent_ids),
    406		.map = {
    407			BERLIN2_SINGLE_DIV(REG_ARC_CLKCTL),
    408		},
    409		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    410		.flags = 0,
    411	},
    412	{
    413		.name = "vip",
    414		.parent_ids = default_parent_ids,
    415		.num_parents = ARRAY_SIZE(default_parent_ids),
    416		.map = {
    417			BERLIN2_SINGLE_DIV(REG_VIP_CLKCTL),
    418		},
    419		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    420		.flags = 0,
    421	},
    422	{
    423		.name = "sdio0xin",
    424		.parent_ids = default_parent_ids,
    425		.num_parents = ARRAY_SIZE(default_parent_ids),
    426		.map = {
    427			BERLIN2_SINGLE_DIV(REG_SDIO0XIN_CLKCTL),
    428		},
    429		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    430		.flags = 0,
    431	},
    432	{
    433		.name = "sdio1xin",
    434		.parent_ids = default_parent_ids,
    435		.num_parents = ARRAY_SIZE(default_parent_ids),
    436		.map = {
    437			BERLIN2_SINGLE_DIV(REG_SDIO1XIN_CLKCTL),
    438		},
    439		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    440		.flags = 0,
    441	},
    442	{
    443		.name = "gfx3d_extra",
    444		.parent_ids = default_parent_ids,
    445		.num_parents = ARRAY_SIZE(default_parent_ids),
    446		.map = {
    447			BERLIN2_SINGLE_DIV(REG_GFX3DEXTRA_CLKCTL),
    448		},
    449		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    450		.flags = 0,
    451	},
    452	{
    453		.name = "gc360",
    454		.parent_ids = default_parent_ids,
    455		.num_parents = ARRAY_SIZE(default_parent_ids),
    456		.map = {
    457			BERLIN2_SINGLE_DIV(REG_GC360_CLKCTL),
    458		},
    459		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    460		.flags = 0,
    461	},
    462	{
    463		.name = "sdio_dllmst",
    464		.parent_ids = default_parent_ids,
    465		.num_parents = ARRAY_SIZE(default_parent_ids),
    466		.map = {
    467			BERLIN2_SINGLE_DIV(REG_SDIO_DLLMST_CLKCTL),
    468		},
    469		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
    470		.flags = 0,
    471	},
    472};
    473
    474static const struct berlin2_gate_data bg2_gates[] __initconst = {
    475	{ "geth0",	"perif",	7 },
    476	{ "geth1",	"perif",	8 },
    477	{ "sata",	"perif",	9 },
    478	{ "ahbapb",	"perif",	10, CLK_IGNORE_UNUSED },
    479	{ "usb0",	"perif",	11 },
    480	{ "usb1",	"perif",	12 },
    481	{ "pbridge",	"perif",	13, CLK_IGNORE_UNUSED },
    482	{ "sdio0",	"perif",	14 },
    483	{ "sdio1",	"perif",	15 },
    484	{ "nfc",	"perif",	17 },
    485	{ "smemc",	"perif",	19 },
    486	{ "audiohd",	"audiohd_pll",	26 },
    487	{ "video0",	"video0_in",	27 },
    488	{ "video1",	"video1_in",	28 },
    489	{ "video2",	"video2_in",	29 },
    490};
    491
    492static void __init berlin2_clock_setup(struct device_node *np)
    493{
    494	struct device_node *parent_np = of_get_parent(np);
    495	const char *parent_names[9];
    496	struct clk *clk;
    497	struct clk_hw *hw;
    498	struct clk_hw **hws;
    499	u8 avpll_flags = 0;
    500	int n, ret;
    501
    502	clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL);
    503	if (!clk_data)
    504		return;
    505	clk_data->num = MAX_CLKS;
    506	hws = clk_data->hws;
    507
    508	gbase = of_iomap(parent_np, 0);
    509	if (!gbase)
    510		return;
    511
    512	/* overwrite default clock names with DT provided ones */
    513	clk = of_clk_get_by_name(np, clk_names[REFCLK]);
    514	if (!IS_ERR(clk)) {
    515		clk_names[REFCLK] = __clk_get_name(clk);
    516		clk_put(clk);
    517	}
    518
    519	clk = of_clk_get_by_name(np, clk_names[VIDEO_EXT0]);
    520	if (!IS_ERR(clk)) {
    521		clk_names[VIDEO_EXT0] = __clk_get_name(clk);
    522		clk_put(clk);
    523	}
    524
    525	/* simple register PLLs */
    526	ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_SYSPLLCTL0,
    527				   clk_names[SYSPLL], clk_names[REFCLK], 0);
    528	if (ret)
    529		goto bg2_fail;
    530
    531	ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_MEMPLLCTL0,
    532				   clk_names[MEMPLL], clk_names[REFCLK], 0);
    533	if (ret)
    534		goto bg2_fail;
    535
    536	ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_CPUPLLCTL0,
    537				   clk_names[CPUPLL], clk_names[REFCLK], 0);
    538	if (ret)
    539		goto bg2_fail;
    540
    541	if (of_device_is_compatible(np, "marvell,berlin2-global-register"))
    542		avpll_flags |= BERLIN2_AVPLL_SCRAMBLE_QUIRK;
    543
    544	/* audio/video VCOs */
    545	ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL0, "avpll_vcoA",
    546			 clk_names[REFCLK], avpll_flags, 0);
    547	if (ret)
    548		goto bg2_fail;
    549
    550	for (n = 0; n < 8; n++) {
    551		ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL0,
    552			     clk_names[AVPLL_A1 + n], n, "avpll_vcoA",
    553			     avpll_flags, 0);
    554		if (ret)
    555			goto bg2_fail;
    556	}
    557
    558	ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL31, "avpll_vcoB",
    559				 clk_names[REFCLK], BERLIN2_AVPLL_BIT_QUIRK |
    560				 avpll_flags, 0);
    561	if (ret)
    562		goto bg2_fail;
    563
    564	for (n = 0; n < 8; n++) {
    565		ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL31,
    566			     clk_names[AVPLL_B1 + n], n, "avpll_vcoB",
    567			     BERLIN2_AVPLL_BIT_QUIRK | avpll_flags, 0);
    568		if (ret)
    569			goto bg2_fail;
    570	}
    571
    572	/* reference clock bypass switches */
    573	parent_names[0] = clk_names[SYSPLL];
    574	parent_names[1] = clk_names[REFCLK];
    575	hw = clk_hw_register_mux(NULL, "syspll_byp", parent_names, 2,
    576			       0, gbase + REG_CLKSWITCH0, 0, 1, 0, &lock);
    577	if (IS_ERR(hw))
    578		goto bg2_fail;
    579	clk_names[SYSPLL] = clk_hw_get_name(hw);
    580
    581	parent_names[0] = clk_names[MEMPLL];
    582	parent_names[1] = clk_names[REFCLK];
    583	hw = clk_hw_register_mux(NULL, "mempll_byp", parent_names, 2,
    584			       0, gbase + REG_CLKSWITCH0, 1, 1, 0, &lock);
    585	if (IS_ERR(hw))
    586		goto bg2_fail;
    587	clk_names[MEMPLL] = clk_hw_get_name(hw);
    588
    589	parent_names[0] = clk_names[CPUPLL];
    590	parent_names[1] = clk_names[REFCLK];
    591	hw = clk_hw_register_mux(NULL, "cpupll_byp", parent_names, 2,
    592			       0, gbase + REG_CLKSWITCH0, 2, 1, 0, &lock);
    593	if (IS_ERR(hw))
    594		goto bg2_fail;
    595	clk_names[CPUPLL] = clk_hw_get_name(hw);
    596
    597	/* clock muxes */
    598	parent_names[0] = clk_names[AVPLL_B3];
    599	parent_names[1] = clk_names[AVPLL_A3];
    600	hw = clk_hw_register_mux(NULL, clk_names[AUDIO1_PLL], parent_names, 2,
    601			       0, gbase + REG_CLKSELECT2, 29, 1, 0, &lock);
    602	if (IS_ERR(hw))
    603		goto bg2_fail;
    604
    605	parent_names[0] = clk_names[VIDEO0_PLL];
    606	parent_names[1] = clk_names[VIDEO_EXT0];
    607	hw = clk_hw_register_mux(NULL, clk_names[VIDEO0_IN], parent_names, 2,
    608			       0, gbase + REG_CLKSELECT3, 4, 1, 0, &lock);
    609	if (IS_ERR(hw))
    610		goto bg2_fail;
    611
    612	parent_names[0] = clk_names[VIDEO1_PLL];
    613	parent_names[1] = clk_names[VIDEO_EXT0];
    614	hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_IN], parent_names, 2,
    615			       0, gbase + REG_CLKSELECT3, 6, 1, 0, &lock);
    616	if (IS_ERR(hw))
    617		goto bg2_fail;
    618
    619	parent_names[0] = clk_names[AVPLL_A2];
    620	parent_names[1] = clk_names[AVPLL_B2];
    621	hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_PLL], parent_names, 2,
    622			       0, gbase + REG_CLKSELECT3, 7, 1, 0, &lock);
    623	if (IS_ERR(hw))
    624		goto bg2_fail;
    625
    626	parent_names[0] = clk_names[VIDEO2_PLL];
    627	parent_names[1] = clk_names[VIDEO_EXT0];
    628	hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_IN], parent_names, 2,
    629			       0, gbase + REG_CLKSELECT3, 9, 1, 0, &lock);
    630	if (IS_ERR(hw))
    631		goto bg2_fail;
    632
    633	parent_names[0] = clk_names[AVPLL_B1];
    634	parent_names[1] = clk_names[AVPLL_A5];
    635	hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_PLL], parent_names, 2,
    636			       0, gbase + REG_CLKSELECT3, 10, 1, 0, &lock);
    637	if (IS_ERR(hw))
    638		goto bg2_fail;
    639
    640	/* clock divider cells */
    641	for (n = 0; n < ARRAY_SIZE(bg2_divs); n++) {
    642		const struct berlin2_div_data *dd = &bg2_divs[n];
    643		int k;
    644
    645		for (k = 0; k < dd->num_parents; k++)
    646			parent_names[k] = clk_names[dd->parent_ids[k]];
    647
    648		hws[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase,
    649				dd->name, dd->div_flags, parent_names,
    650				dd->num_parents, dd->flags, &lock);
    651	}
    652
    653	/* clock gate cells */
    654	for (n = 0; n < ARRAY_SIZE(bg2_gates); n++) {
    655		const struct berlin2_gate_data *gd = &bg2_gates[n];
    656
    657		hws[CLKID_GETH0 + n] = clk_hw_register_gate(NULL, gd->name,
    658			    gd->parent_name, gd->flags, gbase + REG_CLKENABLE,
    659			    gd->bit_idx, 0, &lock);
    660	}
    661
    662	/* twdclk is derived from cpu/3 */
    663	hws[CLKID_TWD] =
    664		clk_hw_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3);
    665
    666	/* check for errors on leaf clocks */
    667	for (n = 0; n < MAX_CLKS; n++) {
    668		if (!IS_ERR(hws[n]))
    669			continue;
    670
    671		pr_err("%pOF: Unable to register leaf clock %d\n", np, n);
    672		goto bg2_fail;
    673	}
    674
    675	/* register clk-provider */
    676	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
    677
    678	return;
    679
    680bg2_fail:
    681	iounmap(gbase);
    682}
    683CLK_OF_DECLARE(berlin2_clk, "marvell,berlin2-clk",
    684	       berlin2_clock_setup);