162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2010,2015 Broadcom
462306a36Sopenharmony_ci * Copyright (C) 2012 Stephen Warren
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci/**
862306a36Sopenharmony_ci * DOC: BCM2835 CPRMAN (clock manager for the "audio" domain)
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * The clock tree on the 2835 has several levels.  There's a root
1162306a36Sopenharmony_ci * oscillator running at 19.2Mhz.  After the oscillator there are 5
1262306a36Sopenharmony_ci * PLLs, roughly divided as "camera", "ARM", "core", "DSI displays",
1362306a36Sopenharmony_ci * and "HDMI displays".  Those 5 PLLs each can divide their output to
1462306a36Sopenharmony_ci * produce up to 4 channels.  Finally, there is the level of clocks to
1562306a36Sopenharmony_ci * be consumed by other hardware components (like "H264" or "HDMI
1662306a36Sopenharmony_ci * state machine"), which divide off of some subset of the PLL
1762306a36Sopenharmony_ci * channels.
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * All of the clocks in the tree are exposed in the DT, because the DT
2062306a36Sopenharmony_ci * may want to make assignments of the final layer of clocks to the
2162306a36Sopenharmony_ci * PLL channels, and some components of the hardware will actually
2262306a36Sopenharmony_ci * skip layers of the tree (for example, the pixel clock comes
2362306a36Sopenharmony_ci * directly from the PLLH PIX channel without using a CM_*CTL clock
2462306a36Sopenharmony_ci * generator).
2562306a36Sopenharmony_ci */
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include <linux/clk-provider.h>
2862306a36Sopenharmony_ci#include <linux/clkdev.h>
2962306a36Sopenharmony_ci#include <linux/clk.h>
3062306a36Sopenharmony_ci#include <linux/debugfs.h>
3162306a36Sopenharmony_ci#include <linux/delay.h>
3262306a36Sopenharmony_ci#include <linux/io.h>
3362306a36Sopenharmony_ci#include <linux/math.h>
3462306a36Sopenharmony_ci#include <linux/module.h>
3562306a36Sopenharmony_ci#include <linux/of.h>
3662306a36Sopenharmony_ci#include <linux/platform_device.h>
3762306a36Sopenharmony_ci#include <linux/slab.h>
3862306a36Sopenharmony_ci#include <dt-bindings/clock/bcm2835.h>
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#define CM_PASSWORD		0x5a000000
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#define CM_GNRICCTL		0x000
4362306a36Sopenharmony_ci#define CM_GNRICDIV		0x004
4462306a36Sopenharmony_ci# define CM_DIV_FRAC_BITS	12
4562306a36Sopenharmony_ci# define CM_DIV_FRAC_MASK	GENMASK(CM_DIV_FRAC_BITS - 1, 0)
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define CM_VPUCTL		0x008
4862306a36Sopenharmony_ci#define CM_VPUDIV		0x00c
4962306a36Sopenharmony_ci#define CM_SYSCTL		0x010
5062306a36Sopenharmony_ci#define CM_SYSDIV		0x014
5162306a36Sopenharmony_ci#define CM_PERIACTL		0x018
5262306a36Sopenharmony_ci#define CM_PERIADIV		0x01c
5362306a36Sopenharmony_ci#define CM_PERIICTL		0x020
5462306a36Sopenharmony_ci#define CM_PERIIDIV		0x024
5562306a36Sopenharmony_ci#define CM_H264CTL		0x028
5662306a36Sopenharmony_ci#define CM_H264DIV		0x02c
5762306a36Sopenharmony_ci#define CM_ISPCTL		0x030
5862306a36Sopenharmony_ci#define CM_ISPDIV		0x034
5962306a36Sopenharmony_ci#define CM_V3DCTL		0x038
6062306a36Sopenharmony_ci#define CM_V3DDIV		0x03c
6162306a36Sopenharmony_ci#define CM_CAM0CTL		0x040
6262306a36Sopenharmony_ci#define CM_CAM0DIV		0x044
6362306a36Sopenharmony_ci#define CM_CAM1CTL		0x048
6462306a36Sopenharmony_ci#define CM_CAM1DIV		0x04c
6562306a36Sopenharmony_ci#define CM_CCP2CTL		0x050
6662306a36Sopenharmony_ci#define CM_CCP2DIV		0x054
6762306a36Sopenharmony_ci#define CM_DSI0ECTL		0x058
6862306a36Sopenharmony_ci#define CM_DSI0EDIV		0x05c
6962306a36Sopenharmony_ci#define CM_DSI0PCTL		0x060
7062306a36Sopenharmony_ci#define CM_DSI0PDIV		0x064
7162306a36Sopenharmony_ci#define CM_DPICTL		0x068
7262306a36Sopenharmony_ci#define CM_DPIDIV		0x06c
7362306a36Sopenharmony_ci#define CM_GP0CTL		0x070
7462306a36Sopenharmony_ci#define CM_GP0DIV		0x074
7562306a36Sopenharmony_ci#define CM_GP1CTL		0x078
7662306a36Sopenharmony_ci#define CM_GP1DIV		0x07c
7762306a36Sopenharmony_ci#define CM_GP2CTL		0x080
7862306a36Sopenharmony_ci#define CM_GP2DIV		0x084
7962306a36Sopenharmony_ci#define CM_HSMCTL		0x088
8062306a36Sopenharmony_ci#define CM_HSMDIV		0x08c
8162306a36Sopenharmony_ci#define CM_OTPCTL		0x090
8262306a36Sopenharmony_ci#define CM_OTPDIV		0x094
8362306a36Sopenharmony_ci#define CM_PCMCTL		0x098
8462306a36Sopenharmony_ci#define CM_PCMDIV		0x09c
8562306a36Sopenharmony_ci#define CM_PWMCTL		0x0a0
8662306a36Sopenharmony_ci#define CM_PWMDIV		0x0a4
8762306a36Sopenharmony_ci#define CM_SLIMCTL		0x0a8
8862306a36Sopenharmony_ci#define CM_SLIMDIV		0x0ac
8962306a36Sopenharmony_ci#define CM_SMICTL		0x0b0
9062306a36Sopenharmony_ci#define CM_SMIDIV		0x0b4
9162306a36Sopenharmony_ci/* no definition for 0x0b8  and 0x0bc */
9262306a36Sopenharmony_ci#define CM_TCNTCTL		0x0c0
9362306a36Sopenharmony_ci# define CM_TCNT_SRC1_SHIFT		12
9462306a36Sopenharmony_ci#define CM_TCNTCNT		0x0c4
9562306a36Sopenharmony_ci#define CM_TECCTL		0x0c8
9662306a36Sopenharmony_ci#define CM_TECDIV		0x0cc
9762306a36Sopenharmony_ci#define CM_TD0CTL		0x0d0
9862306a36Sopenharmony_ci#define CM_TD0DIV		0x0d4
9962306a36Sopenharmony_ci#define CM_TD1CTL		0x0d8
10062306a36Sopenharmony_ci#define CM_TD1DIV		0x0dc
10162306a36Sopenharmony_ci#define CM_TSENSCTL		0x0e0
10262306a36Sopenharmony_ci#define CM_TSENSDIV		0x0e4
10362306a36Sopenharmony_ci#define CM_TIMERCTL		0x0e8
10462306a36Sopenharmony_ci#define CM_TIMERDIV		0x0ec
10562306a36Sopenharmony_ci#define CM_UARTCTL		0x0f0
10662306a36Sopenharmony_ci#define CM_UARTDIV		0x0f4
10762306a36Sopenharmony_ci#define CM_VECCTL		0x0f8
10862306a36Sopenharmony_ci#define CM_VECDIV		0x0fc
10962306a36Sopenharmony_ci#define CM_PULSECTL		0x190
11062306a36Sopenharmony_ci#define CM_PULSEDIV		0x194
11162306a36Sopenharmony_ci#define CM_SDCCTL		0x1a8
11262306a36Sopenharmony_ci#define CM_SDCDIV		0x1ac
11362306a36Sopenharmony_ci#define CM_ARMCTL		0x1b0
11462306a36Sopenharmony_ci#define CM_AVEOCTL		0x1b8
11562306a36Sopenharmony_ci#define CM_AVEODIV		0x1bc
11662306a36Sopenharmony_ci#define CM_EMMCCTL		0x1c0
11762306a36Sopenharmony_ci#define CM_EMMCDIV		0x1c4
11862306a36Sopenharmony_ci#define CM_EMMC2CTL		0x1d0
11962306a36Sopenharmony_ci#define CM_EMMC2DIV		0x1d4
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci/* General bits for the CM_*CTL regs */
12262306a36Sopenharmony_ci# define CM_ENABLE			BIT(4)
12362306a36Sopenharmony_ci# define CM_KILL			BIT(5)
12462306a36Sopenharmony_ci# define CM_GATE_BIT			6
12562306a36Sopenharmony_ci# define CM_GATE			BIT(CM_GATE_BIT)
12662306a36Sopenharmony_ci# define CM_BUSY			BIT(7)
12762306a36Sopenharmony_ci# define CM_BUSYD			BIT(8)
12862306a36Sopenharmony_ci# define CM_FRAC			BIT(9)
12962306a36Sopenharmony_ci# define CM_SRC_SHIFT			0
13062306a36Sopenharmony_ci# define CM_SRC_BITS			4
13162306a36Sopenharmony_ci# define CM_SRC_MASK			0xf
13262306a36Sopenharmony_ci# define CM_SRC_GND			0
13362306a36Sopenharmony_ci# define CM_SRC_OSC			1
13462306a36Sopenharmony_ci# define CM_SRC_TESTDEBUG0		2
13562306a36Sopenharmony_ci# define CM_SRC_TESTDEBUG1		3
13662306a36Sopenharmony_ci# define CM_SRC_PLLA_CORE		4
13762306a36Sopenharmony_ci# define CM_SRC_PLLA_PER		4
13862306a36Sopenharmony_ci# define CM_SRC_PLLC_CORE0		5
13962306a36Sopenharmony_ci# define CM_SRC_PLLC_PER		5
14062306a36Sopenharmony_ci# define CM_SRC_PLLC_CORE1		8
14162306a36Sopenharmony_ci# define CM_SRC_PLLD_CORE		6
14262306a36Sopenharmony_ci# define CM_SRC_PLLD_PER		6
14362306a36Sopenharmony_ci# define CM_SRC_PLLH_AUX		7
14462306a36Sopenharmony_ci# define CM_SRC_PLLC_CORE1		8
14562306a36Sopenharmony_ci# define CM_SRC_PLLC_CORE2		9
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci#define CM_OSCCOUNT		0x100
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci#define CM_PLLA			0x104
15062306a36Sopenharmony_ci# define CM_PLL_ANARST			BIT(8)
15162306a36Sopenharmony_ci# define CM_PLLA_HOLDPER		BIT(7)
15262306a36Sopenharmony_ci# define CM_PLLA_LOADPER		BIT(6)
15362306a36Sopenharmony_ci# define CM_PLLA_HOLDCORE		BIT(5)
15462306a36Sopenharmony_ci# define CM_PLLA_LOADCORE		BIT(4)
15562306a36Sopenharmony_ci# define CM_PLLA_HOLDCCP2		BIT(3)
15662306a36Sopenharmony_ci# define CM_PLLA_LOADCCP2		BIT(2)
15762306a36Sopenharmony_ci# define CM_PLLA_HOLDDSI0		BIT(1)
15862306a36Sopenharmony_ci# define CM_PLLA_LOADDSI0		BIT(0)
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci#define CM_PLLC			0x108
16162306a36Sopenharmony_ci# define CM_PLLC_HOLDPER		BIT(7)
16262306a36Sopenharmony_ci# define CM_PLLC_LOADPER		BIT(6)
16362306a36Sopenharmony_ci# define CM_PLLC_HOLDCORE2		BIT(5)
16462306a36Sopenharmony_ci# define CM_PLLC_LOADCORE2		BIT(4)
16562306a36Sopenharmony_ci# define CM_PLLC_HOLDCORE1		BIT(3)
16662306a36Sopenharmony_ci# define CM_PLLC_LOADCORE1		BIT(2)
16762306a36Sopenharmony_ci# define CM_PLLC_HOLDCORE0		BIT(1)
16862306a36Sopenharmony_ci# define CM_PLLC_LOADCORE0		BIT(0)
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci#define CM_PLLD			0x10c
17162306a36Sopenharmony_ci# define CM_PLLD_HOLDPER		BIT(7)
17262306a36Sopenharmony_ci# define CM_PLLD_LOADPER		BIT(6)
17362306a36Sopenharmony_ci# define CM_PLLD_HOLDCORE		BIT(5)
17462306a36Sopenharmony_ci# define CM_PLLD_LOADCORE		BIT(4)
17562306a36Sopenharmony_ci# define CM_PLLD_HOLDDSI1		BIT(3)
17662306a36Sopenharmony_ci# define CM_PLLD_LOADDSI1		BIT(2)
17762306a36Sopenharmony_ci# define CM_PLLD_HOLDDSI0		BIT(1)
17862306a36Sopenharmony_ci# define CM_PLLD_LOADDSI0		BIT(0)
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci#define CM_PLLH			0x110
18162306a36Sopenharmony_ci# define CM_PLLH_LOADRCAL		BIT(2)
18262306a36Sopenharmony_ci# define CM_PLLH_LOADAUX		BIT(1)
18362306a36Sopenharmony_ci# define CM_PLLH_LOADPIX		BIT(0)
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci#define CM_LOCK			0x114
18662306a36Sopenharmony_ci# define CM_LOCK_FLOCKH			BIT(12)
18762306a36Sopenharmony_ci# define CM_LOCK_FLOCKD			BIT(11)
18862306a36Sopenharmony_ci# define CM_LOCK_FLOCKC			BIT(10)
18962306a36Sopenharmony_ci# define CM_LOCK_FLOCKB			BIT(9)
19062306a36Sopenharmony_ci# define CM_LOCK_FLOCKA			BIT(8)
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci#define CM_EVENT		0x118
19362306a36Sopenharmony_ci#define CM_DSI1ECTL		0x158
19462306a36Sopenharmony_ci#define CM_DSI1EDIV		0x15c
19562306a36Sopenharmony_ci#define CM_DSI1PCTL		0x160
19662306a36Sopenharmony_ci#define CM_DSI1PDIV		0x164
19762306a36Sopenharmony_ci#define CM_DFTCTL		0x168
19862306a36Sopenharmony_ci#define CM_DFTDIV		0x16c
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci#define CM_PLLB			0x170
20162306a36Sopenharmony_ci# define CM_PLLB_HOLDARM		BIT(1)
20262306a36Sopenharmony_ci# define CM_PLLB_LOADARM		BIT(0)
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci#define A2W_PLLA_CTRL		0x1100
20562306a36Sopenharmony_ci#define A2W_PLLC_CTRL		0x1120
20662306a36Sopenharmony_ci#define A2W_PLLD_CTRL		0x1140
20762306a36Sopenharmony_ci#define A2W_PLLH_CTRL		0x1160
20862306a36Sopenharmony_ci#define A2W_PLLB_CTRL		0x11e0
20962306a36Sopenharmony_ci# define A2W_PLL_CTRL_PRST_DISABLE	BIT(17)
21062306a36Sopenharmony_ci# define A2W_PLL_CTRL_PWRDN		BIT(16)
21162306a36Sopenharmony_ci# define A2W_PLL_CTRL_PDIV_MASK		0x000007000
21262306a36Sopenharmony_ci# define A2W_PLL_CTRL_PDIV_SHIFT	12
21362306a36Sopenharmony_ci# define A2W_PLL_CTRL_NDIV_MASK		0x0000003ff
21462306a36Sopenharmony_ci# define A2W_PLL_CTRL_NDIV_SHIFT	0
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci#define A2W_PLLA_ANA0		0x1010
21762306a36Sopenharmony_ci#define A2W_PLLC_ANA0		0x1030
21862306a36Sopenharmony_ci#define A2W_PLLD_ANA0		0x1050
21962306a36Sopenharmony_ci#define A2W_PLLH_ANA0		0x1070
22062306a36Sopenharmony_ci#define A2W_PLLB_ANA0		0x10f0
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci#define A2W_PLL_KA_SHIFT	7
22362306a36Sopenharmony_ci#define A2W_PLL_KA_MASK		GENMASK(9, 7)
22462306a36Sopenharmony_ci#define A2W_PLL_KI_SHIFT	19
22562306a36Sopenharmony_ci#define A2W_PLL_KI_MASK		GENMASK(21, 19)
22662306a36Sopenharmony_ci#define A2W_PLL_KP_SHIFT	15
22762306a36Sopenharmony_ci#define A2W_PLL_KP_MASK		GENMASK(18, 15)
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci#define A2W_PLLH_KA_SHIFT	19
23062306a36Sopenharmony_ci#define A2W_PLLH_KA_MASK	GENMASK(21, 19)
23162306a36Sopenharmony_ci#define A2W_PLLH_KI_LOW_SHIFT	22
23262306a36Sopenharmony_ci#define A2W_PLLH_KI_LOW_MASK	GENMASK(23, 22)
23362306a36Sopenharmony_ci#define A2W_PLLH_KI_HIGH_SHIFT	0
23462306a36Sopenharmony_ci#define A2W_PLLH_KI_HIGH_MASK	GENMASK(0, 0)
23562306a36Sopenharmony_ci#define A2W_PLLH_KP_SHIFT	1
23662306a36Sopenharmony_ci#define A2W_PLLH_KP_MASK	GENMASK(4, 1)
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci#define A2W_XOSC_CTRL		0x1190
23962306a36Sopenharmony_ci# define A2W_XOSC_CTRL_PLLB_ENABLE	BIT(7)
24062306a36Sopenharmony_ci# define A2W_XOSC_CTRL_PLLA_ENABLE	BIT(6)
24162306a36Sopenharmony_ci# define A2W_XOSC_CTRL_PLLD_ENABLE	BIT(5)
24262306a36Sopenharmony_ci# define A2W_XOSC_CTRL_DDR_ENABLE	BIT(4)
24362306a36Sopenharmony_ci# define A2W_XOSC_CTRL_CPR1_ENABLE	BIT(3)
24462306a36Sopenharmony_ci# define A2W_XOSC_CTRL_USB_ENABLE	BIT(2)
24562306a36Sopenharmony_ci# define A2W_XOSC_CTRL_HDMI_ENABLE	BIT(1)
24662306a36Sopenharmony_ci# define A2W_XOSC_CTRL_PLLC_ENABLE	BIT(0)
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci#define A2W_PLLA_FRAC		0x1200
24962306a36Sopenharmony_ci#define A2W_PLLC_FRAC		0x1220
25062306a36Sopenharmony_ci#define A2W_PLLD_FRAC		0x1240
25162306a36Sopenharmony_ci#define A2W_PLLH_FRAC		0x1260
25262306a36Sopenharmony_ci#define A2W_PLLB_FRAC		0x12e0
25362306a36Sopenharmony_ci# define A2W_PLL_FRAC_MASK		((1 << A2W_PLL_FRAC_BITS) - 1)
25462306a36Sopenharmony_ci# define A2W_PLL_FRAC_BITS		20
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci#define A2W_PLL_CHANNEL_DISABLE		BIT(8)
25762306a36Sopenharmony_ci#define A2W_PLL_DIV_BITS		8
25862306a36Sopenharmony_ci#define A2W_PLL_DIV_SHIFT		0
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci#define A2W_PLLA_DSI0		0x1300
26162306a36Sopenharmony_ci#define A2W_PLLA_CORE		0x1400
26262306a36Sopenharmony_ci#define A2W_PLLA_PER		0x1500
26362306a36Sopenharmony_ci#define A2W_PLLA_CCP2		0x1600
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci#define A2W_PLLC_CORE2		0x1320
26662306a36Sopenharmony_ci#define A2W_PLLC_CORE1		0x1420
26762306a36Sopenharmony_ci#define A2W_PLLC_PER		0x1520
26862306a36Sopenharmony_ci#define A2W_PLLC_CORE0		0x1620
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci#define A2W_PLLD_DSI0		0x1340
27162306a36Sopenharmony_ci#define A2W_PLLD_CORE		0x1440
27262306a36Sopenharmony_ci#define A2W_PLLD_PER		0x1540
27362306a36Sopenharmony_ci#define A2W_PLLD_DSI1		0x1640
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci#define A2W_PLLH_AUX		0x1360
27662306a36Sopenharmony_ci#define A2W_PLLH_RCAL		0x1460
27762306a36Sopenharmony_ci#define A2W_PLLH_PIX		0x1560
27862306a36Sopenharmony_ci#define A2W_PLLH_STS		0x1660
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci#define A2W_PLLH_CTRLR		0x1960
28162306a36Sopenharmony_ci#define A2W_PLLH_FRACR		0x1a60
28262306a36Sopenharmony_ci#define A2W_PLLH_AUXR		0x1b60
28362306a36Sopenharmony_ci#define A2W_PLLH_RCALR		0x1c60
28462306a36Sopenharmony_ci#define A2W_PLLH_PIXR		0x1d60
28562306a36Sopenharmony_ci#define A2W_PLLH_STSR		0x1e60
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci#define A2W_PLLB_ARM		0x13e0
28862306a36Sopenharmony_ci#define A2W_PLLB_SP0		0x14e0
28962306a36Sopenharmony_ci#define A2W_PLLB_SP1		0x15e0
29062306a36Sopenharmony_ci#define A2W_PLLB_SP2		0x16e0
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci#define LOCK_TIMEOUT_NS		100000000
29362306a36Sopenharmony_ci#define BCM2835_MAX_FB_RATE	1750000000u
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci#define SOC_BCM2835		BIT(0)
29662306a36Sopenharmony_ci#define SOC_BCM2711		BIT(1)
29762306a36Sopenharmony_ci#define SOC_ALL			(SOC_BCM2835 | SOC_BCM2711)
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci/*
30062306a36Sopenharmony_ci * Names of clocks used within the driver that need to be replaced
30162306a36Sopenharmony_ci * with an external parent's name.  This array is in the order that
30262306a36Sopenharmony_ci * the clocks node in the DT references external clocks.
30362306a36Sopenharmony_ci */
30462306a36Sopenharmony_cistatic const char *const cprman_parent_names[] = {
30562306a36Sopenharmony_ci	"xosc",
30662306a36Sopenharmony_ci	"dsi0_byte",
30762306a36Sopenharmony_ci	"dsi0_ddr2",
30862306a36Sopenharmony_ci	"dsi0_ddr",
30962306a36Sopenharmony_ci	"dsi1_byte",
31062306a36Sopenharmony_ci	"dsi1_ddr2",
31162306a36Sopenharmony_ci	"dsi1_ddr",
31262306a36Sopenharmony_ci};
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_cistruct bcm2835_cprman {
31562306a36Sopenharmony_ci	struct device *dev;
31662306a36Sopenharmony_ci	void __iomem *regs;
31762306a36Sopenharmony_ci	spinlock_t regs_lock; /* spinlock for all clocks */
31862306a36Sopenharmony_ci	unsigned int soc;
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	/*
32162306a36Sopenharmony_ci	 * Real names of cprman clock parents looked up through
32262306a36Sopenharmony_ci	 * of_clk_get_parent_name(), which will be used in the
32362306a36Sopenharmony_ci	 * parent_names[] arrays for clock registration.
32462306a36Sopenharmony_ci	 */
32562306a36Sopenharmony_ci	const char *real_parent_names[ARRAY_SIZE(cprman_parent_names)];
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	/* Must be last */
32862306a36Sopenharmony_ci	struct clk_hw_onecell_data onecell;
32962306a36Sopenharmony_ci};
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_cistruct cprman_plat_data {
33262306a36Sopenharmony_ci	unsigned int soc;
33362306a36Sopenharmony_ci};
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_cistatic inline void cprman_write(struct bcm2835_cprman *cprman, u32 reg, u32 val)
33662306a36Sopenharmony_ci{
33762306a36Sopenharmony_ci	writel(CM_PASSWORD | val, cprman->regs + reg);
33862306a36Sopenharmony_ci}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_cistatic inline u32 cprman_read(struct bcm2835_cprman *cprman, u32 reg)
34162306a36Sopenharmony_ci{
34262306a36Sopenharmony_ci	return readl(cprman->regs + reg);
34362306a36Sopenharmony_ci}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci/* Does a cycle of measuring a clock through the TCNT clock, which may
34662306a36Sopenharmony_ci * source from many other clocks in the system.
34762306a36Sopenharmony_ci */
34862306a36Sopenharmony_cistatic unsigned long bcm2835_measure_tcnt_mux(struct bcm2835_cprman *cprman,
34962306a36Sopenharmony_ci					      u32 tcnt_mux)
35062306a36Sopenharmony_ci{
35162306a36Sopenharmony_ci	u32 osccount = 19200; /* 1ms */
35262306a36Sopenharmony_ci	u32 count;
35362306a36Sopenharmony_ci	ktime_t timeout;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	spin_lock(&cprman->regs_lock);
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	cprman_write(cprman, CM_TCNTCTL, CM_KILL);
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	cprman_write(cprman, CM_TCNTCTL,
36062306a36Sopenharmony_ci		     (tcnt_mux & CM_SRC_MASK) |
36162306a36Sopenharmony_ci		     (tcnt_mux >> CM_SRC_BITS) << CM_TCNT_SRC1_SHIFT);
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	cprman_write(cprman, CM_OSCCOUNT, osccount);
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	/* do a kind delay at the start */
36662306a36Sopenharmony_ci	mdelay(1);
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	/* Finish off whatever is left of OSCCOUNT */
36962306a36Sopenharmony_ci	timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
37062306a36Sopenharmony_ci	while (cprman_read(cprman, CM_OSCCOUNT)) {
37162306a36Sopenharmony_ci		if (ktime_after(ktime_get(), timeout)) {
37262306a36Sopenharmony_ci			dev_err(cprman->dev, "timeout waiting for OSCCOUNT\n");
37362306a36Sopenharmony_ci			count = 0;
37462306a36Sopenharmony_ci			goto out;
37562306a36Sopenharmony_ci		}
37662306a36Sopenharmony_ci		cpu_relax();
37762306a36Sopenharmony_ci	}
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	/* Wait for BUSY to clear. */
38062306a36Sopenharmony_ci	timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
38162306a36Sopenharmony_ci	while (cprman_read(cprman, CM_TCNTCTL) & CM_BUSY) {
38262306a36Sopenharmony_ci		if (ktime_after(ktime_get(), timeout)) {
38362306a36Sopenharmony_ci			dev_err(cprman->dev, "timeout waiting for !BUSY\n");
38462306a36Sopenharmony_ci			count = 0;
38562306a36Sopenharmony_ci			goto out;
38662306a36Sopenharmony_ci		}
38762306a36Sopenharmony_ci		cpu_relax();
38862306a36Sopenharmony_ci	}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	count = cprman_read(cprman, CM_TCNTCNT);
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	cprman_write(cprman, CM_TCNTCTL, 0);
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ciout:
39562306a36Sopenharmony_ci	spin_unlock(&cprman->regs_lock);
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	return count * 1000;
39862306a36Sopenharmony_ci}
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_cistatic void bcm2835_debugfs_regset(struct bcm2835_cprman *cprman, u32 base,
40162306a36Sopenharmony_ci				   const struct debugfs_reg32 *regs,
40262306a36Sopenharmony_ci				   size_t nregs, struct dentry *dentry)
40362306a36Sopenharmony_ci{
40462306a36Sopenharmony_ci	struct debugfs_regset32 *regset;
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	regset = devm_kzalloc(cprman->dev, sizeof(*regset), GFP_KERNEL);
40762306a36Sopenharmony_ci	if (!regset)
40862306a36Sopenharmony_ci		return;
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	regset->regs = regs;
41162306a36Sopenharmony_ci	regset->nregs = nregs;
41262306a36Sopenharmony_ci	regset->base = cprman->regs + base;
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	debugfs_create_regset32("regdump", S_IRUGO, dentry, regset);
41562306a36Sopenharmony_ci}
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_cistruct bcm2835_pll_data {
41862306a36Sopenharmony_ci	const char *name;
41962306a36Sopenharmony_ci	u32 cm_ctrl_reg;
42062306a36Sopenharmony_ci	u32 a2w_ctrl_reg;
42162306a36Sopenharmony_ci	u32 frac_reg;
42262306a36Sopenharmony_ci	u32 ana_reg_base;
42362306a36Sopenharmony_ci	u32 reference_enable_mask;
42462306a36Sopenharmony_ci	/* Bit in CM_LOCK to indicate when the PLL has locked. */
42562306a36Sopenharmony_ci	u32 lock_mask;
42662306a36Sopenharmony_ci	u32 flags;
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	const struct bcm2835_pll_ana_bits *ana;
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	unsigned long min_rate;
43162306a36Sopenharmony_ci	unsigned long max_rate;
43262306a36Sopenharmony_ci	/*
43362306a36Sopenharmony_ci	 * Highest rate for the VCO before we have to use the
43462306a36Sopenharmony_ci	 * pre-divide-by-2.
43562306a36Sopenharmony_ci	 */
43662306a36Sopenharmony_ci	unsigned long max_fb_rate;
43762306a36Sopenharmony_ci};
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_cistruct bcm2835_pll_ana_bits {
44062306a36Sopenharmony_ci	u32 mask0;
44162306a36Sopenharmony_ci	u32 set0;
44262306a36Sopenharmony_ci	u32 mask1;
44362306a36Sopenharmony_ci	u32 set1;
44462306a36Sopenharmony_ci	u32 mask3;
44562306a36Sopenharmony_ci	u32 set3;
44662306a36Sopenharmony_ci	u32 fb_prediv_mask;
44762306a36Sopenharmony_ci};
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_cistatic const struct bcm2835_pll_ana_bits bcm2835_ana_default = {
45062306a36Sopenharmony_ci	.mask0 = 0,
45162306a36Sopenharmony_ci	.set0 = 0,
45262306a36Sopenharmony_ci	.mask1 = A2W_PLL_KI_MASK | A2W_PLL_KP_MASK,
45362306a36Sopenharmony_ci	.set1 = (2 << A2W_PLL_KI_SHIFT) | (8 << A2W_PLL_KP_SHIFT),
45462306a36Sopenharmony_ci	.mask3 = A2W_PLL_KA_MASK,
45562306a36Sopenharmony_ci	.set3 = (2 << A2W_PLL_KA_SHIFT),
45662306a36Sopenharmony_ci	.fb_prediv_mask = BIT(14),
45762306a36Sopenharmony_ci};
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_cistatic const struct bcm2835_pll_ana_bits bcm2835_ana_pllh = {
46062306a36Sopenharmony_ci	.mask0 = A2W_PLLH_KA_MASK | A2W_PLLH_KI_LOW_MASK,
46162306a36Sopenharmony_ci	.set0 = (2 << A2W_PLLH_KA_SHIFT) | (2 << A2W_PLLH_KI_LOW_SHIFT),
46262306a36Sopenharmony_ci	.mask1 = A2W_PLLH_KI_HIGH_MASK | A2W_PLLH_KP_MASK,
46362306a36Sopenharmony_ci	.set1 = (6 << A2W_PLLH_KP_SHIFT),
46462306a36Sopenharmony_ci	.mask3 = 0,
46562306a36Sopenharmony_ci	.set3 = 0,
46662306a36Sopenharmony_ci	.fb_prediv_mask = BIT(11),
46762306a36Sopenharmony_ci};
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_cistruct bcm2835_pll_divider_data {
47062306a36Sopenharmony_ci	const char *name;
47162306a36Sopenharmony_ci	const char *source_pll;
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	u32 cm_reg;
47462306a36Sopenharmony_ci	u32 a2w_reg;
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	u32 load_mask;
47762306a36Sopenharmony_ci	u32 hold_mask;
47862306a36Sopenharmony_ci	u32 fixed_divider;
47962306a36Sopenharmony_ci	u32 flags;
48062306a36Sopenharmony_ci};
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_cistruct bcm2835_clock_data {
48362306a36Sopenharmony_ci	const char *name;
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	const char *const *parents;
48662306a36Sopenharmony_ci	int num_mux_parents;
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci	/* Bitmap encoding which parents accept rate change propagation. */
48962306a36Sopenharmony_ci	unsigned int set_rate_parent;
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	u32 ctl_reg;
49262306a36Sopenharmony_ci	u32 div_reg;
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	/* Number of integer bits in the divider */
49562306a36Sopenharmony_ci	u32 int_bits;
49662306a36Sopenharmony_ci	/* Number of fractional bits in the divider */
49762306a36Sopenharmony_ci	u32 frac_bits;
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	u32 flags;
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	bool is_vpu_clock;
50262306a36Sopenharmony_ci	bool is_mash_clock;
50362306a36Sopenharmony_ci	bool low_jitter;
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	u32 tcnt_mux;
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	bool round_up;
50862306a36Sopenharmony_ci};
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_cistruct bcm2835_gate_data {
51162306a36Sopenharmony_ci	const char *name;
51262306a36Sopenharmony_ci	const char *parent;
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	u32 ctl_reg;
51562306a36Sopenharmony_ci};
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_cistruct bcm2835_pll {
51862306a36Sopenharmony_ci	struct clk_hw hw;
51962306a36Sopenharmony_ci	struct bcm2835_cprman *cprman;
52062306a36Sopenharmony_ci	const struct bcm2835_pll_data *data;
52162306a36Sopenharmony_ci};
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_cistatic int bcm2835_pll_is_on(struct clk_hw *hw)
52462306a36Sopenharmony_ci{
52562306a36Sopenharmony_ci	struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
52662306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = pll->cprman;
52762306a36Sopenharmony_ci	const struct bcm2835_pll_data *data = pll->data;
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	return cprman_read(cprman, data->a2w_ctrl_reg) &
53062306a36Sopenharmony_ci		A2W_PLL_CTRL_PRST_DISABLE;
53162306a36Sopenharmony_ci}
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_cistatic u32 bcm2835_pll_get_prediv_mask(struct bcm2835_cprman *cprman,
53462306a36Sopenharmony_ci				       const struct bcm2835_pll_data *data)
53562306a36Sopenharmony_ci{
53662306a36Sopenharmony_ci	/*
53762306a36Sopenharmony_ci	 * On BCM2711 there isn't a pre-divisor available in the PLL feedback
53862306a36Sopenharmony_ci	 * loop. Bits 13:14 of ANA1 (PLLA,PLLB,PLLC,PLLD) have been re-purposed
53962306a36Sopenharmony_ci	 * for to for VCO RANGE bits.
54062306a36Sopenharmony_ci	 */
54162306a36Sopenharmony_ci	if (cprman->soc & SOC_BCM2711)
54262306a36Sopenharmony_ci		return 0;
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci	return data->ana->fb_prediv_mask;
54562306a36Sopenharmony_ci}
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_cistatic void bcm2835_pll_choose_ndiv_and_fdiv(unsigned long rate,
54862306a36Sopenharmony_ci					     unsigned long parent_rate,
54962306a36Sopenharmony_ci					     u32 *ndiv, u32 *fdiv)
55062306a36Sopenharmony_ci{
55162306a36Sopenharmony_ci	u64 div;
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	div = (u64)rate << A2W_PLL_FRAC_BITS;
55462306a36Sopenharmony_ci	do_div(div, parent_rate);
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	*ndiv = div >> A2W_PLL_FRAC_BITS;
55762306a36Sopenharmony_ci	*fdiv = div & ((1 << A2W_PLL_FRAC_BITS) - 1);
55862306a36Sopenharmony_ci}
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_cistatic long bcm2835_pll_rate_from_divisors(unsigned long parent_rate,
56162306a36Sopenharmony_ci					   u32 ndiv, u32 fdiv, u32 pdiv)
56262306a36Sopenharmony_ci{
56362306a36Sopenharmony_ci	u64 rate;
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	if (pdiv == 0)
56662306a36Sopenharmony_ci		return 0;
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	rate = (u64)parent_rate * ((ndiv << A2W_PLL_FRAC_BITS) + fdiv);
56962306a36Sopenharmony_ci	do_div(rate, pdiv);
57062306a36Sopenharmony_ci	return rate >> A2W_PLL_FRAC_BITS;
57162306a36Sopenharmony_ci}
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_cistatic long bcm2835_pll_round_rate(struct clk_hw *hw, unsigned long rate,
57462306a36Sopenharmony_ci				   unsigned long *parent_rate)
57562306a36Sopenharmony_ci{
57662306a36Sopenharmony_ci	struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
57762306a36Sopenharmony_ci	const struct bcm2835_pll_data *data = pll->data;
57862306a36Sopenharmony_ci	u32 ndiv, fdiv;
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci	rate = clamp(rate, data->min_rate, data->max_rate);
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	bcm2835_pll_choose_ndiv_and_fdiv(rate, *parent_rate, &ndiv, &fdiv);
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	return bcm2835_pll_rate_from_divisors(*parent_rate, ndiv, fdiv, 1);
58562306a36Sopenharmony_ci}
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_cistatic unsigned long bcm2835_pll_get_rate(struct clk_hw *hw,
58862306a36Sopenharmony_ci					  unsigned long parent_rate)
58962306a36Sopenharmony_ci{
59062306a36Sopenharmony_ci	struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
59162306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = pll->cprman;
59262306a36Sopenharmony_ci	const struct bcm2835_pll_data *data = pll->data;
59362306a36Sopenharmony_ci	u32 a2wctrl = cprman_read(cprman, data->a2w_ctrl_reg);
59462306a36Sopenharmony_ci	u32 ndiv, pdiv, fdiv;
59562306a36Sopenharmony_ci	bool using_prediv;
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	if (parent_rate == 0)
59862306a36Sopenharmony_ci		return 0;
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	fdiv = cprman_read(cprman, data->frac_reg) & A2W_PLL_FRAC_MASK;
60162306a36Sopenharmony_ci	ndiv = (a2wctrl & A2W_PLL_CTRL_NDIV_MASK) >> A2W_PLL_CTRL_NDIV_SHIFT;
60262306a36Sopenharmony_ci	pdiv = (a2wctrl & A2W_PLL_CTRL_PDIV_MASK) >> A2W_PLL_CTRL_PDIV_SHIFT;
60362306a36Sopenharmony_ci	using_prediv = cprman_read(cprman, data->ana_reg_base + 4) &
60462306a36Sopenharmony_ci		       bcm2835_pll_get_prediv_mask(cprman, data);
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci	if (using_prediv) {
60762306a36Sopenharmony_ci		ndiv *= 2;
60862306a36Sopenharmony_ci		fdiv *= 2;
60962306a36Sopenharmony_ci	}
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci	return bcm2835_pll_rate_from_divisors(parent_rate, ndiv, fdiv, pdiv);
61262306a36Sopenharmony_ci}
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_cistatic void bcm2835_pll_off(struct clk_hw *hw)
61562306a36Sopenharmony_ci{
61662306a36Sopenharmony_ci	struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
61762306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = pll->cprman;
61862306a36Sopenharmony_ci	const struct bcm2835_pll_data *data = pll->data;
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	spin_lock(&cprman->regs_lock);
62162306a36Sopenharmony_ci	cprman_write(cprman, data->cm_ctrl_reg, CM_PLL_ANARST);
62262306a36Sopenharmony_ci	cprman_write(cprman, data->a2w_ctrl_reg,
62362306a36Sopenharmony_ci		     cprman_read(cprman, data->a2w_ctrl_reg) |
62462306a36Sopenharmony_ci		     A2W_PLL_CTRL_PWRDN);
62562306a36Sopenharmony_ci	spin_unlock(&cprman->regs_lock);
62662306a36Sopenharmony_ci}
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_cistatic int bcm2835_pll_on(struct clk_hw *hw)
62962306a36Sopenharmony_ci{
63062306a36Sopenharmony_ci	struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
63162306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = pll->cprman;
63262306a36Sopenharmony_ci	const struct bcm2835_pll_data *data = pll->data;
63362306a36Sopenharmony_ci	ktime_t timeout;
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci	cprman_write(cprman, data->a2w_ctrl_reg,
63662306a36Sopenharmony_ci		     cprman_read(cprman, data->a2w_ctrl_reg) &
63762306a36Sopenharmony_ci		     ~A2W_PLL_CTRL_PWRDN);
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci	/* Take the PLL out of reset. */
64062306a36Sopenharmony_ci	spin_lock(&cprman->regs_lock);
64162306a36Sopenharmony_ci	cprman_write(cprman, data->cm_ctrl_reg,
64262306a36Sopenharmony_ci		     cprman_read(cprman, data->cm_ctrl_reg) & ~CM_PLL_ANARST);
64362306a36Sopenharmony_ci	spin_unlock(&cprman->regs_lock);
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	/* Wait for the PLL to lock. */
64662306a36Sopenharmony_ci	timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
64762306a36Sopenharmony_ci	while (!(cprman_read(cprman, CM_LOCK) & data->lock_mask)) {
64862306a36Sopenharmony_ci		if (ktime_after(ktime_get(), timeout)) {
64962306a36Sopenharmony_ci			dev_err(cprman->dev, "%s: couldn't lock PLL\n",
65062306a36Sopenharmony_ci				clk_hw_get_name(hw));
65162306a36Sopenharmony_ci			return -ETIMEDOUT;
65262306a36Sopenharmony_ci		}
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci		cpu_relax();
65562306a36Sopenharmony_ci	}
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	cprman_write(cprman, data->a2w_ctrl_reg,
65862306a36Sopenharmony_ci		     cprman_read(cprman, data->a2w_ctrl_reg) |
65962306a36Sopenharmony_ci		     A2W_PLL_CTRL_PRST_DISABLE);
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	return 0;
66262306a36Sopenharmony_ci}
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_cistatic void
66562306a36Sopenharmony_cibcm2835_pll_write_ana(struct bcm2835_cprman *cprman, u32 ana_reg_base, u32 *ana)
66662306a36Sopenharmony_ci{
66762306a36Sopenharmony_ci	int i;
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	/*
67062306a36Sopenharmony_ci	 * ANA register setup is done as a series of writes to
67162306a36Sopenharmony_ci	 * ANA3-ANA0, in that order.  This lets us write all 4
67262306a36Sopenharmony_ci	 * registers as a single cycle of the serdes interface (taking
67362306a36Sopenharmony_ci	 * 100 xosc clocks), whereas if we were to update ana0, 1, and
67462306a36Sopenharmony_ci	 * 3 individually through their partial-write registers, each
67562306a36Sopenharmony_ci	 * would be their own serdes cycle.
67662306a36Sopenharmony_ci	 */
67762306a36Sopenharmony_ci	for (i = 3; i >= 0; i--)
67862306a36Sopenharmony_ci		cprman_write(cprman, ana_reg_base + i * 4, ana[i]);
67962306a36Sopenharmony_ci}
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_cistatic int bcm2835_pll_set_rate(struct clk_hw *hw,
68262306a36Sopenharmony_ci				unsigned long rate, unsigned long parent_rate)
68362306a36Sopenharmony_ci{
68462306a36Sopenharmony_ci	struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
68562306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = pll->cprman;
68662306a36Sopenharmony_ci	const struct bcm2835_pll_data *data = pll->data;
68762306a36Sopenharmony_ci	u32 prediv_mask = bcm2835_pll_get_prediv_mask(cprman, data);
68862306a36Sopenharmony_ci	bool was_using_prediv, use_fb_prediv, do_ana_setup_first;
68962306a36Sopenharmony_ci	u32 ndiv, fdiv, a2w_ctl;
69062306a36Sopenharmony_ci	u32 ana[4];
69162306a36Sopenharmony_ci	int i;
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	if (rate > data->max_fb_rate) {
69462306a36Sopenharmony_ci		use_fb_prediv = true;
69562306a36Sopenharmony_ci		rate /= 2;
69662306a36Sopenharmony_ci	} else {
69762306a36Sopenharmony_ci		use_fb_prediv = false;
69862306a36Sopenharmony_ci	}
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci	bcm2835_pll_choose_ndiv_and_fdiv(rate, parent_rate, &ndiv, &fdiv);
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci	for (i = 3; i >= 0; i--)
70362306a36Sopenharmony_ci		ana[i] = cprman_read(cprman, data->ana_reg_base + i * 4);
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_ci	was_using_prediv = ana[1] & prediv_mask;
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci	ana[0] &= ~data->ana->mask0;
70862306a36Sopenharmony_ci	ana[0] |= data->ana->set0;
70962306a36Sopenharmony_ci	ana[1] &= ~data->ana->mask1;
71062306a36Sopenharmony_ci	ana[1] |= data->ana->set1;
71162306a36Sopenharmony_ci	ana[3] &= ~data->ana->mask3;
71262306a36Sopenharmony_ci	ana[3] |= data->ana->set3;
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ci	if (was_using_prediv && !use_fb_prediv) {
71562306a36Sopenharmony_ci		ana[1] &= ~prediv_mask;
71662306a36Sopenharmony_ci		do_ana_setup_first = true;
71762306a36Sopenharmony_ci	} else if (!was_using_prediv && use_fb_prediv) {
71862306a36Sopenharmony_ci		ana[1] |= prediv_mask;
71962306a36Sopenharmony_ci		do_ana_setup_first = false;
72062306a36Sopenharmony_ci	} else {
72162306a36Sopenharmony_ci		do_ana_setup_first = true;
72262306a36Sopenharmony_ci	}
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci	/* Unmask the reference clock from the oscillator. */
72562306a36Sopenharmony_ci	spin_lock(&cprman->regs_lock);
72662306a36Sopenharmony_ci	cprman_write(cprman, A2W_XOSC_CTRL,
72762306a36Sopenharmony_ci		     cprman_read(cprman, A2W_XOSC_CTRL) |
72862306a36Sopenharmony_ci		     data->reference_enable_mask);
72962306a36Sopenharmony_ci	spin_unlock(&cprman->regs_lock);
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	if (do_ana_setup_first)
73262306a36Sopenharmony_ci		bcm2835_pll_write_ana(cprman, data->ana_reg_base, ana);
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci	/* Set the PLL multiplier from the oscillator. */
73562306a36Sopenharmony_ci	cprman_write(cprman, data->frac_reg, fdiv);
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci	a2w_ctl = cprman_read(cprman, data->a2w_ctrl_reg);
73862306a36Sopenharmony_ci	a2w_ctl &= ~A2W_PLL_CTRL_NDIV_MASK;
73962306a36Sopenharmony_ci	a2w_ctl |= ndiv << A2W_PLL_CTRL_NDIV_SHIFT;
74062306a36Sopenharmony_ci	a2w_ctl &= ~A2W_PLL_CTRL_PDIV_MASK;
74162306a36Sopenharmony_ci	a2w_ctl |= 1 << A2W_PLL_CTRL_PDIV_SHIFT;
74262306a36Sopenharmony_ci	cprman_write(cprman, data->a2w_ctrl_reg, a2w_ctl);
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci	if (!do_ana_setup_first)
74562306a36Sopenharmony_ci		bcm2835_pll_write_ana(cprman, data->ana_reg_base, ana);
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_ci	return 0;
74862306a36Sopenharmony_ci}
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_cistatic void bcm2835_pll_debug_init(struct clk_hw *hw,
75162306a36Sopenharmony_ci				  struct dentry *dentry)
75262306a36Sopenharmony_ci{
75362306a36Sopenharmony_ci	struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
75462306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = pll->cprman;
75562306a36Sopenharmony_ci	const struct bcm2835_pll_data *data = pll->data;
75662306a36Sopenharmony_ci	struct debugfs_reg32 *regs;
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_ci	regs = devm_kcalloc(cprman->dev, 7, sizeof(*regs), GFP_KERNEL);
75962306a36Sopenharmony_ci	if (!regs)
76062306a36Sopenharmony_ci		return;
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci	regs[0].name = "cm_ctrl";
76362306a36Sopenharmony_ci	regs[0].offset = data->cm_ctrl_reg;
76462306a36Sopenharmony_ci	regs[1].name = "a2w_ctrl";
76562306a36Sopenharmony_ci	regs[1].offset = data->a2w_ctrl_reg;
76662306a36Sopenharmony_ci	regs[2].name = "frac";
76762306a36Sopenharmony_ci	regs[2].offset = data->frac_reg;
76862306a36Sopenharmony_ci	regs[3].name = "ana0";
76962306a36Sopenharmony_ci	regs[3].offset = data->ana_reg_base + 0 * 4;
77062306a36Sopenharmony_ci	regs[4].name = "ana1";
77162306a36Sopenharmony_ci	regs[4].offset = data->ana_reg_base + 1 * 4;
77262306a36Sopenharmony_ci	regs[5].name = "ana2";
77362306a36Sopenharmony_ci	regs[5].offset = data->ana_reg_base + 2 * 4;
77462306a36Sopenharmony_ci	regs[6].name = "ana3";
77562306a36Sopenharmony_ci	regs[6].offset = data->ana_reg_base + 3 * 4;
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci	bcm2835_debugfs_regset(cprman, 0, regs, 7, dentry);
77862306a36Sopenharmony_ci}
77962306a36Sopenharmony_ci
78062306a36Sopenharmony_cistatic const struct clk_ops bcm2835_pll_clk_ops = {
78162306a36Sopenharmony_ci	.is_prepared = bcm2835_pll_is_on,
78262306a36Sopenharmony_ci	.prepare = bcm2835_pll_on,
78362306a36Sopenharmony_ci	.unprepare = bcm2835_pll_off,
78462306a36Sopenharmony_ci	.recalc_rate = bcm2835_pll_get_rate,
78562306a36Sopenharmony_ci	.set_rate = bcm2835_pll_set_rate,
78662306a36Sopenharmony_ci	.round_rate = bcm2835_pll_round_rate,
78762306a36Sopenharmony_ci	.debug_init = bcm2835_pll_debug_init,
78862306a36Sopenharmony_ci};
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_cistruct bcm2835_pll_divider {
79162306a36Sopenharmony_ci	struct clk_divider div;
79262306a36Sopenharmony_ci	struct bcm2835_cprman *cprman;
79362306a36Sopenharmony_ci	const struct bcm2835_pll_divider_data *data;
79462306a36Sopenharmony_ci};
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_cistatic struct bcm2835_pll_divider *
79762306a36Sopenharmony_cibcm2835_pll_divider_from_hw(struct clk_hw *hw)
79862306a36Sopenharmony_ci{
79962306a36Sopenharmony_ci	return container_of(hw, struct bcm2835_pll_divider, div.hw);
80062306a36Sopenharmony_ci}
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_cistatic int bcm2835_pll_divider_is_on(struct clk_hw *hw)
80362306a36Sopenharmony_ci{
80462306a36Sopenharmony_ci	struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
80562306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = divider->cprman;
80662306a36Sopenharmony_ci	const struct bcm2835_pll_divider_data *data = divider->data;
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	return !(cprman_read(cprman, data->a2w_reg) & A2W_PLL_CHANNEL_DISABLE);
80962306a36Sopenharmony_ci}
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_cistatic int bcm2835_pll_divider_determine_rate(struct clk_hw *hw,
81262306a36Sopenharmony_ci					      struct clk_rate_request *req)
81362306a36Sopenharmony_ci{
81462306a36Sopenharmony_ci	return clk_divider_ops.determine_rate(hw, req);
81562306a36Sopenharmony_ci}
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_cistatic unsigned long bcm2835_pll_divider_get_rate(struct clk_hw *hw,
81862306a36Sopenharmony_ci						  unsigned long parent_rate)
81962306a36Sopenharmony_ci{
82062306a36Sopenharmony_ci	return clk_divider_ops.recalc_rate(hw, parent_rate);
82162306a36Sopenharmony_ci}
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_cistatic void bcm2835_pll_divider_off(struct clk_hw *hw)
82462306a36Sopenharmony_ci{
82562306a36Sopenharmony_ci	struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
82662306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = divider->cprman;
82762306a36Sopenharmony_ci	const struct bcm2835_pll_divider_data *data = divider->data;
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_ci	spin_lock(&cprman->regs_lock);
83062306a36Sopenharmony_ci	cprman_write(cprman, data->cm_reg,
83162306a36Sopenharmony_ci		     (cprman_read(cprman, data->cm_reg) &
83262306a36Sopenharmony_ci		      ~data->load_mask) | data->hold_mask);
83362306a36Sopenharmony_ci	cprman_write(cprman, data->a2w_reg,
83462306a36Sopenharmony_ci		     cprman_read(cprman, data->a2w_reg) |
83562306a36Sopenharmony_ci		     A2W_PLL_CHANNEL_DISABLE);
83662306a36Sopenharmony_ci	spin_unlock(&cprman->regs_lock);
83762306a36Sopenharmony_ci}
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_cistatic int bcm2835_pll_divider_on(struct clk_hw *hw)
84062306a36Sopenharmony_ci{
84162306a36Sopenharmony_ci	struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
84262306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = divider->cprman;
84362306a36Sopenharmony_ci	const struct bcm2835_pll_divider_data *data = divider->data;
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_ci	spin_lock(&cprman->regs_lock);
84662306a36Sopenharmony_ci	cprman_write(cprman, data->a2w_reg,
84762306a36Sopenharmony_ci		     cprman_read(cprman, data->a2w_reg) &
84862306a36Sopenharmony_ci		     ~A2W_PLL_CHANNEL_DISABLE);
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci	cprman_write(cprman, data->cm_reg,
85162306a36Sopenharmony_ci		     cprman_read(cprman, data->cm_reg) & ~data->hold_mask);
85262306a36Sopenharmony_ci	spin_unlock(&cprman->regs_lock);
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci	return 0;
85562306a36Sopenharmony_ci}
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_cistatic int bcm2835_pll_divider_set_rate(struct clk_hw *hw,
85862306a36Sopenharmony_ci					unsigned long rate,
85962306a36Sopenharmony_ci					unsigned long parent_rate)
86062306a36Sopenharmony_ci{
86162306a36Sopenharmony_ci	struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
86262306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = divider->cprman;
86362306a36Sopenharmony_ci	const struct bcm2835_pll_divider_data *data = divider->data;
86462306a36Sopenharmony_ci	u32 cm, div, max_div = 1 << A2W_PLL_DIV_BITS;
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_ci	div = DIV_ROUND_UP_ULL(parent_rate, rate);
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci	div = min(div, max_div);
86962306a36Sopenharmony_ci	if (div == max_div)
87062306a36Sopenharmony_ci		div = 0;
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci	cprman_write(cprman, data->a2w_reg, div);
87362306a36Sopenharmony_ci	cm = cprman_read(cprman, data->cm_reg);
87462306a36Sopenharmony_ci	cprman_write(cprman, data->cm_reg, cm | data->load_mask);
87562306a36Sopenharmony_ci	cprman_write(cprman, data->cm_reg, cm & ~data->load_mask);
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci	return 0;
87862306a36Sopenharmony_ci}
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_cistatic void bcm2835_pll_divider_debug_init(struct clk_hw *hw,
88162306a36Sopenharmony_ci					   struct dentry *dentry)
88262306a36Sopenharmony_ci{
88362306a36Sopenharmony_ci	struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
88462306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = divider->cprman;
88562306a36Sopenharmony_ci	const struct bcm2835_pll_divider_data *data = divider->data;
88662306a36Sopenharmony_ci	struct debugfs_reg32 *regs;
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_ci	regs = devm_kcalloc(cprman->dev, 7, sizeof(*regs), GFP_KERNEL);
88962306a36Sopenharmony_ci	if (!regs)
89062306a36Sopenharmony_ci		return;
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_ci	regs[0].name = "cm";
89362306a36Sopenharmony_ci	regs[0].offset = data->cm_reg;
89462306a36Sopenharmony_ci	regs[1].name = "a2w";
89562306a36Sopenharmony_ci	regs[1].offset = data->a2w_reg;
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci	bcm2835_debugfs_regset(cprman, 0, regs, 2, dentry);
89862306a36Sopenharmony_ci}
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_cistatic const struct clk_ops bcm2835_pll_divider_clk_ops = {
90162306a36Sopenharmony_ci	.is_prepared = bcm2835_pll_divider_is_on,
90262306a36Sopenharmony_ci	.prepare = bcm2835_pll_divider_on,
90362306a36Sopenharmony_ci	.unprepare = bcm2835_pll_divider_off,
90462306a36Sopenharmony_ci	.recalc_rate = bcm2835_pll_divider_get_rate,
90562306a36Sopenharmony_ci	.set_rate = bcm2835_pll_divider_set_rate,
90662306a36Sopenharmony_ci	.determine_rate = bcm2835_pll_divider_determine_rate,
90762306a36Sopenharmony_ci	.debug_init = bcm2835_pll_divider_debug_init,
90862306a36Sopenharmony_ci};
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci/*
91162306a36Sopenharmony_ci * The CM dividers do fixed-point division, so we can't use the
91262306a36Sopenharmony_ci * generic integer divider code like the PLL dividers do (and we can't
91362306a36Sopenharmony_ci * fake it by having some fixed shifts preceding it in the clock tree,
91462306a36Sopenharmony_ci * because we'd run out of bits in a 32-bit unsigned long).
91562306a36Sopenharmony_ci */
91662306a36Sopenharmony_cistruct bcm2835_clock {
91762306a36Sopenharmony_ci	struct clk_hw hw;
91862306a36Sopenharmony_ci	struct bcm2835_cprman *cprman;
91962306a36Sopenharmony_ci	const struct bcm2835_clock_data *data;
92062306a36Sopenharmony_ci};
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_cistatic struct bcm2835_clock *bcm2835_clock_from_hw(struct clk_hw *hw)
92362306a36Sopenharmony_ci{
92462306a36Sopenharmony_ci	return container_of(hw, struct bcm2835_clock, hw);
92562306a36Sopenharmony_ci}
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_cistatic int bcm2835_clock_is_on(struct clk_hw *hw)
92862306a36Sopenharmony_ci{
92962306a36Sopenharmony_ci	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
93062306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = clock->cprman;
93162306a36Sopenharmony_ci	const struct bcm2835_clock_data *data = clock->data;
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_ci	return (cprman_read(cprman, data->ctl_reg) & CM_ENABLE) != 0;
93462306a36Sopenharmony_ci}
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_cistatic u32 bcm2835_clock_choose_div(struct clk_hw *hw,
93762306a36Sopenharmony_ci				    unsigned long rate,
93862306a36Sopenharmony_ci				    unsigned long parent_rate)
93962306a36Sopenharmony_ci{
94062306a36Sopenharmony_ci	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
94162306a36Sopenharmony_ci	const struct bcm2835_clock_data *data = clock->data;
94262306a36Sopenharmony_ci	u32 unused_frac_mask =
94362306a36Sopenharmony_ci		GENMASK(CM_DIV_FRAC_BITS - data->frac_bits, 0) >> 1;
94462306a36Sopenharmony_ci	u64 temp = (u64)parent_rate << CM_DIV_FRAC_BITS;
94562306a36Sopenharmony_ci	u32 div, mindiv, maxdiv;
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci	do_div(temp, rate);
94862306a36Sopenharmony_ci	div = temp;
94962306a36Sopenharmony_ci	div &= ~unused_frac_mask;
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_ci	/* different clamping limits apply for a mash clock */
95262306a36Sopenharmony_ci	if (data->is_mash_clock) {
95362306a36Sopenharmony_ci		/* clamp to min divider of 2 */
95462306a36Sopenharmony_ci		mindiv = 2 << CM_DIV_FRAC_BITS;
95562306a36Sopenharmony_ci		/* clamp to the highest possible integer divider */
95662306a36Sopenharmony_ci		maxdiv = (BIT(data->int_bits) - 1) << CM_DIV_FRAC_BITS;
95762306a36Sopenharmony_ci	} else {
95862306a36Sopenharmony_ci		/* clamp to min divider of 1 */
95962306a36Sopenharmony_ci		mindiv = 1 << CM_DIV_FRAC_BITS;
96062306a36Sopenharmony_ci		/* clamp to the highest possible fractional divider */
96162306a36Sopenharmony_ci		maxdiv = GENMASK(data->int_bits + CM_DIV_FRAC_BITS - 1,
96262306a36Sopenharmony_ci				 CM_DIV_FRAC_BITS - data->frac_bits);
96362306a36Sopenharmony_ci	}
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	/* apply the clamping  limits */
96662306a36Sopenharmony_ci	div = max_t(u32, div, mindiv);
96762306a36Sopenharmony_ci	div = min_t(u32, div, maxdiv);
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci	return div;
97062306a36Sopenharmony_ci}
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_cistatic unsigned long bcm2835_clock_rate_from_divisor(struct bcm2835_clock *clock,
97362306a36Sopenharmony_ci						     unsigned long parent_rate,
97462306a36Sopenharmony_ci						     u32 div)
97562306a36Sopenharmony_ci{
97662306a36Sopenharmony_ci	const struct bcm2835_clock_data *data = clock->data;
97762306a36Sopenharmony_ci	u64 temp;
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	if (data->int_bits == 0 && data->frac_bits == 0)
98062306a36Sopenharmony_ci		return parent_rate;
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ci	/*
98362306a36Sopenharmony_ci	 * The divisor is a 12.12 fixed point field, but only some of
98462306a36Sopenharmony_ci	 * the bits are populated in any given clock.
98562306a36Sopenharmony_ci	 */
98662306a36Sopenharmony_ci	div >>= CM_DIV_FRAC_BITS - data->frac_bits;
98762306a36Sopenharmony_ci	div &= (1 << (data->int_bits + data->frac_bits)) - 1;
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci	if (div == 0)
99062306a36Sopenharmony_ci		return 0;
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_ci	temp = (u64)parent_rate << data->frac_bits;
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci	do_div(temp, div);
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci	return temp;
99762306a36Sopenharmony_ci}
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_cistatic unsigned long bcm2835_round_rate(unsigned long rate)
100062306a36Sopenharmony_ci{
100162306a36Sopenharmony_ci	unsigned long scaler;
100262306a36Sopenharmony_ci	unsigned long limit;
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci	limit = rate / 100000;
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_ci	scaler = 1;
100762306a36Sopenharmony_ci	while (scaler < limit)
100862306a36Sopenharmony_ci		scaler *= 10;
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	/*
101162306a36Sopenharmony_ci	 * If increasing a clock by less than 0.1% changes it
101262306a36Sopenharmony_ci	 * from ..999.. to ..000.., round up.
101362306a36Sopenharmony_ci	 */
101462306a36Sopenharmony_ci	if ((rate + scaler - 1) / scaler % 1000 == 0)
101562306a36Sopenharmony_ci		rate = roundup(rate, scaler);
101662306a36Sopenharmony_ci
101762306a36Sopenharmony_ci	return rate;
101862306a36Sopenharmony_ci}
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_cistatic unsigned long bcm2835_clock_get_rate(struct clk_hw *hw,
102162306a36Sopenharmony_ci					    unsigned long parent_rate)
102262306a36Sopenharmony_ci{
102362306a36Sopenharmony_ci	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
102462306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = clock->cprman;
102562306a36Sopenharmony_ci	const struct bcm2835_clock_data *data = clock->data;
102662306a36Sopenharmony_ci	unsigned long rate;
102762306a36Sopenharmony_ci	u32 div;
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci	if (data->int_bits == 0 && data->frac_bits == 0)
103062306a36Sopenharmony_ci		return parent_rate;
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_ci	div = cprman_read(cprman, data->div_reg);
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_ci	rate = bcm2835_clock_rate_from_divisor(clock, parent_rate, div);
103562306a36Sopenharmony_ci
103662306a36Sopenharmony_ci	if (data->round_up)
103762306a36Sopenharmony_ci		rate = bcm2835_round_rate(rate);
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci	return rate;
104062306a36Sopenharmony_ci}
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_cistatic void bcm2835_clock_wait_busy(struct bcm2835_clock *clock)
104362306a36Sopenharmony_ci{
104462306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = clock->cprman;
104562306a36Sopenharmony_ci	const struct bcm2835_clock_data *data = clock->data;
104662306a36Sopenharmony_ci	ktime_t timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci	while (cprman_read(cprman, data->ctl_reg) & CM_BUSY) {
104962306a36Sopenharmony_ci		if (ktime_after(ktime_get(), timeout)) {
105062306a36Sopenharmony_ci			dev_err(cprman->dev, "%s: couldn't lock PLL\n",
105162306a36Sopenharmony_ci				clk_hw_get_name(&clock->hw));
105262306a36Sopenharmony_ci			return;
105362306a36Sopenharmony_ci		}
105462306a36Sopenharmony_ci		cpu_relax();
105562306a36Sopenharmony_ci	}
105662306a36Sopenharmony_ci}
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_cistatic void bcm2835_clock_off(struct clk_hw *hw)
105962306a36Sopenharmony_ci{
106062306a36Sopenharmony_ci	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
106162306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = clock->cprman;
106262306a36Sopenharmony_ci	const struct bcm2835_clock_data *data = clock->data;
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci	spin_lock(&cprman->regs_lock);
106562306a36Sopenharmony_ci	cprman_write(cprman, data->ctl_reg,
106662306a36Sopenharmony_ci		     cprman_read(cprman, data->ctl_reg) & ~CM_ENABLE);
106762306a36Sopenharmony_ci	spin_unlock(&cprman->regs_lock);
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ci	/* BUSY will remain high until the divider completes its cycle. */
107062306a36Sopenharmony_ci	bcm2835_clock_wait_busy(clock);
107162306a36Sopenharmony_ci}
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_cistatic int bcm2835_clock_on(struct clk_hw *hw)
107462306a36Sopenharmony_ci{
107562306a36Sopenharmony_ci	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
107662306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = clock->cprman;
107762306a36Sopenharmony_ci	const struct bcm2835_clock_data *data = clock->data;
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_ci	spin_lock(&cprman->regs_lock);
108062306a36Sopenharmony_ci	cprman_write(cprman, data->ctl_reg,
108162306a36Sopenharmony_ci		     cprman_read(cprman, data->ctl_reg) |
108262306a36Sopenharmony_ci		     CM_ENABLE |
108362306a36Sopenharmony_ci		     CM_GATE);
108462306a36Sopenharmony_ci	spin_unlock(&cprman->regs_lock);
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci	/* Debug code to measure the clock once it's turned on to see
108762306a36Sopenharmony_ci	 * if it's ticking at the rate we expect.
108862306a36Sopenharmony_ci	 */
108962306a36Sopenharmony_ci	if (data->tcnt_mux && false) {
109062306a36Sopenharmony_ci		dev_info(cprman->dev,
109162306a36Sopenharmony_ci			 "clk %s: rate %ld, measure %ld\n",
109262306a36Sopenharmony_ci			 data->name,
109362306a36Sopenharmony_ci			 clk_hw_get_rate(hw),
109462306a36Sopenharmony_ci			 bcm2835_measure_tcnt_mux(cprman, data->tcnt_mux));
109562306a36Sopenharmony_ci	}
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_ci	return 0;
109862306a36Sopenharmony_ci}
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_cistatic int bcm2835_clock_set_rate(struct clk_hw *hw,
110162306a36Sopenharmony_ci				  unsigned long rate, unsigned long parent_rate)
110262306a36Sopenharmony_ci{
110362306a36Sopenharmony_ci	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
110462306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = clock->cprman;
110562306a36Sopenharmony_ci	const struct bcm2835_clock_data *data = clock->data;
110662306a36Sopenharmony_ci	u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate);
110762306a36Sopenharmony_ci	u32 ctl;
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_ci	spin_lock(&cprman->regs_lock);
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci	/*
111262306a36Sopenharmony_ci	 * Setting up frac support
111362306a36Sopenharmony_ci	 *
111462306a36Sopenharmony_ci	 * In principle it is recommended to stop/start the clock first,
111562306a36Sopenharmony_ci	 * but as we set CLK_SET_RATE_GATE during registration of the
111662306a36Sopenharmony_ci	 * clock this requirement should be take care of by the
111762306a36Sopenharmony_ci	 * clk-framework.
111862306a36Sopenharmony_ci	 */
111962306a36Sopenharmony_ci	ctl = cprman_read(cprman, data->ctl_reg) & ~CM_FRAC;
112062306a36Sopenharmony_ci	ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0;
112162306a36Sopenharmony_ci	cprman_write(cprman, data->ctl_reg, ctl);
112262306a36Sopenharmony_ci
112362306a36Sopenharmony_ci	cprman_write(cprman, data->div_reg, div);
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_ci	spin_unlock(&cprman->regs_lock);
112662306a36Sopenharmony_ci
112762306a36Sopenharmony_ci	return 0;
112862306a36Sopenharmony_ci}
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_cistatic bool
113162306a36Sopenharmony_cibcm2835_clk_is_pllc(struct clk_hw *hw)
113262306a36Sopenharmony_ci{
113362306a36Sopenharmony_ci	if (!hw)
113462306a36Sopenharmony_ci		return false;
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ci	return strncmp(clk_hw_get_name(hw), "pllc", 4) == 0;
113762306a36Sopenharmony_ci}
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_cistatic unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
114062306a36Sopenharmony_ci							int parent_idx,
114162306a36Sopenharmony_ci							unsigned long rate,
114262306a36Sopenharmony_ci							u32 *div,
114362306a36Sopenharmony_ci							unsigned long *prate,
114462306a36Sopenharmony_ci							unsigned long *avgrate)
114562306a36Sopenharmony_ci{
114662306a36Sopenharmony_ci	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
114762306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = clock->cprman;
114862306a36Sopenharmony_ci	const struct bcm2835_clock_data *data = clock->data;
114962306a36Sopenharmony_ci	unsigned long best_rate = 0;
115062306a36Sopenharmony_ci	u32 curdiv, mindiv, maxdiv;
115162306a36Sopenharmony_ci	struct clk_hw *parent;
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci	parent = clk_hw_get_parent_by_index(hw, parent_idx);
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci	if (!(BIT(parent_idx) & data->set_rate_parent)) {
115662306a36Sopenharmony_ci		*prate = clk_hw_get_rate(parent);
115762306a36Sopenharmony_ci		*div = bcm2835_clock_choose_div(hw, rate, *prate);
115862306a36Sopenharmony_ci
115962306a36Sopenharmony_ci		*avgrate = bcm2835_clock_rate_from_divisor(clock, *prate, *div);
116062306a36Sopenharmony_ci
116162306a36Sopenharmony_ci		if (data->low_jitter && (*div & CM_DIV_FRAC_MASK)) {
116262306a36Sopenharmony_ci			unsigned long high, low;
116362306a36Sopenharmony_ci			u32 int_div = *div & ~CM_DIV_FRAC_MASK;
116462306a36Sopenharmony_ci
116562306a36Sopenharmony_ci			high = bcm2835_clock_rate_from_divisor(clock, *prate,
116662306a36Sopenharmony_ci							       int_div);
116762306a36Sopenharmony_ci			int_div += CM_DIV_FRAC_MASK + 1;
116862306a36Sopenharmony_ci			low = bcm2835_clock_rate_from_divisor(clock, *prate,
116962306a36Sopenharmony_ci							      int_div);
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_ci			/*
117262306a36Sopenharmony_ci			 * Return a value which is the maximum deviation
117362306a36Sopenharmony_ci			 * below the ideal rate, for use as a metric.
117462306a36Sopenharmony_ci			 */
117562306a36Sopenharmony_ci			return *avgrate - max(*avgrate - low, high - *avgrate);
117662306a36Sopenharmony_ci		}
117762306a36Sopenharmony_ci		return *avgrate;
117862306a36Sopenharmony_ci	}
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci	if (data->frac_bits)
118162306a36Sopenharmony_ci		dev_warn(cprman->dev,
118262306a36Sopenharmony_ci			"frac bits are not used when propagating rate change");
118362306a36Sopenharmony_ci
118462306a36Sopenharmony_ci	/* clamp to min divider of 2 if we're dealing with a mash clock */
118562306a36Sopenharmony_ci	mindiv = data->is_mash_clock ? 2 : 1;
118662306a36Sopenharmony_ci	maxdiv = BIT(data->int_bits) - 1;
118762306a36Sopenharmony_ci
118862306a36Sopenharmony_ci	/* TODO: Be smart, and only test a subset of the available divisors. */
118962306a36Sopenharmony_ci	for (curdiv = mindiv; curdiv <= maxdiv; curdiv++) {
119062306a36Sopenharmony_ci		unsigned long tmp_rate;
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_ci		tmp_rate = clk_hw_round_rate(parent, rate * curdiv);
119362306a36Sopenharmony_ci		tmp_rate /= curdiv;
119462306a36Sopenharmony_ci		if (curdiv == mindiv ||
119562306a36Sopenharmony_ci		    (tmp_rate > best_rate && tmp_rate <= rate))
119662306a36Sopenharmony_ci			best_rate = tmp_rate;
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci		if (best_rate == rate)
119962306a36Sopenharmony_ci			break;
120062306a36Sopenharmony_ci	}
120162306a36Sopenharmony_ci
120262306a36Sopenharmony_ci	*div = curdiv << CM_DIV_FRAC_BITS;
120362306a36Sopenharmony_ci	*prate = curdiv * best_rate;
120462306a36Sopenharmony_ci	*avgrate = best_rate;
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_ci	return best_rate;
120762306a36Sopenharmony_ci}
120862306a36Sopenharmony_ci
120962306a36Sopenharmony_cistatic int bcm2835_clock_determine_rate(struct clk_hw *hw,
121062306a36Sopenharmony_ci					struct clk_rate_request *req)
121162306a36Sopenharmony_ci{
121262306a36Sopenharmony_ci	struct clk_hw *parent, *best_parent = NULL;
121362306a36Sopenharmony_ci	bool current_parent_is_pllc;
121462306a36Sopenharmony_ci	unsigned long rate, best_rate = 0;
121562306a36Sopenharmony_ci	unsigned long prate, best_prate = 0;
121662306a36Sopenharmony_ci	unsigned long avgrate, best_avgrate = 0;
121762306a36Sopenharmony_ci	size_t i;
121862306a36Sopenharmony_ci	u32 div;
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_ci	current_parent_is_pllc = bcm2835_clk_is_pllc(clk_hw_get_parent(hw));
122162306a36Sopenharmony_ci
122262306a36Sopenharmony_ci	/*
122362306a36Sopenharmony_ci	 * Select parent clock that results in the closest but lower rate
122462306a36Sopenharmony_ci	 */
122562306a36Sopenharmony_ci	for (i = 0; i < clk_hw_get_num_parents(hw); ++i) {
122662306a36Sopenharmony_ci		parent = clk_hw_get_parent_by_index(hw, i);
122762306a36Sopenharmony_ci		if (!parent)
122862306a36Sopenharmony_ci			continue;
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci		/*
123162306a36Sopenharmony_ci		 * Don't choose a PLLC-derived clock as our parent
123262306a36Sopenharmony_ci		 * unless it had been manually set that way.  PLLC's
123362306a36Sopenharmony_ci		 * frequency gets adjusted by the firmware due to
123462306a36Sopenharmony_ci		 * over-temp or under-voltage conditions, without
123562306a36Sopenharmony_ci		 * prior notification to our clock consumer.
123662306a36Sopenharmony_ci		 */
123762306a36Sopenharmony_ci		if (bcm2835_clk_is_pllc(parent) && !current_parent_is_pllc)
123862306a36Sopenharmony_ci			continue;
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_ci		rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate,
124162306a36Sopenharmony_ci							  &div, &prate,
124262306a36Sopenharmony_ci							  &avgrate);
124362306a36Sopenharmony_ci		if (abs(req->rate - rate) < abs(req->rate - best_rate)) {
124462306a36Sopenharmony_ci			best_parent = parent;
124562306a36Sopenharmony_ci			best_prate = prate;
124662306a36Sopenharmony_ci			best_rate = rate;
124762306a36Sopenharmony_ci			best_avgrate = avgrate;
124862306a36Sopenharmony_ci		}
124962306a36Sopenharmony_ci	}
125062306a36Sopenharmony_ci
125162306a36Sopenharmony_ci	if (!best_parent)
125262306a36Sopenharmony_ci		return -EINVAL;
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci	req->best_parent_hw = best_parent;
125562306a36Sopenharmony_ci	req->best_parent_rate = best_prate;
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_ci	req->rate = best_avgrate;
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci	return 0;
126062306a36Sopenharmony_ci}
126162306a36Sopenharmony_ci
126262306a36Sopenharmony_cistatic int bcm2835_clock_set_parent(struct clk_hw *hw, u8 index)
126362306a36Sopenharmony_ci{
126462306a36Sopenharmony_ci	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
126562306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = clock->cprman;
126662306a36Sopenharmony_ci	const struct bcm2835_clock_data *data = clock->data;
126762306a36Sopenharmony_ci	u8 src = (index << CM_SRC_SHIFT) & CM_SRC_MASK;
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_ci	cprman_write(cprman, data->ctl_reg, src);
127062306a36Sopenharmony_ci	return 0;
127162306a36Sopenharmony_ci}
127262306a36Sopenharmony_ci
127362306a36Sopenharmony_cistatic u8 bcm2835_clock_get_parent(struct clk_hw *hw)
127462306a36Sopenharmony_ci{
127562306a36Sopenharmony_ci	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
127662306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = clock->cprman;
127762306a36Sopenharmony_ci	const struct bcm2835_clock_data *data = clock->data;
127862306a36Sopenharmony_ci	u32 src = cprman_read(cprman, data->ctl_reg);
127962306a36Sopenharmony_ci
128062306a36Sopenharmony_ci	return (src & CM_SRC_MASK) >> CM_SRC_SHIFT;
128162306a36Sopenharmony_ci}
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_cistatic const struct debugfs_reg32 bcm2835_debugfs_clock_reg32[] = {
128462306a36Sopenharmony_ci	{
128562306a36Sopenharmony_ci		.name = "ctl",
128662306a36Sopenharmony_ci		.offset = 0,
128762306a36Sopenharmony_ci	},
128862306a36Sopenharmony_ci	{
128962306a36Sopenharmony_ci		.name = "div",
129062306a36Sopenharmony_ci		.offset = 4,
129162306a36Sopenharmony_ci	},
129262306a36Sopenharmony_ci};
129362306a36Sopenharmony_ci
129462306a36Sopenharmony_cistatic void bcm2835_clock_debug_init(struct clk_hw *hw,
129562306a36Sopenharmony_ci				    struct dentry *dentry)
129662306a36Sopenharmony_ci{
129762306a36Sopenharmony_ci	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
129862306a36Sopenharmony_ci	struct bcm2835_cprman *cprman = clock->cprman;
129962306a36Sopenharmony_ci	const struct bcm2835_clock_data *data = clock->data;
130062306a36Sopenharmony_ci
130162306a36Sopenharmony_ci	bcm2835_debugfs_regset(cprman, data->ctl_reg,
130262306a36Sopenharmony_ci		bcm2835_debugfs_clock_reg32,
130362306a36Sopenharmony_ci		ARRAY_SIZE(bcm2835_debugfs_clock_reg32),
130462306a36Sopenharmony_ci		dentry);
130562306a36Sopenharmony_ci}
130662306a36Sopenharmony_ci
130762306a36Sopenharmony_cistatic const struct clk_ops bcm2835_clock_clk_ops = {
130862306a36Sopenharmony_ci	.is_prepared = bcm2835_clock_is_on,
130962306a36Sopenharmony_ci	.prepare = bcm2835_clock_on,
131062306a36Sopenharmony_ci	.unprepare = bcm2835_clock_off,
131162306a36Sopenharmony_ci	.recalc_rate = bcm2835_clock_get_rate,
131262306a36Sopenharmony_ci	.set_rate = bcm2835_clock_set_rate,
131362306a36Sopenharmony_ci	.determine_rate = bcm2835_clock_determine_rate,
131462306a36Sopenharmony_ci	.set_parent = bcm2835_clock_set_parent,
131562306a36Sopenharmony_ci	.get_parent = bcm2835_clock_get_parent,
131662306a36Sopenharmony_ci	.debug_init = bcm2835_clock_debug_init,
131762306a36Sopenharmony_ci};
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_cistatic int bcm2835_vpu_clock_is_on(struct clk_hw *hw)
132062306a36Sopenharmony_ci{
132162306a36Sopenharmony_ci	return true;
132262306a36Sopenharmony_ci}
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_ci/*
132562306a36Sopenharmony_ci * The VPU clock can never be disabled (it doesn't have an ENABLE
132662306a36Sopenharmony_ci * bit), so it gets its own set of clock ops.
132762306a36Sopenharmony_ci */
132862306a36Sopenharmony_cistatic const struct clk_ops bcm2835_vpu_clock_clk_ops = {
132962306a36Sopenharmony_ci	.is_prepared = bcm2835_vpu_clock_is_on,
133062306a36Sopenharmony_ci	.recalc_rate = bcm2835_clock_get_rate,
133162306a36Sopenharmony_ci	.set_rate = bcm2835_clock_set_rate,
133262306a36Sopenharmony_ci	.determine_rate = bcm2835_clock_determine_rate,
133362306a36Sopenharmony_ci	.set_parent = bcm2835_clock_set_parent,
133462306a36Sopenharmony_ci	.get_parent = bcm2835_clock_get_parent,
133562306a36Sopenharmony_ci	.debug_init = bcm2835_clock_debug_init,
133662306a36Sopenharmony_ci};
133762306a36Sopenharmony_ci
133862306a36Sopenharmony_cistatic struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman,
133962306a36Sopenharmony_ci					   const void *data)
134062306a36Sopenharmony_ci{
134162306a36Sopenharmony_ci	const struct bcm2835_pll_data *pll_data = data;
134262306a36Sopenharmony_ci	struct bcm2835_pll *pll;
134362306a36Sopenharmony_ci	struct clk_init_data init;
134462306a36Sopenharmony_ci	int ret;
134562306a36Sopenharmony_ci
134662306a36Sopenharmony_ci	memset(&init, 0, sizeof(init));
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_ci	/* All of the PLLs derive from the external oscillator. */
134962306a36Sopenharmony_ci	init.parent_names = &cprman->real_parent_names[0];
135062306a36Sopenharmony_ci	init.num_parents = 1;
135162306a36Sopenharmony_ci	init.name = pll_data->name;
135262306a36Sopenharmony_ci	init.ops = &bcm2835_pll_clk_ops;
135362306a36Sopenharmony_ci	init.flags = pll_data->flags | CLK_IGNORE_UNUSED;
135462306a36Sopenharmony_ci
135562306a36Sopenharmony_ci	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
135662306a36Sopenharmony_ci	if (!pll)
135762306a36Sopenharmony_ci		return NULL;
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_ci	pll->cprman = cprman;
136062306a36Sopenharmony_ci	pll->data = pll_data;
136162306a36Sopenharmony_ci	pll->hw.init = &init;
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_ci	ret = devm_clk_hw_register(cprman->dev, &pll->hw);
136462306a36Sopenharmony_ci	if (ret) {
136562306a36Sopenharmony_ci		kfree(pll);
136662306a36Sopenharmony_ci		return NULL;
136762306a36Sopenharmony_ci	}
136862306a36Sopenharmony_ci	return &pll->hw;
136962306a36Sopenharmony_ci}
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_cistatic struct clk_hw *
137262306a36Sopenharmony_cibcm2835_register_pll_divider(struct bcm2835_cprman *cprman,
137362306a36Sopenharmony_ci			     const void *data)
137462306a36Sopenharmony_ci{
137562306a36Sopenharmony_ci	const struct bcm2835_pll_divider_data *divider_data = data;
137662306a36Sopenharmony_ci	struct bcm2835_pll_divider *divider;
137762306a36Sopenharmony_ci	struct clk_init_data init;
137862306a36Sopenharmony_ci	const char *divider_name;
137962306a36Sopenharmony_ci	int ret;
138062306a36Sopenharmony_ci
138162306a36Sopenharmony_ci	if (divider_data->fixed_divider != 1) {
138262306a36Sopenharmony_ci		divider_name = devm_kasprintf(cprman->dev, GFP_KERNEL,
138362306a36Sopenharmony_ci					      "%s_prediv", divider_data->name);
138462306a36Sopenharmony_ci		if (!divider_name)
138562306a36Sopenharmony_ci			return NULL;
138662306a36Sopenharmony_ci	} else {
138762306a36Sopenharmony_ci		divider_name = divider_data->name;
138862306a36Sopenharmony_ci	}
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci	memset(&init, 0, sizeof(init));
139162306a36Sopenharmony_ci
139262306a36Sopenharmony_ci	init.parent_names = &divider_data->source_pll;
139362306a36Sopenharmony_ci	init.num_parents = 1;
139462306a36Sopenharmony_ci	init.name = divider_name;
139562306a36Sopenharmony_ci	init.ops = &bcm2835_pll_divider_clk_ops;
139662306a36Sopenharmony_ci	init.flags = divider_data->flags | CLK_IGNORE_UNUSED;
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci	divider = devm_kzalloc(cprman->dev, sizeof(*divider), GFP_KERNEL);
139962306a36Sopenharmony_ci	if (!divider)
140062306a36Sopenharmony_ci		return NULL;
140162306a36Sopenharmony_ci
140262306a36Sopenharmony_ci	divider->div.reg = cprman->regs + divider_data->a2w_reg;
140362306a36Sopenharmony_ci	divider->div.shift = A2W_PLL_DIV_SHIFT;
140462306a36Sopenharmony_ci	divider->div.width = A2W_PLL_DIV_BITS;
140562306a36Sopenharmony_ci	divider->div.flags = CLK_DIVIDER_MAX_AT_ZERO;
140662306a36Sopenharmony_ci	divider->div.lock = &cprman->regs_lock;
140762306a36Sopenharmony_ci	divider->div.hw.init = &init;
140862306a36Sopenharmony_ci	divider->div.table = NULL;
140962306a36Sopenharmony_ci
141062306a36Sopenharmony_ci	divider->cprman = cprman;
141162306a36Sopenharmony_ci	divider->data = divider_data;
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_ci	ret = devm_clk_hw_register(cprman->dev, &divider->div.hw);
141462306a36Sopenharmony_ci	if (ret)
141562306a36Sopenharmony_ci		return ERR_PTR(ret);
141662306a36Sopenharmony_ci
141762306a36Sopenharmony_ci	/*
141862306a36Sopenharmony_ci	 * PLLH's channels have a fixed divide by 10 afterwards, which
141962306a36Sopenharmony_ci	 * is what our consumers are actually using.
142062306a36Sopenharmony_ci	 */
142162306a36Sopenharmony_ci	if (divider_data->fixed_divider != 1) {
142262306a36Sopenharmony_ci		return clk_hw_register_fixed_factor(cprman->dev,
142362306a36Sopenharmony_ci						    divider_data->name,
142462306a36Sopenharmony_ci						    divider_name,
142562306a36Sopenharmony_ci						    CLK_SET_RATE_PARENT,
142662306a36Sopenharmony_ci						    1,
142762306a36Sopenharmony_ci						    divider_data->fixed_divider);
142862306a36Sopenharmony_ci	}
142962306a36Sopenharmony_ci
143062306a36Sopenharmony_ci	return &divider->div.hw;
143162306a36Sopenharmony_ci}
143262306a36Sopenharmony_ci
143362306a36Sopenharmony_cistatic struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman,
143462306a36Sopenharmony_ci					     const void *data)
143562306a36Sopenharmony_ci{
143662306a36Sopenharmony_ci	const struct bcm2835_clock_data *clock_data = data;
143762306a36Sopenharmony_ci	struct bcm2835_clock *clock;
143862306a36Sopenharmony_ci	struct clk_init_data init;
143962306a36Sopenharmony_ci	const char *parents[1 << CM_SRC_BITS];
144062306a36Sopenharmony_ci	size_t i;
144162306a36Sopenharmony_ci	int ret;
144262306a36Sopenharmony_ci
144362306a36Sopenharmony_ci	/*
144462306a36Sopenharmony_ci	 * Replace our strings referencing parent clocks with the
144562306a36Sopenharmony_ci	 * actual clock-output-name of the parent.
144662306a36Sopenharmony_ci	 */
144762306a36Sopenharmony_ci	for (i = 0; i < clock_data->num_mux_parents; i++) {
144862306a36Sopenharmony_ci		parents[i] = clock_data->parents[i];
144962306a36Sopenharmony_ci
145062306a36Sopenharmony_ci		ret = match_string(cprman_parent_names,
145162306a36Sopenharmony_ci				   ARRAY_SIZE(cprman_parent_names),
145262306a36Sopenharmony_ci				   parents[i]);
145362306a36Sopenharmony_ci		if (ret >= 0)
145462306a36Sopenharmony_ci			parents[i] = cprman->real_parent_names[ret];
145562306a36Sopenharmony_ci	}
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_ci	memset(&init, 0, sizeof(init));
145862306a36Sopenharmony_ci	init.parent_names = parents;
145962306a36Sopenharmony_ci	init.num_parents = clock_data->num_mux_parents;
146062306a36Sopenharmony_ci	init.name = clock_data->name;
146162306a36Sopenharmony_ci	init.flags = clock_data->flags | CLK_IGNORE_UNUSED;
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci	/*
146462306a36Sopenharmony_ci	 * Pass the CLK_SET_RATE_PARENT flag if we are allowed to propagate
146562306a36Sopenharmony_ci	 * rate changes on at least of the parents.
146662306a36Sopenharmony_ci	 */
146762306a36Sopenharmony_ci	if (clock_data->set_rate_parent)
146862306a36Sopenharmony_ci		init.flags |= CLK_SET_RATE_PARENT;
146962306a36Sopenharmony_ci
147062306a36Sopenharmony_ci	if (clock_data->is_vpu_clock) {
147162306a36Sopenharmony_ci		init.ops = &bcm2835_vpu_clock_clk_ops;
147262306a36Sopenharmony_ci	} else {
147362306a36Sopenharmony_ci		init.ops = &bcm2835_clock_clk_ops;
147462306a36Sopenharmony_ci		init.flags |= CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
147562306a36Sopenharmony_ci
147662306a36Sopenharmony_ci		/* If the clock wasn't actually enabled at boot, it's not
147762306a36Sopenharmony_ci		 * critical.
147862306a36Sopenharmony_ci		 */
147962306a36Sopenharmony_ci		if (!(cprman_read(cprman, clock_data->ctl_reg) & CM_ENABLE))
148062306a36Sopenharmony_ci			init.flags &= ~CLK_IS_CRITICAL;
148162306a36Sopenharmony_ci	}
148262306a36Sopenharmony_ci
148362306a36Sopenharmony_ci	clock = devm_kzalloc(cprman->dev, sizeof(*clock), GFP_KERNEL);
148462306a36Sopenharmony_ci	if (!clock)
148562306a36Sopenharmony_ci		return NULL;
148662306a36Sopenharmony_ci
148762306a36Sopenharmony_ci	clock->cprman = cprman;
148862306a36Sopenharmony_ci	clock->data = clock_data;
148962306a36Sopenharmony_ci	clock->hw.init = &init;
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_ci	ret = devm_clk_hw_register(cprman->dev, &clock->hw);
149262306a36Sopenharmony_ci	if (ret)
149362306a36Sopenharmony_ci		return ERR_PTR(ret);
149462306a36Sopenharmony_ci	return &clock->hw;
149562306a36Sopenharmony_ci}
149662306a36Sopenharmony_ci
149762306a36Sopenharmony_cistatic struct clk_hw *bcm2835_register_gate(struct bcm2835_cprman *cprman,
149862306a36Sopenharmony_ci					    const void *data)
149962306a36Sopenharmony_ci{
150062306a36Sopenharmony_ci	const struct bcm2835_gate_data *gate_data = data;
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci	return clk_hw_register_gate(cprman->dev, gate_data->name,
150362306a36Sopenharmony_ci				    gate_data->parent,
150462306a36Sopenharmony_ci				    CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
150562306a36Sopenharmony_ci				    cprman->regs + gate_data->ctl_reg,
150662306a36Sopenharmony_ci				    CM_GATE_BIT, 0, &cprman->regs_lock);
150762306a36Sopenharmony_ci}
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_cistruct bcm2835_clk_desc {
151062306a36Sopenharmony_ci	struct clk_hw *(*clk_register)(struct bcm2835_cprman *cprman,
151162306a36Sopenharmony_ci				       const void *data);
151262306a36Sopenharmony_ci	unsigned int supported;
151362306a36Sopenharmony_ci	const void *data;
151462306a36Sopenharmony_ci};
151562306a36Sopenharmony_ci
151662306a36Sopenharmony_ci/* assignment helper macros for different clock types */
151762306a36Sopenharmony_ci#define _REGISTER(f, s, ...) { .clk_register = f, \
151862306a36Sopenharmony_ci			       .supported = s,				\
151962306a36Sopenharmony_ci			       .data = __VA_ARGS__ }
152062306a36Sopenharmony_ci#define REGISTER_PLL(s, ...)	_REGISTER(&bcm2835_register_pll,	\
152162306a36Sopenharmony_ci					  s,				\
152262306a36Sopenharmony_ci					  &(struct bcm2835_pll_data)	\
152362306a36Sopenharmony_ci					  {__VA_ARGS__})
152462306a36Sopenharmony_ci#define REGISTER_PLL_DIV(s, ...) _REGISTER(&bcm2835_register_pll_divider, \
152562306a36Sopenharmony_ci					   s,				  \
152662306a36Sopenharmony_ci					   &(struct bcm2835_pll_divider_data) \
152762306a36Sopenharmony_ci					   {__VA_ARGS__})
152862306a36Sopenharmony_ci#define REGISTER_CLK(s, ...)	_REGISTER(&bcm2835_register_clock,	\
152962306a36Sopenharmony_ci					  s,				\
153062306a36Sopenharmony_ci					  &(struct bcm2835_clock_data)	\
153162306a36Sopenharmony_ci					  {__VA_ARGS__})
153262306a36Sopenharmony_ci#define REGISTER_GATE(s, ...)	_REGISTER(&bcm2835_register_gate,	\
153362306a36Sopenharmony_ci					  s,				\
153462306a36Sopenharmony_ci					  &(struct bcm2835_gate_data)	\
153562306a36Sopenharmony_ci					  {__VA_ARGS__})
153662306a36Sopenharmony_ci
153762306a36Sopenharmony_ci/* parent mux arrays plus helper macros */
153862306a36Sopenharmony_ci
153962306a36Sopenharmony_ci/* main oscillator parent mux */
154062306a36Sopenharmony_cistatic const char *const bcm2835_clock_osc_parents[] = {
154162306a36Sopenharmony_ci	"gnd",
154262306a36Sopenharmony_ci	"xosc",
154362306a36Sopenharmony_ci	"testdebug0",
154462306a36Sopenharmony_ci	"testdebug1"
154562306a36Sopenharmony_ci};
154662306a36Sopenharmony_ci
154762306a36Sopenharmony_ci#define REGISTER_OSC_CLK(s, ...)	REGISTER_CLK(			\
154862306a36Sopenharmony_ci	s,								\
154962306a36Sopenharmony_ci	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents),	\
155062306a36Sopenharmony_ci	.parents = bcm2835_clock_osc_parents,				\
155162306a36Sopenharmony_ci	__VA_ARGS__)
155262306a36Sopenharmony_ci
155362306a36Sopenharmony_ci/* main peripherial parent mux */
155462306a36Sopenharmony_cistatic const char *const bcm2835_clock_per_parents[] = {
155562306a36Sopenharmony_ci	"gnd",
155662306a36Sopenharmony_ci	"xosc",
155762306a36Sopenharmony_ci	"testdebug0",
155862306a36Sopenharmony_ci	"testdebug1",
155962306a36Sopenharmony_ci	"plla_per",
156062306a36Sopenharmony_ci	"pllc_per",
156162306a36Sopenharmony_ci	"plld_per",
156262306a36Sopenharmony_ci	"pllh_aux",
156362306a36Sopenharmony_ci};
156462306a36Sopenharmony_ci
156562306a36Sopenharmony_ci#define REGISTER_PER_CLK(s, ...)	REGISTER_CLK(			\
156662306a36Sopenharmony_ci	s,								\
156762306a36Sopenharmony_ci	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),	\
156862306a36Sopenharmony_ci	.parents = bcm2835_clock_per_parents,				\
156962306a36Sopenharmony_ci	__VA_ARGS__)
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci/*
157262306a36Sopenharmony_ci * Restrict clock sources for the PCM peripheral to the oscillator and
157362306a36Sopenharmony_ci * PLLD_PER because other source may have varying rates or be switched
157462306a36Sopenharmony_ci * off.
157562306a36Sopenharmony_ci *
157662306a36Sopenharmony_ci * Prevent other sources from being selected by replacing their names in
157762306a36Sopenharmony_ci * the list of potential parents with dummy entries (entry index is
157862306a36Sopenharmony_ci * significant).
157962306a36Sopenharmony_ci */
158062306a36Sopenharmony_cistatic const char *const bcm2835_pcm_per_parents[] = {
158162306a36Sopenharmony_ci	"-",
158262306a36Sopenharmony_ci	"xosc",
158362306a36Sopenharmony_ci	"-",
158462306a36Sopenharmony_ci	"-",
158562306a36Sopenharmony_ci	"-",
158662306a36Sopenharmony_ci	"-",
158762306a36Sopenharmony_ci	"plld_per",
158862306a36Sopenharmony_ci	"-",
158962306a36Sopenharmony_ci};
159062306a36Sopenharmony_ci
159162306a36Sopenharmony_ci#define REGISTER_PCM_CLK(s, ...)	REGISTER_CLK(			\
159262306a36Sopenharmony_ci	s,								\
159362306a36Sopenharmony_ci	.num_mux_parents = ARRAY_SIZE(bcm2835_pcm_per_parents),		\
159462306a36Sopenharmony_ci	.parents = bcm2835_pcm_per_parents,				\
159562306a36Sopenharmony_ci	__VA_ARGS__)
159662306a36Sopenharmony_ci
159762306a36Sopenharmony_ci/* main vpu parent mux */
159862306a36Sopenharmony_cistatic const char *const bcm2835_clock_vpu_parents[] = {
159962306a36Sopenharmony_ci	"gnd",
160062306a36Sopenharmony_ci	"xosc",
160162306a36Sopenharmony_ci	"testdebug0",
160262306a36Sopenharmony_ci	"testdebug1",
160362306a36Sopenharmony_ci	"plla_core",
160462306a36Sopenharmony_ci	"pllc_core0",
160562306a36Sopenharmony_ci	"plld_core",
160662306a36Sopenharmony_ci	"pllh_aux",
160762306a36Sopenharmony_ci	"pllc_core1",
160862306a36Sopenharmony_ci	"pllc_core2",
160962306a36Sopenharmony_ci};
161062306a36Sopenharmony_ci
161162306a36Sopenharmony_ci#define REGISTER_VPU_CLK(s, ...)	REGISTER_CLK(			\
161262306a36Sopenharmony_ci	s,								\
161362306a36Sopenharmony_ci	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),	\
161462306a36Sopenharmony_ci	.parents = bcm2835_clock_vpu_parents,				\
161562306a36Sopenharmony_ci	__VA_ARGS__)
161662306a36Sopenharmony_ci
161762306a36Sopenharmony_ci/*
161862306a36Sopenharmony_ci * DSI parent clocks.  The DSI byte/DDR/DDR2 clocks come from the DSI
161962306a36Sopenharmony_ci * analog PHY.  The _inv variants are generated internally to cprman,
162062306a36Sopenharmony_ci * but we don't use them so they aren't hooked up.
162162306a36Sopenharmony_ci */
162262306a36Sopenharmony_cistatic const char *const bcm2835_clock_dsi0_parents[] = {
162362306a36Sopenharmony_ci	"gnd",
162462306a36Sopenharmony_ci	"xosc",
162562306a36Sopenharmony_ci	"testdebug0",
162662306a36Sopenharmony_ci	"testdebug1",
162762306a36Sopenharmony_ci	"dsi0_ddr",
162862306a36Sopenharmony_ci	"dsi0_ddr_inv",
162962306a36Sopenharmony_ci	"dsi0_ddr2",
163062306a36Sopenharmony_ci	"dsi0_ddr2_inv",
163162306a36Sopenharmony_ci	"dsi0_byte",
163262306a36Sopenharmony_ci	"dsi0_byte_inv",
163362306a36Sopenharmony_ci};
163462306a36Sopenharmony_ci
163562306a36Sopenharmony_cistatic const char *const bcm2835_clock_dsi1_parents[] = {
163662306a36Sopenharmony_ci	"gnd",
163762306a36Sopenharmony_ci	"xosc",
163862306a36Sopenharmony_ci	"testdebug0",
163962306a36Sopenharmony_ci	"testdebug1",
164062306a36Sopenharmony_ci	"dsi1_ddr",
164162306a36Sopenharmony_ci	"dsi1_ddr_inv",
164262306a36Sopenharmony_ci	"dsi1_ddr2",
164362306a36Sopenharmony_ci	"dsi1_ddr2_inv",
164462306a36Sopenharmony_ci	"dsi1_byte",
164562306a36Sopenharmony_ci	"dsi1_byte_inv",
164662306a36Sopenharmony_ci};
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_ci#define REGISTER_DSI0_CLK(s, ...)	REGISTER_CLK(			\
164962306a36Sopenharmony_ci	s,								\
165062306a36Sopenharmony_ci	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_dsi0_parents),	\
165162306a36Sopenharmony_ci	.parents = bcm2835_clock_dsi0_parents,				\
165262306a36Sopenharmony_ci	__VA_ARGS__)
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_ci#define REGISTER_DSI1_CLK(s, ...)	REGISTER_CLK(			\
165562306a36Sopenharmony_ci	s,								\
165662306a36Sopenharmony_ci	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_dsi1_parents),	\
165762306a36Sopenharmony_ci	.parents = bcm2835_clock_dsi1_parents,				\
165862306a36Sopenharmony_ci	__VA_ARGS__)
165962306a36Sopenharmony_ci
166062306a36Sopenharmony_ci/*
166162306a36Sopenharmony_ci * the real definition of all the pll, pll_dividers and clocks
166262306a36Sopenharmony_ci * these make use of the above REGISTER_* macros
166362306a36Sopenharmony_ci */
166462306a36Sopenharmony_cistatic const struct bcm2835_clk_desc clk_desc_array[] = {
166562306a36Sopenharmony_ci	/* the PLL + PLL dividers */
166662306a36Sopenharmony_ci
166762306a36Sopenharmony_ci	/*
166862306a36Sopenharmony_ci	 * PLLA is the auxiliary PLL, used to drive the CCP2
166962306a36Sopenharmony_ci	 * (Compact Camera Port 2) transmitter clock.
167062306a36Sopenharmony_ci	 *
167162306a36Sopenharmony_ci	 * It is in the PX LDO power domain, which is on when the
167262306a36Sopenharmony_ci	 * AUDIO domain is on.
167362306a36Sopenharmony_ci	 */
167462306a36Sopenharmony_ci	[BCM2835_PLLA]		= REGISTER_PLL(
167562306a36Sopenharmony_ci		SOC_ALL,
167662306a36Sopenharmony_ci		.name = "plla",
167762306a36Sopenharmony_ci		.cm_ctrl_reg = CM_PLLA,
167862306a36Sopenharmony_ci		.a2w_ctrl_reg = A2W_PLLA_CTRL,
167962306a36Sopenharmony_ci		.frac_reg = A2W_PLLA_FRAC,
168062306a36Sopenharmony_ci		.ana_reg_base = A2W_PLLA_ANA0,
168162306a36Sopenharmony_ci		.reference_enable_mask = A2W_XOSC_CTRL_PLLA_ENABLE,
168262306a36Sopenharmony_ci		.lock_mask = CM_LOCK_FLOCKA,
168362306a36Sopenharmony_ci
168462306a36Sopenharmony_ci		.ana = &bcm2835_ana_default,
168562306a36Sopenharmony_ci
168662306a36Sopenharmony_ci		.min_rate = 600000000u,
168762306a36Sopenharmony_ci		.max_rate = 2400000000u,
168862306a36Sopenharmony_ci		.max_fb_rate = BCM2835_MAX_FB_RATE),
168962306a36Sopenharmony_ci	[BCM2835_PLLA_CORE]	= REGISTER_PLL_DIV(
169062306a36Sopenharmony_ci		SOC_ALL,
169162306a36Sopenharmony_ci		.name = "plla_core",
169262306a36Sopenharmony_ci		.source_pll = "plla",
169362306a36Sopenharmony_ci		.cm_reg = CM_PLLA,
169462306a36Sopenharmony_ci		.a2w_reg = A2W_PLLA_CORE,
169562306a36Sopenharmony_ci		.load_mask = CM_PLLA_LOADCORE,
169662306a36Sopenharmony_ci		.hold_mask = CM_PLLA_HOLDCORE,
169762306a36Sopenharmony_ci		.fixed_divider = 1,
169862306a36Sopenharmony_ci		.flags = CLK_SET_RATE_PARENT),
169962306a36Sopenharmony_ci	[BCM2835_PLLA_PER]	= REGISTER_PLL_DIV(
170062306a36Sopenharmony_ci		SOC_ALL,
170162306a36Sopenharmony_ci		.name = "plla_per",
170262306a36Sopenharmony_ci		.source_pll = "plla",
170362306a36Sopenharmony_ci		.cm_reg = CM_PLLA,
170462306a36Sopenharmony_ci		.a2w_reg = A2W_PLLA_PER,
170562306a36Sopenharmony_ci		.load_mask = CM_PLLA_LOADPER,
170662306a36Sopenharmony_ci		.hold_mask = CM_PLLA_HOLDPER,
170762306a36Sopenharmony_ci		.fixed_divider = 1,
170862306a36Sopenharmony_ci		.flags = CLK_SET_RATE_PARENT),
170962306a36Sopenharmony_ci	[BCM2835_PLLA_DSI0]	= REGISTER_PLL_DIV(
171062306a36Sopenharmony_ci		SOC_ALL,
171162306a36Sopenharmony_ci		.name = "plla_dsi0",
171262306a36Sopenharmony_ci		.source_pll = "plla",
171362306a36Sopenharmony_ci		.cm_reg = CM_PLLA,
171462306a36Sopenharmony_ci		.a2w_reg = A2W_PLLA_DSI0,
171562306a36Sopenharmony_ci		.load_mask = CM_PLLA_LOADDSI0,
171662306a36Sopenharmony_ci		.hold_mask = CM_PLLA_HOLDDSI0,
171762306a36Sopenharmony_ci		.fixed_divider = 1),
171862306a36Sopenharmony_ci	[BCM2835_PLLA_CCP2]	= REGISTER_PLL_DIV(
171962306a36Sopenharmony_ci		SOC_ALL,
172062306a36Sopenharmony_ci		.name = "plla_ccp2",
172162306a36Sopenharmony_ci		.source_pll = "plla",
172262306a36Sopenharmony_ci		.cm_reg = CM_PLLA,
172362306a36Sopenharmony_ci		.a2w_reg = A2W_PLLA_CCP2,
172462306a36Sopenharmony_ci		.load_mask = CM_PLLA_LOADCCP2,
172562306a36Sopenharmony_ci		.hold_mask = CM_PLLA_HOLDCCP2,
172662306a36Sopenharmony_ci		.fixed_divider = 1,
172762306a36Sopenharmony_ci		.flags = CLK_SET_RATE_PARENT),
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_ci	/* PLLB is used for the ARM's clock. */
173062306a36Sopenharmony_ci	[BCM2835_PLLB]		= REGISTER_PLL(
173162306a36Sopenharmony_ci		SOC_ALL,
173262306a36Sopenharmony_ci		.name = "pllb",
173362306a36Sopenharmony_ci		.cm_ctrl_reg = CM_PLLB,
173462306a36Sopenharmony_ci		.a2w_ctrl_reg = A2W_PLLB_CTRL,
173562306a36Sopenharmony_ci		.frac_reg = A2W_PLLB_FRAC,
173662306a36Sopenharmony_ci		.ana_reg_base = A2W_PLLB_ANA0,
173762306a36Sopenharmony_ci		.reference_enable_mask = A2W_XOSC_CTRL_PLLB_ENABLE,
173862306a36Sopenharmony_ci		.lock_mask = CM_LOCK_FLOCKB,
173962306a36Sopenharmony_ci
174062306a36Sopenharmony_ci		.ana = &bcm2835_ana_default,
174162306a36Sopenharmony_ci
174262306a36Sopenharmony_ci		.min_rate = 600000000u,
174362306a36Sopenharmony_ci		.max_rate = 3000000000u,
174462306a36Sopenharmony_ci		.max_fb_rate = BCM2835_MAX_FB_RATE,
174562306a36Sopenharmony_ci		.flags = CLK_GET_RATE_NOCACHE),
174662306a36Sopenharmony_ci	[BCM2835_PLLB_ARM]	= REGISTER_PLL_DIV(
174762306a36Sopenharmony_ci		SOC_ALL,
174862306a36Sopenharmony_ci		.name = "pllb_arm",
174962306a36Sopenharmony_ci		.source_pll = "pllb",
175062306a36Sopenharmony_ci		.cm_reg = CM_PLLB,
175162306a36Sopenharmony_ci		.a2w_reg = A2W_PLLB_ARM,
175262306a36Sopenharmony_ci		.load_mask = CM_PLLB_LOADARM,
175362306a36Sopenharmony_ci		.hold_mask = CM_PLLB_HOLDARM,
175462306a36Sopenharmony_ci		.fixed_divider = 1,
175562306a36Sopenharmony_ci		.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE),
175662306a36Sopenharmony_ci
175762306a36Sopenharmony_ci	/*
175862306a36Sopenharmony_ci	 * PLLC is the core PLL, used to drive the core VPU clock.
175962306a36Sopenharmony_ci	 *
176062306a36Sopenharmony_ci	 * It is in the PX LDO power domain, which is on when the
176162306a36Sopenharmony_ci	 * AUDIO domain is on.
176262306a36Sopenharmony_ci	 */
176362306a36Sopenharmony_ci	[BCM2835_PLLC]		= REGISTER_PLL(
176462306a36Sopenharmony_ci		SOC_ALL,
176562306a36Sopenharmony_ci		.name = "pllc",
176662306a36Sopenharmony_ci		.cm_ctrl_reg = CM_PLLC,
176762306a36Sopenharmony_ci		.a2w_ctrl_reg = A2W_PLLC_CTRL,
176862306a36Sopenharmony_ci		.frac_reg = A2W_PLLC_FRAC,
176962306a36Sopenharmony_ci		.ana_reg_base = A2W_PLLC_ANA0,
177062306a36Sopenharmony_ci		.reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE,
177162306a36Sopenharmony_ci		.lock_mask = CM_LOCK_FLOCKC,
177262306a36Sopenharmony_ci
177362306a36Sopenharmony_ci		.ana = &bcm2835_ana_default,
177462306a36Sopenharmony_ci
177562306a36Sopenharmony_ci		.min_rate = 600000000u,
177662306a36Sopenharmony_ci		.max_rate = 3000000000u,
177762306a36Sopenharmony_ci		.max_fb_rate = BCM2835_MAX_FB_RATE),
177862306a36Sopenharmony_ci	[BCM2835_PLLC_CORE0]	= REGISTER_PLL_DIV(
177962306a36Sopenharmony_ci		SOC_ALL,
178062306a36Sopenharmony_ci		.name = "pllc_core0",
178162306a36Sopenharmony_ci		.source_pll = "pllc",
178262306a36Sopenharmony_ci		.cm_reg = CM_PLLC,
178362306a36Sopenharmony_ci		.a2w_reg = A2W_PLLC_CORE0,
178462306a36Sopenharmony_ci		.load_mask = CM_PLLC_LOADCORE0,
178562306a36Sopenharmony_ci		.hold_mask = CM_PLLC_HOLDCORE0,
178662306a36Sopenharmony_ci		.fixed_divider = 1,
178762306a36Sopenharmony_ci		.flags = CLK_SET_RATE_PARENT),
178862306a36Sopenharmony_ci	[BCM2835_PLLC_CORE1]	= REGISTER_PLL_DIV(
178962306a36Sopenharmony_ci		SOC_ALL,
179062306a36Sopenharmony_ci		.name = "pllc_core1",
179162306a36Sopenharmony_ci		.source_pll = "pllc",
179262306a36Sopenharmony_ci		.cm_reg = CM_PLLC,
179362306a36Sopenharmony_ci		.a2w_reg = A2W_PLLC_CORE1,
179462306a36Sopenharmony_ci		.load_mask = CM_PLLC_LOADCORE1,
179562306a36Sopenharmony_ci		.hold_mask = CM_PLLC_HOLDCORE1,
179662306a36Sopenharmony_ci		.fixed_divider = 1,
179762306a36Sopenharmony_ci		.flags = CLK_SET_RATE_PARENT),
179862306a36Sopenharmony_ci	[BCM2835_PLLC_CORE2]	= REGISTER_PLL_DIV(
179962306a36Sopenharmony_ci		SOC_ALL,
180062306a36Sopenharmony_ci		.name = "pllc_core2",
180162306a36Sopenharmony_ci		.source_pll = "pllc",
180262306a36Sopenharmony_ci		.cm_reg = CM_PLLC,
180362306a36Sopenharmony_ci		.a2w_reg = A2W_PLLC_CORE2,
180462306a36Sopenharmony_ci		.load_mask = CM_PLLC_LOADCORE2,
180562306a36Sopenharmony_ci		.hold_mask = CM_PLLC_HOLDCORE2,
180662306a36Sopenharmony_ci		.fixed_divider = 1,
180762306a36Sopenharmony_ci		.flags = CLK_SET_RATE_PARENT),
180862306a36Sopenharmony_ci	[BCM2835_PLLC_PER]	= REGISTER_PLL_DIV(
180962306a36Sopenharmony_ci		SOC_ALL,
181062306a36Sopenharmony_ci		.name = "pllc_per",
181162306a36Sopenharmony_ci		.source_pll = "pllc",
181262306a36Sopenharmony_ci		.cm_reg = CM_PLLC,
181362306a36Sopenharmony_ci		.a2w_reg = A2W_PLLC_PER,
181462306a36Sopenharmony_ci		.load_mask = CM_PLLC_LOADPER,
181562306a36Sopenharmony_ci		.hold_mask = CM_PLLC_HOLDPER,
181662306a36Sopenharmony_ci		.fixed_divider = 1,
181762306a36Sopenharmony_ci		.flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
181862306a36Sopenharmony_ci
181962306a36Sopenharmony_ci	/*
182062306a36Sopenharmony_ci	 * PLLD is the display PLL, used to drive DSI display panels.
182162306a36Sopenharmony_ci	 *
182262306a36Sopenharmony_ci	 * It is in the PX LDO power domain, which is on when the
182362306a36Sopenharmony_ci	 * AUDIO domain is on.
182462306a36Sopenharmony_ci	 */
182562306a36Sopenharmony_ci	[BCM2835_PLLD]		= REGISTER_PLL(
182662306a36Sopenharmony_ci		SOC_ALL,
182762306a36Sopenharmony_ci		.name = "plld",
182862306a36Sopenharmony_ci		.cm_ctrl_reg = CM_PLLD,
182962306a36Sopenharmony_ci		.a2w_ctrl_reg = A2W_PLLD_CTRL,
183062306a36Sopenharmony_ci		.frac_reg = A2W_PLLD_FRAC,
183162306a36Sopenharmony_ci		.ana_reg_base = A2W_PLLD_ANA0,
183262306a36Sopenharmony_ci		.reference_enable_mask = A2W_XOSC_CTRL_DDR_ENABLE,
183362306a36Sopenharmony_ci		.lock_mask = CM_LOCK_FLOCKD,
183462306a36Sopenharmony_ci
183562306a36Sopenharmony_ci		.ana = &bcm2835_ana_default,
183662306a36Sopenharmony_ci
183762306a36Sopenharmony_ci		.min_rate = 600000000u,
183862306a36Sopenharmony_ci		.max_rate = 2400000000u,
183962306a36Sopenharmony_ci		.max_fb_rate = BCM2835_MAX_FB_RATE),
184062306a36Sopenharmony_ci	[BCM2835_PLLD_CORE]	= REGISTER_PLL_DIV(
184162306a36Sopenharmony_ci		SOC_ALL,
184262306a36Sopenharmony_ci		.name = "plld_core",
184362306a36Sopenharmony_ci		.source_pll = "plld",
184462306a36Sopenharmony_ci		.cm_reg = CM_PLLD,
184562306a36Sopenharmony_ci		.a2w_reg = A2W_PLLD_CORE,
184662306a36Sopenharmony_ci		.load_mask = CM_PLLD_LOADCORE,
184762306a36Sopenharmony_ci		.hold_mask = CM_PLLD_HOLDCORE,
184862306a36Sopenharmony_ci		.fixed_divider = 1,
184962306a36Sopenharmony_ci		.flags = CLK_SET_RATE_PARENT),
185062306a36Sopenharmony_ci	/*
185162306a36Sopenharmony_ci	 * VPU firmware assumes that PLLD_PER isn't disabled by the ARM core.
185262306a36Sopenharmony_ci	 * Otherwise this could cause firmware lookups. That's why we mark
185362306a36Sopenharmony_ci	 * it as critical.
185462306a36Sopenharmony_ci	 */
185562306a36Sopenharmony_ci	[BCM2835_PLLD_PER]	= REGISTER_PLL_DIV(
185662306a36Sopenharmony_ci		SOC_ALL,
185762306a36Sopenharmony_ci		.name = "plld_per",
185862306a36Sopenharmony_ci		.source_pll = "plld",
185962306a36Sopenharmony_ci		.cm_reg = CM_PLLD,
186062306a36Sopenharmony_ci		.a2w_reg = A2W_PLLD_PER,
186162306a36Sopenharmony_ci		.load_mask = CM_PLLD_LOADPER,
186262306a36Sopenharmony_ci		.hold_mask = CM_PLLD_HOLDPER,
186362306a36Sopenharmony_ci		.fixed_divider = 1,
186462306a36Sopenharmony_ci		.flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
186562306a36Sopenharmony_ci	[BCM2835_PLLD_DSI0]	= REGISTER_PLL_DIV(
186662306a36Sopenharmony_ci		SOC_ALL,
186762306a36Sopenharmony_ci		.name = "plld_dsi0",
186862306a36Sopenharmony_ci		.source_pll = "plld",
186962306a36Sopenharmony_ci		.cm_reg = CM_PLLD,
187062306a36Sopenharmony_ci		.a2w_reg = A2W_PLLD_DSI0,
187162306a36Sopenharmony_ci		.load_mask = CM_PLLD_LOADDSI0,
187262306a36Sopenharmony_ci		.hold_mask = CM_PLLD_HOLDDSI0,
187362306a36Sopenharmony_ci		.fixed_divider = 1),
187462306a36Sopenharmony_ci	[BCM2835_PLLD_DSI1]	= REGISTER_PLL_DIV(
187562306a36Sopenharmony_ci		SOC_ALL,
187662306a36Sopenharmony_ci		.name = "plld_dsi1",
187762306a36Sopenharmony_ci		.source_pll = "plld",
187862306a36Sopenharmony_ci		.cm_reg = CM_PLLD,
187962306a36Sopenharmony_ci		.a2w_reg = A2W_PLLD_DSI1,
188062306a36Sopenharmony_ci		.load_mask = CM_PLLD_LOADDSI1,
188162306a36Sopenharmony_ci		.hold_mask = CM_PLLD_HOLDDSI1,
188262306a36Sopenharmony_ci		.fixed_divider = 1),
188362306a36Sopenharmony_ci
188462306a36Sopenharmony_ci	/*
188562306a36Sopenharmony_ci	 * PLLH is used to supply the pixel clock or the AUX clock for the
188662306a36Sopenharmony_ci	 * TV encoder.
188762306a36Sopenharmony_ci	 *
188862306a36Sopenharmony_ci	 * It is in the HDMI power domain.
188962306a36Sopenharmony_ci	 */
189062306a36Sopenharmony_ci	[BCM2835_PLLH]		= REGISTER_PLL(
189162306a36Sopenharmony_ci		SOC_BCM2835,
189262306a36Sopenharmony_ci		"pllh",
189362306a36Sopenharmony_ci		.cm_ctrl_reg = CM_PLLH,
189462306a36Sopenharmony_ci		.a2w_ctrl_reg = A2W_PLLH_CTRL,
189562306a36Sopenharmony_ci		.frac_reg = A2W_PLLH_FRAC,
189662306a36Sopenharmony_ci		.ana_reg_base = A2W_PLLH_ANA0,
189762306a36Sopenharmony_ci		.reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE,
189862306a36Sopenharmony_ci		.lock_mask = CM_LOCK_FLOCKH,
189962306a36Sopenharmony_ci
190062306a36Sopenharmony_ci		.ana = &bcm2835_ana_pllh,
190162306a36Sopenharmony_ci
190262306a36Sopenharmony_ci		.min_rate = 600000000u,
190362306a36Sopenharmony_ci		.max_rate = 3000000000u,
190462306a36Sopenharmony_ci		.max_fb_rate = BCM2835_MAX_FB_RATE),
190562306a36Sopenharmony_ci	[BCM2835_PLLH_RCAL]	= REGISTER_PLL_DIV(
190662306a36Sopenharmony_ci		SOC_BCM2835,
190762306a36Sopenharmony_ci		.name = "pllh_rcal",
190862306a36Sopenharmony_ci		.source_pll = "pllh",
190962306a36Sopenharmony_ci		.cm_reg = CM_PLLH,
191062306a36Sopenharmony_ci		.a2w_reg = A2W_PLLH_RCAL,
191162306a36Sopenharmony_ci		.load_mask = CM_PLLH_LOADRCAL,
191262306a36Sopenharmony_ci		.hold_mask = 0,
191362306a36Sopenharmony_ci		.fixed_divider = 10,
191462306a36Sopenharmony_ci		.flags = CLK_SET_RATE_PARENT),
191562306a36Sopenharmony_ci	[BCM2835_PLLH_AUX]	= REGISTER_PLL_DIV(
191662306a36Sopenharmony_ci		SOC_BCM2835,
191762306a36Sopenharmony_ci		.name = "pllh_aux",
191862306a36Sopenharmony_ci		.source_pll = "pllh",
191962306a36Sopenharmony_ci		.cm_reg = CM_PLLH,
192062306a36Sopenharmony_ci		.a2w_reg = A2W_PLLH_AUX,
192162306a36Sopenharmony_ci		.load_mask = CM_PLLH_LOADAUX,
192262306a36Sopenharmony_ci		.hold_mask = 0,
192362306a36Sopenharmony_ci		.fixed_divider = 1,
192462306a36Sopenharmony_ci		.flags = CLK_SET_RATE_PARENT),
192562306a36Sopenharmony_ci	[BCM2835_PLLH_PIX]	= REGISTER_PLL_DIV(
192662306a36Sopenharmony_ci		SOC_BCM2835,
192762306a36Sopenharmony_ci		.name = "pllh_pix",
192862306a36Sopenharmony_ci		.source_pll = "pllh",
192962306a36Sopenharmony_ci		.cm_reg = CM_PLLH,
193062306a36Sopenharmony_ci		.a2w_reg = A2W_PLLH_PIX,
193162306a36Sopenharmony_ci		.load_mask = CM_PLLH_LOADPIX,
193262306a36Sopenharmony_ci		.hold_mask = 0,
193362306a36Sopenharmony_ci		.fixed_divider = 10,
193462306a36Sopenharmony_ci		.flags = CLK_SET_RATE_PARENT),
193562306a36Sopenharmony_ci
193662306a36Sopenharmony_ci	/* the clocks */
193762306a36Sopenharmony_ci
193862306a36Sopenharmony_ci	/* clocks with oscillator parent mux */
193962306a36Sopenharmony_ci
194062306a36Sopenharmony_ci	/* One Time Programmable Memory clock.  Maximum 10Mhz. */
194162306a36Sopenharmony_ci	[BCM2835_CLOCK_OTP]	= REGISTER_OSC_CLK(
194262306a36Sopenharmony_ci		SOC_ALL,
194362306a36Sopenharmony_ci		.name = "otp",
194462306a36Sopenharmony_ci		.ctl_reg = CM_OTPCTL,
194562306a36Sopenharmony_ci		.div_reg = CM_OTPDIV,
194662306a36Sopenharmony_ci		.int_bits = 4,
194762306a36Sopenharmony_ci		.frac_bits = 0,
194862306a36Sopenharmony_ci		.tcnt_mux = 6),
194962306a36Sopenharmony_ci	/*
195062306a36Sopenharmony_ci	 * Used for a 1Mhz clock for the system clocksource, and also used
195162306a36Sopenharmony_ci	 * bythe watchdog timer and the camera pulse generator.
195262306a36Sopenharmony_ci	 */
195362306a36Sopenharmony_ci	[BCM2835_CLOCK_TIMER]	= REGISTER_OSC_CLK(
195462306a36Sopenharmony_ci		SOC_ALL,
195562306a36Sopenharmony_ci		.name = "timer",
195662306a36Sopenharmony_ci		.ctl_reg = CM_TIMERCTL,
195762306a36Sopenharmony_ci		.div_reg = CM_TIMERDIV,
195862306a36Sopenharmony_ci		.int_bits = 6,
195962306a36Sopenharmony_ci		.frac_bits = 12),
196062306a36Sopenharmony_ci	/*
196162306a36Sopenharmony_ci	 * Clock for the temperature sensor.
196262306a36Sopenharmony_ci	 * Generally run at 2Mhz, max 5Mhz.
196362306a36Sopenharmony_ci	 */
196462306a36Sopenharmony_ci	[BCM2835_CLOCK_TSENS]	= REGISTER_OSC_CLK(
196562306a36Sopenharmony_ci		SOC_ALL,
196662306a36Sopenharmony_ci		.name = "tsens",
196762306a36Sopenharmony_ci		.ctl_reg = CM_TSENSCTL,
196862306a36Sopenharmony_ci		.div_reg = CM_TSENSDIV,
196962306a36Sopenharmony_ci		.int_bits = 5,
197062306a36Sopenharmony_ci		.frac_bits = 0),
197162306a36Sopenharmony_ci	[BCM2835_CLOCK_TEC]	= REGISTER_OSC_CLK(
197262306a36Sopenharmony_ci		SOC_ALL,
197362306a36Sopenharmony_ci		.name = "tec",
197462306a36Sopenharmony_ci		.ctl_reg = CM_TECCTL,
197562306a36Sopenharmony_ci		.div_reg = CM_TECDIV,
197662306a36Sopenharmony_ci		.int_bits = 6,
197762306a36Sopenharmony_ci		.frac_bits = 0),
197862306a36Sopenharmony_ci
197962306a36Sopenharmony_ci	/* clocks with vpu parent mux */
198062306a36Sopenharmony_ci	[BCM2835_CLOCK_H264]	= REGISTER_VPU_CLK(
198162306a36Sopenharmony_ci		SOC_ALL,
198262306a36Sopenharmony_ci		.name = "h264",
198362306a36Sopenharmony_ci		.ctl_reg = CM_H264CTL,
198462306a36Sopenharmony_ci		.div_reg = CM_H264DIV,
198562306a36Sopenharmony_ci		.int_bits = 4,
198662306a36Sopenharmony_ci		.frac_bits = 8,
198762306a36Sopenharmony_ci		.tcnt_mux = 1),
198862306a36Sopenharmony_ci	[BCM2835_CLOCK_ISP]	= REGISTER_VPU_CLK(
198962306a36Sopenharmony_ci		SOC_ALL,
199062306a36Sopenharmony_ci		.name = "isp",
199162306a36Sopenharmony_ci		.ctl_reg = CM_ISPCTL,
199262306a36Sopenharmony_ci		.div_reg = CM_ISPDIV,
199362306a36Sopenharmony_ci		.int_bits = 4,
199462306a36Sopenharmony_ci		.frac_bits = 8,
199562306a36Sopenharmony_ci		.tcnt_mux = 2),
199662306a36Sopenharmony_ci
199762306a36Sopenharmony_ci	/*
199862306a36Sopenharmony_ci	 * Secondary SDRAM clock.  Used for low-voltage modes when the PLL
199962306a36Sopenharmony_ci	 * in the SDRAM controller can't be used.
200062306a36Sopenharmony_ci	 */
200162306a36Sopenharmony_ci	[BCM2835_CLOCK_SDRAM]	= REGISTER_VPU_CLK(
200262306a36Sopenharmony_ci		SOC_ALL,
200362306a36Sopenharmony_ci		.name = "sdram",
200462306a36Sopenharmony_ci		.ctl_reg = CM_SDCCTL,
200562306a36Sopenharmony_ci		.div_reg = CM_SDCDIV,
200662306a36Sopenharmony_ci		.int_bits = 6,
200762306a36Sopenharmony_ci		.frac_bits = 0,
200862306a36Sopenharmony_ci		.tcnt_mux = 3),
200962306a36Sopenharmony_ci	[BCM2835_CLOCK_V3D]	= REGISTER_VPU_CLK(
201062306a36Sopenharmony_ci		SOC_ALL,
201162306a36Sopenharmony_ci		.name = "v3d",
201262306a36Sopenharmony_ci		.ctl_reg = CM_V3DCTL,
201362306a36Sopenharmony_ci		.div_reg = CM_V3DDIV,
201462306a36Sopenharmony_ci		.int_bits = 4,
201562306a36Sopenharmony_ci		.frac_bits = 8,
201662306a36Sopenharmony_ci		.tcnt_mux = 4),
201762306a36Sopenharmony_ci	/*
201862306a36Sopenharmony_ci	 * VPU clock.  This doesn't have an enable bit, since it drives
201962306a36Sopenharmony_ci	 * the bus for everything else, and is special so it doesn't need
202062306a36Sopenharmony_ci	 * to be gated for rate changes.  It is also known as "clk_audio"
202162306a36Sopenharmony_ci	 * in various hardware documentation.
202262306a36Sopenharmony_ci	 */
202362306a36Sopenharmony_ci	[BCM2835_CLOCK_VPU]	= REGISTER_VPU_CLK(
202462306a36Sopenharmony_ci		SOC_ALL,
202562306a36Sopenharmony_ci		.name = "vpu",
202662306a36Sopenharmony_ci		.ctl_reg = CM_VPUCTL,
202762306a36Sopenharmony_ci		.div_reg = CM_VPUDIV,
202862306a36Sopenharmony_ci		.int_bits = 12,
202962306a36Sopenharmony_ci		.frac_bits = 8,
203062306a36Sopenharmony_ci		.flags = CLK_IS_CRITICAL,
203162306a36Sopenharmony_ci		.is_vpu_clock = true,
203262306a36Sopenharmony_ci		.tcnt_mux = 5),
203362306a36Sopenharmony_ci
203462306a36Sopenharmony_ci	/* clocks with per parent mux */
203562306a36Sopenharmony_ci	[BCM2835_CLOCK_AVEO]	= REGISTER_PER_CLK(
203662306a36Sopenharmony_ci		SOC_ALL,
203762306a36Sopenharmony_ci		.name = "aveo",
203862306a36Sopenharmony_ci		.ctl_reg = CM_AVEOCTL,
203962306a36Sopenharmony_ci		.div_reg = CM_AVEODIV,
204062306a36Sopenharmony_ci		.int_bits = 4,
204162306a36Sopenharmony_ci		.frac_bits = 0,
204262306a36Sopenharmony_ci		.tcnt_mux = 38),
204362306a36Sopenharmony_ci	[BCM2835_CLOCK_CAM0]	= REGISTER_PER_CLK(
204462306a36Sopenharmony_ci		SOC_ALL,
204562306a36Sopenharmony_ci		.name = "cam0",
204662306a36Sopenharmony_ci		.ctl_reg = CM_CAM0CTL,
204762306a36Sopenharmony_ci		.div_reg = CM_CAM0DIV,
204862306a36Sopenharmony_ci		.int_bits = 4,
204962306a36Sopenharmony_ci		.frac_bits = 8,
205062306a36Sopenharmony_ci		.tcnt_mux = 14),
205162306a36Sopenharmony_ci	[BCM2835_CLOCK_CAM1]	= REGISTER_PER_CLK(
205262306a36Sopenharmony_ci		SOC_ALL,
205362306a36Sopenharmony_ci		.name = "cam1",
205462306a36Sopenharmony_ci		.ctl_reg = CM_CAM1CTL,
205562306a36Sopenharmony_ci		.div_reg = CM_CAM1DIV,
205662306a36Sopenharmony_ci		.int_bits = 4,
205762306a36Sopenharmony_ci		.frac_bits = 8,
205862306a36Sopenharmony_ci		.tcnt_mux = 15),
205962306a36Sopenharmony_ci	[BCM2835_CLOCK_DFT]	= REGISTER_PER_CLK(
206062306a36Sopenharmony_ci		SOC_ALL,
206162306a36Sopenharmony_ci		.name = "dft",
206262306a36Sopenharmony_ci		.ctl_reg = CM_DFTCTL,
206362306a36Sopenharmony_ci		.div_reg = CM_DFTDIV,
206462306a36Sopenharmony_ci		.int_bits = 5,
206562306a36Sopenharmony_ci		.frac_bits = 0),
206662306a36Sopenharmony_ci	[BCM2835_CLOCK_DPI]	= REGISTER_PER_CLK(
206762306a36Sopenharmony_ci		SOC_ALL,
206862306a36Sopenharmony_ci		.name = "dpi",
206962306a36Sopenharmony_ci		.ctl_reg = CM_DPICTL,
207062306a36Sopenharmony_ci		.div_reg = CM_DPIDIV,
207162306a36Sopenharmony_ci		.int_bits = 4,
207262306a36Sopenharmony_ci		.frac_bits = 8,
207362306a36Sopenharmony_ci		.tcnt_mux = 17),
207462306a36Sopenharmony_ci
207562306a36Sopenharmony_ci	/* Arasan EMMC clock */
207662306a36Sopenharmony_ci	[BCM2835_CLOCK_EMMC]	= REGISTER_PER_CLK(
207762306a36Sopenharmony_ci		SOC_ALL,
207862306a36Sopenharmony_ci		.name = "emmc",
207962306a36Sopenharmony_ci		.ctl_reg = CM_EMMCCTL,
208062306a36Sopenharmony_ci		.div_reg = CM_EMMCDIV,
208162306a36Sopenharmony_ci		.int_bits = 4,
208262306a36Sopenharmony_ci		.frac_bits = 8,
208362306a36Sopenharmony_ci		.tcnt_mux = 39),
208462306a36Sopenharmony_ci
208562306a36Sopenharmony_ci	/* EMMC2 clock (only available for BCM2711) */
208662306a36Sopenharmony_ci	[BCM2711_CLOCK_EMMC2]	= REGISTER_PER_CLK(
208762306a36Sopenharmony_ci		SOC_BCM2711,
208862306a36Sopenharmony_ci		.name = "emmc2",
208962306a36Sopenharmony_ci		.ctl_reg = CM_EMMC2CTL,
209062306a36Sopenharmony_ci		.div_reg = CM_EMMC2DIV,
209162306a36Sopenharmony_ci		.int_bits = 4,
209262306a36Sopenharmony_ci		.frac_bits = 8,
209362306a36Sopenharmony_ci		.tcnt_mux = 42),
209462306a36Sopenharmony_ci
209562306a36Sopenharmony_ci	/* General purpose (GPIO) clocks */
209662306a36Sopenharmony_ci	[BCM2835_CLOCK_GP0]	= REGISTER_PER_CLK(
209762306a36Sopenharmony_ci		SOC_ALL,
209862306a36Sopenharmony_ci		.name = "gp0",
209962306a36Sopenharmony_ci		.ctl_reg = CM_GP0CTL,
210062306a36Sopenharmony_ci		.div_reg = CM_GP0DIV,
210162306a36Sopenharmony_ci		.int_bits = 12,
210262306a36Sopenharmony_ci		.frac_bits = 12,
210362306a36Sopenharmony_ci		.is_mash_clock = true,
210462306a36Sopenharmony_ci		.tcnt_mux = 20),
210562306a36Sopenharmony_ci	[BCM2835_CLOCK_GP1]	= REGISTER_PER_CLK(
210662306a36Sopenharmony_ci		SOC_ALL,
210762306a36Sopenharmony_ci		.name = "gp1",
210862306a36Sopenharmony_ci		.ctl_reg = CM_GP1CTL,
210962306a36Sopenharmony_ci		.div_reg = CM_GP1DIV,
211062306a36Sopenharmony_ci		.int_bits = 12,
211162306a36Sopenharmony_ci		.frac_bits = 12,
211262306a36Sopenharmony_ci		.flags = CLK_IS_CRITICAL,
211362306a36Sopenharmony_ci		.is_mash_clock = true,
211462306a36Sopenharmony_ci		.tcnt_mux = 21),
211562306a36Sopenharmony_ci	[BCM2835_CLOCK_GP2]	= REGISTER_PER_CLK(
211662306a36Sopenharmony_ci		SOC_ALL,
211762306a36Sopenharmony_ci		.name = "gp2",
211862306a36Sopenharmony_ci		.ctl_reg = CM_GP2CTL,
211962306a36Sopenharmony_ci		.div_reg = CM_GP2DIV,
212062306a36Sopenharmony_ci		.int_bits = 12,
212162306a36Sopenharmony_ci		.frac_bits = 12,
212262306a36Sopenharmony_ci		.flags = CLK_IS_CRITICAL),
212362306a36Sopenharmony_ci
212462306a36Sopenharmony_ci	/* HDMI state machine */
212562306a36Sopenharmony_ci	[BCM2835_CLOCK_HSM]	= REGISTER_PER_CLK(
212662306a36Sopenharmony_ci		SOC_ALL,
212762306a36Sopenharmony_ci		.name = "hsm",
212862306a36Sopenharmony_ci		.ctl_reg = CM_HSMCTL,
212962306a36Sopenharmony_ci		.div_reg = CM_HSMDIV,
213062306a36Sopenharmony_ci		.int_bits = 4,
213162306a36Sopenharmony_ci		.frac_bits = 8,
213262306a36Sopenharmony_ci		.tcnt_mux = 22),
213362306a36Sopenharmony_ci	[BCM2835_CLOCK_PCM]	= REGISTER_PCM_CLK(
213462306a36Sopenharmony_ci		SOC_ALL,
213562306a36Sopenharmony_ci		.name = "pcm",
213662306a36Sopenharmony_ci		.ctl_reg = CM_PCMCTL,
213762306a36Sopenharmony_ci		.div_reg = CM_PCMDIV,
213862306a36Sopenharmony_ci		.int_bits = 12,
213962306a36Sopenharmony_ci		.frac_bits = 12,
214062306a36Sopenharmony_ci		.is_mash_clock = true,
214162306a36Sopenharmony_ci		.low_jitter = true,
214262306a36Sopenharmony_ci		.tcnt_mux = 23),
214362306a36Sopenharmony_ci	[BCM2835_CLOCK_PWM]	= REGISTER_PER_CLK(
214462306a36Sopenharmony_ci		SOC_ALL,
214562306a36Sopenharmony_ci		.name = "pwm",
214662306a36Sopenharmony_ci		.ctl_reg = CM_PWMCTL,
214762306a36Sopenharmony_ci		.div_reg = CM_PWMDIV,
214862306a36Sopenharmony_ci		.int_bits = 12,
214962306a36Sopenharmony_ci		.frac_bits = 12,
215062306a36Sopenharmony_ci		.is_mash_clock = true,
215162306a36Sopenharmony_ci		.tcnt_mux = 24),
215262306a36Sopenharmony_ci	[BCM2835_CLOCK_SLIM]	= REGISTER_PER_CLK(
215362306a36Sopenharmony_ci		SOC_ALL,
215462306a36Sopenharmony_ci		.name = "slim",
215562306a36Sopenharmony_ci		.ctl_reg = CM_SLIMCTL,
215662306a36Sopenharmony_ci		.div_reg = CM_SLIMDIV,
215762306a36Sopenharmony_ci		.int_bits = 12,
215862306a36Sopenharmony_ci		.frac_bits = 12,
215962306a36Sopenharmony_ci		.is_mash_clock = true,
216062306a36Sopenharmony_ci		.tcnt_mux = 25),
216162306a36Sopenharmony_ci	[BCM2835_CLOCK_SMI]	= REGISTER_PER_CLK(
216262306a36Sopenharmony_ci		SOC_ALL,
216362306a36Sopenharmony_ci		.name = "smi",
216462306a36Sopenharmony_ci		.ctl_reg = CM_SMICTL,
216562306a36Sopenharmony_ci		.div_reg = CM_SMIDIV,
216662306a36Sopenharmony_ci		.int_bits = 4,
216762306a36Sopenharmony_ci		.frac_bits = 8,
216862306a36Sopenharmony_ci		.tcnt_mux = 27),
216962306a36Sopenharmony_ci	[BCM2835_CLOCK_UART]	= REGISTER_PER_CLK(
217062306a36Sopenharmony_ci		SOC_ALL,
217162306a36Sopenharmony_ci		.name = "uart",
217262306a36Sopenharmony_ci		.ctl_reg = CM_UARTCTL,
217362306a36Sopenharmony_ci		.div_reg = CM_UARTDIV,
217462306a36Sopenharmony_ci		.int_bits = 10,
217562306a36Sopenharmony_ci		.frac_bits = 12,
217662306a36Sopenharmony_ci		.tcnt_mux = 28,
217762306a36Sopenharmony_ci		.round_up = true),
217862306a36Sopenharmony_ci
217962306a36Sopenharmony_ci	/* TV encoder clock.  Only operating frequency is 108Mhz.  */
218062306a36Sopenharmony_ci	[BCM2835_CLOCK_VEC]	= REGISTER_PER_CLK(
218162306a36Sopenharmony_ci		SOC_ALL,
218262306a36Sopenharmony_ci		.name = "vec",
218362306a36Sopenharmony_ci		.ctl_reg = CM_VECCTL,
218462306a36Sopenharmony_ci		.div_reg = CM_VECDIV,
218562306a36Sopenharmony_ci		.int_bits = 4,
218662306a36Sopenharmony_ci		.frac_bits = 0,
218762306a36Sopenharmony_ci		/*
218862306a36Sopenharmony_ci		 * Allow rate change propagation only on PLLH_AUX which is
218962306a36Sopenharmony_ci		 * assigned index 7 in the parent array.
219062306a36Sopenharmony_ci		 */
219162306a36Sopenharmony_ci		.set_rate_parent = BIT(7),
219262306a36Sopenharmony_ci		.tcnt_mux = 29),
219362306a36Sopenharmony_ci
219462306a36Sopenharmony_ci	/* dsi clocks */
219562306a36Sopenharmony_ci	[BCM2835_CLOCK_DSI0E]	= REGISTER_PER_CLK(
219662306a36Sopenharmony_ci		SOC_ALL,
219762306a36Sopenharmony_ci		.name = "dsi0e",
219862306a36Sopenharmony_ci		.ctl_reg = CM_DSI0ECTL,
219962306a36Sopenharmony_ci		.div_reg = CM_DSI0EDIV,
220062306a36Sopenharmony_ci		.int_bits = 4,
220162306a36Sopenharmony_ci		.frac_bits = 8,
220262306a36Sopenharmony_ci		.tcnt_mux = 18),
220362306a36Sopenharmony_ci	[BCM2835_CLOCK_DSI1E]	= REGISTER_PER_CLK(
220462306a36Sopenharmony_ci		SOC_ALL,
220562306a36Sopenharmony_ci		.name = "dsi1e",
220662306a36Sopenharmony_ci		.ctl_reg = CM_DSI1ECTL,
220762306a36Sopenharmony_ci		.div_reg = CM_DSI1EDIV,
220862306a36Sopenharmony_ci		.int_bits = 4,
220962306a36Sopenharmony_ci		.frac_bits = 8,
221062306a36Sopenharmony_ci		.tcnt_mux = 19),
221162306a36Sopenharmony_ci	[BCM2835_CLOCK_DSI0P]	= REGISTER_DSI0_CLK(
221262306a36Sopenharmony_ci		SOC_ALL,
221362306a36Sopenharmony_ci		.name = "dsi0p",
221462306a36Sopenharmony_ci		.ctl_reg = CM_DSI0PCTL,
221562306a36Sopenharmony_ci		.div_reg = CM_DSI0PDIV,
221662306a36Sopenharmony_ci		.int_bits = 0,
221762306a36Sopenharmony_ci		.frac_bits = 0,
221862306a36Sopenharmony_ci		.tcnt_mux = 12),
221962306a36Sopenharmony_ci	[BCM2835_CLOCK_DSI1P]	= REGISTER_DSI1_CLK(
222062306a36Sopenharmony_ci		SOC_ALL,
222162306a36Sopenharmony_ci		.name = "dsi1p",
222262306a36Sopenharmony_ci		.ctl_reg = CM_DSI1PCTL,
222362306a36Sopenharmony_ci		.div_reg = CM_DSI1PDIV,
222462306a36Sopenharmony_ci		.int_bits = 0,
222562306a36Sopenharmony_ci		.frac_bits = 0,
222662306a36Sopenharmony_ci		.tcnt_mux = 13),
222762306a36Sopenharmony_ci
222862306a36Sopenharmony_ci	/* the gates */
222962306a36Sopenharmony_ci
223062306a36Sopenharmony_ci	/*
223162306a36Sopenharmony_ci	 * CM_PERIICTL (and CM_PERIACTL, CM_SYSCTL and CM_VPUCTL if
223262306a36Sopenharmony_ci	 * you have the debug bit set in the power manager, which we
223362306a36Sopenharmony_ci	 * don't bother exposing) are individual gates off of the
223462306a36Sopenharmony_ci	 * non-stop vpu clock.
223562306a36Sopenharmony_ci	 */
223662306a36Sopenharmony_ci	[BCM2835_CLOCK_PERI_IMAGE] = REGISTER_GATE(
223762306a36Sopenharmony_ci		SOC_ALL,
223862306a36Sopenharmony_ci		.name = "peri_image",
223962306a36Sopenharmony_ci		.parent = "vpu",
224062306a36Sopenharmony_ci		.ctl_reg = CM_PERIICTL),
224162306a36Sopenharmony_ci};
224262306a36Sopenharmony_ci
224362306a36Sopenharmony_ci/*
224462306a36Sopenharmony_ci * Permanently take a reference on the parent of the SDRAM clock.
224562306a36Sopenharmony_ci *
224662306a36Sopenharmony_ci * While the SDRAM is being driven by its dedicated PLL most of the
224762306a36Sopenharmony_ci * time, there is a little loop running in the firmware that
224862306a36Sopenharmony_ci * periodically switches the SDRAM to using our CM clock to do PVT
224962306a36Sopenharmony_ci * recalibration, with the assumption that the previously configured
225062306a36Sopenharmony_ci * SDRAM parent is still enabled and running.
225162306a36Sopenharmony_ci */
225262306a36Sopenharmony_cistatic int bcm2835_mark_sdc_parent_critical(struct clk *sdc)
225362306a36Sopenharmony_ci{
225462306a36Sopenharmony_ci	struct clk *parent = clk_get_parent(sdc);
225562306a36Sopenharmony_ci
225662306a36Sopenharmony_ci	if (IS_ERR(parent))
225762306a36Sopenharmony_ci		return PTR_ERR(parent);
225862306a36Sopenharmony_ci
225962306a36Sopenharmony_ci	return clk_prepare_enable(parent);
226062306a36Sopenharmony_ci}
226162306a36Sopenharmony_ci
226262306a36Sopenharmony_cistatic int bcm2835_clk_probe(struct platform_device *pdev)
226362306a36Sopenharmony_ci{
226462306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
226562306a36Sopenharmony_ci	struct clk_hw **hws;
226662306a36Sopenharmony_ci	struct bcm2835_cprman *cprman;
226762306a36Sopenharmony_ci	const struct bcm2835_clk_desc *desc;
226862306a36Sopenharmony_ci	const size_t asize = ARRAY_SIZE(clk_desc_array);
226962306a36Sopenharmony_ci	const struct cprman_plat_data *pdata;
227062306a36Sopenharmony_ci	size_t i;
227162306a36Sopenharmony_ci	int ret;
227262306a36Sopenharmony_ci
227362306a36Sopenharmony_ci	pdata = of_device_get_match_data(&pdev->dev);
227462306a36Sopenharmony_ci	if (!pdata)
227562306a36Sopenharmony_ci		return -ENODEV;
227662306a36Sopenharmony_ci
227762306a36Sopenharmony_ci	cprman = devm_kzalloc(dev,
227862306a36Sopenharmony_ci			      struct_size(cprman, onecell.hws, asize),
227962306a36Sopenharmony_ci			      GFP_KERNEL);
228062306a36Sopenharmony_ci	if (!cprman)
228162306a36Sopenharmony_ci		return -ENOMEM;
228262306a36Sopenharmony_ci
228362306a36Sopenharmony_ci	spin_lock_init(&cprman->regs_lock);
228462306a36Sopenharmony_ci	cprman->dev = dev;
228562306a36Sopenharmony_ci	cprman->regs = devm_platform_ioremap_resource(pdev, 0);
228662306a36Sopenharmony_ci	if (IS_ERR(cprman->regs))
228762306a36Sopenharmony_ci		return PTR_ERR(cprman->regs);
228862306a36Sopenharmony_ci
228962306a36Sopenharmony_ci	memcpy(cprman->real_parent_names, cprman_parent_names,
229062306a36Sopenharmony_ci	       sizeof(cprman_parent_names));
229162306a36Sopenharmony_ci	of_clk_parent_fill(dev->of_node, cprman->real_parent_names,
229262306a36Sopenharmony_ci			   ARRAY_SIZE(cprman_parent_names));
229362306a36Sopenharmony_ci
229462306a36Sopenharmony_ci	/*
229562306a36Sopenharmony_ci	 * Make sure the external oscillator has been registered.
229662306a36Sopenharmony_ci	 *
229762306a36Sopenharmony_ci	 * The other (DSI) clocks are not present on older device
229862306a36Sopenharmony_ci	 * trees, which we still need to support for backwards
229962306a36Sopenharmony_ci	 * compatibility.
230062306a36Sopenharmony_ci	 */
230162306a36Sopenharmony_ci	if (!cprman->real_parent_names[0])
230262306a36Sopenharmony_ci		return -ENODEV;
230362306a36Sopenharmony_ci
230462306a36Sopenharmony_ci	platform_set_drvdata(pdev, cprman);
230562306a36Sopenharmony_ci
230662306a36Sopenharmony_ci	cprman->onecell.num = asize;
230762306a36Sopenharmony_ci	cprman->soc = pdata->soc;
230862306a36Sopenharmony_ci	hws = cprman->onecell.hws;
230962306a36Sopenharmony_ci
231062306a36Sopenharmony_ci	for (i = 0; i < asize; i++) {
231162306a36Sopenharmony_ci		desc = &clk_desc_array[i];
231262306a36Sopenharmony_ci		if (desc->clk_register && desc->data &&
231362306a36Sopenharmony_ci		    (desc->supported & pdata->soc)) {
231462306a36Sopenharmony_ci			hws[i] = desc->clk_register(cprman, desc->data);
231562306a36Sopenharmony_ci		}
231662306a36Sopenharmony_ci	}
231762306a36Sopenharmony_ci
231862306a36Sopenharmony_ci	ret = bcm2835_mark_sdc_parent_critical(hws[BCM2835_CLOCK_SDRAM]->clk);
231962306a36Sopenharmony_ci	if (ret)
232062306a36Sopenharmony_ci		return ret;
232162306a36Sopenharmony_ci
232262306a36Sopenharmony_ci	return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
232362306a36Sopenharmony_ci				      &cprman->onecell);
232462306a36Sopenharmony_ci}
232562306a36Sopenharmony_ci
232662306a36Sopenharmony_cistatic const struct cprman_plat_data cprman_bcm2835_plat_data = {
232762306a36Sopenharmony_ci	.soc = SOC_BCM2835,
232862306a36Sopenharmony_ci};
232962306a36Sopenharmony_ci
233062306a36Sopenharmony_cistatic const struct cprman_plat_data cprman_bcm2711_plat_data = {
233162306a36Sopenharmony_ci	.soc = SOC_BCM2711,
233262306a36Sopenharmony_ci};
233362306a36Sopenharmony_ci
233462306a36Sopenharmony_cistatic const struct of_device_id bcm2835_clk_of_match[] = {
233562306a36Sopenharmony_ci	{ .compatible = "brcm,bcm2835-cprman", .data = &cprman_bcm2835_plat_data },
233662306a36Sopenharmony_ci	{ .compatible = "brcm,bcm2711-cprman", .data = &cprman_bcm2711_plat_data },
233762306a36Sopenharmony_ci	{}
233862306a36Sopenharmony_ci};
233962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, bcm2835_clk_of_match);
234062306a36Sopenharmony_ci
234162306a36Sopenharmony_cistatic struct platform_driver bcm2835_clk_driver = {
234262306a36Sopenharmony_ci	.driver = {
234362306a36Sopenharmony_ci		.name = "bcm2835-clk",
234462306a36Sopenharmony_ci		.of_match_table = bcm2835_clk_of_match,
234562306a36Sopenharmony_ci	},
234662306a36Sopenharmony_ci	.probe          = bcm2835_clk_probe,
234762306a36Sopenharmony_ci};
234862306a36Sopenharmony_ci
234962306a36Sopenharmony_cibuiltin_platform_driver(bcm2835_clk_driver);
235062306a36Sopenharmony_ci
235162306a36Sopenharmony_ciMODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
235262306a36Sopenharmony_ciMODULE_DESCRIPTION("BCM2835 clock driver");
2353