summaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/Kconfig68
-rw-r--r--drivers/clk/Makefile15
-rw-r--r--drivers/clk/analogbits/Makefile3
-rw-r--r--drivers/clk/analogbits/wrpll-cln28hpc.c367
-rw-r--r--drivers/clk/at91/Makefile7
-rw-r--r--drivers/clk/at91/at91rm9200.c218
-rw-r--r--drivers/clk/at91/at91sam9260.c83
-rw-r--r--drivers/clk/at91/at91sam9g45.c237
-rw-r--r--drivers/clk/at91/at91sam9n12.c264
-rw-r--r--drivers/clk/at91/at91sam9rl.c59
-rw-r--r--drivers/clk/at91/at91sam9x5.c96
-rw-r--r--drivers/clk/at91/clk-audio-pll.c148
-rw-r--r--drivers/clk/at91/clk-generated.c118
-rw-r--r--drivers/clk/at91/clk-h32mx.c38
-rw-r--r--drivers/clk/at91/clk-i2s-mux.c46
-rw-r--r--drivers/clk/at91/clk-main.c285
-rw-r--r--drivers/clk/at91/clk-master.c433
-rw-r--r--drivers/clk/at91/clk-peripheral.c197
-rw-r--r--drivers/clk/at91/clk-pll.c90
-rw-r--r--drivers/clk/at91/clk-plldiv.c64
-rw-r--r--drivers/clk/at91/clk-programmable.c78
-rw-r--r--drivers/clk/at91/clk-sam9x60-pll.c731
-rw-r--r--drivers/clk/at91/clk-slow.c48
-rw-r--r--drivers/clk/at91/clk-smd.c75
-rw-r--r--drivers/clk/at91/clk-system.c72
-rw-r--r--drivers/clk/at91/clk-usb.c187
-rw-r--r--drivers/clk/at91/clk-utmi.c190
-rw-r--r--drivers/clk/at91/dt-compat.c727
-rw-r--r--drivers/clk/at91/pmc.c223
-rw-r--r--drivers/clk/at91/pmc.h170
-rw-r--r--drivers/clk/at91/sam9x60.c169
-rw-r--r--drivers/clk/at91/sama5d2.c151
-rw-r--r--drivers/clk/at91/sama5d3.c270
-rw-r--r--drivers/clk/at91/sama5d4.c98
-rw-r--r--drivers/clk/at91/sama7g5.c1133
-rw-r--r--drivers/clk/at91/sckc.c280
-rw-r--r--drivers/clk/bcm/Makefile2
-rw-r--r--drivers/clk/bcm/clk-bcm2835-aux.c67
-rw-r--r--drivers/clk/clk-ar933x.c31
-rw-r--r--drivers/clk/clk-ar9344.c31
-rw-r--r--drivers/clk/clk-bulk.c108
-rw-r--r--drivers/clk/clk-composite.c145
-rw-r--r--drivers/clk/clk-conf.c16
-rw-r--r--drivers/clk/clk-divider.c164
-rw-r--r--drivers/clk/clk-fixed-factor.c57
-rw-r--r--drivers/clk/clk-fixed.c32
-rw-r--r--drivers/clk/clk-fractional-divider.c131
-rw-r--r--drivers/clk/clk-gate-shared.c33
-rw-r--r--drivers/clk/clk-gate.c52
-rw-r--r--drivers/clk/clk-gpio.c53
-rw-r--r--drivers/clk/clk-mux.c215
-rw-r--r--drivers/clk/clk-qoric.c132
-rw-r--r--drivers/clk/clk-rpi.c106
-rw-r--r--drivers/clk/clk-scmi.c245
-rw-r--r--drivers/clk/clk-stm32f4.c1907
-rw-r--r--drivers/clk/clk-stm32mp1.c947
-rw-r--r--drivers/clk/clk.c556
-rw-r--r--drivers/clk/clkdev.c16
-rw-r--r--drivers/clk/imx/Makefile5
-rw-r--r--drivers/clk/imx/clk-composite-8m.c73
-rw-r--r--drivers/clk/imx/clk-composite-93.c216
-rw-r--r--drivers/clk/imx/clk-cpu.c32
-rw-r--r--drivers/clk/imx/clk-frac-pll.c42
-rw-r--r--drivers/clk/imx/clk-fracn-gppll.c297
-rw-r--r--drivers/clk/imx/clk-gate-93.c186
-rw-r--r--drivers/clk/imx/clk-gate-exclusive.c36
-rw-r--r--drivers/clk/imx/clk-gate2.c45
-rw-r--r--drivers/clk/imx/clk-imx1.c13
-rw-r--r--drivers/clk/imx/clk-imx21.c13
-rw-r--r--drivers/clk/imx/clk-imx25.c55
-rw-r--r--drivers/clk/imx/clk-imx27.c17
-rw-r--r--drivers/clk/imx/clk-imx31.c13
-rw-r--r--drivers/clk/imx/clk-imx35.c13
-rw-r--r--drivers/clk/imx/clk-imx5.c64
-rw-r--r--drivers/clk/imx/clk-imx6.c66
-rw-r--r--drivers/clk/imx/clk-imx6sl.c20
-rw-r--r--drivers/clk/imx/clk-imx6sx.c20
-rw-r--r--drivers/clk/imx/clk-imx6ul.c23
-rw-r--r--drivers/clk/imx/clk-imx7.c48
-rw-r--r--drivers/clk/imx/clk-imx8mm.c80
-rw-r--r--drivers/clk/imx/clk-imx8mn.c559
-rw-r--r--drivers/clk/imx/clk-imx8mp.c708
-rw-r--r--drivers/clk/imx/clk-imx8mq.c7
-rw-r--r--drivers/clk/imx/clk-imx93.c331
-rw-r--r--drivers/clk/imx/clk-pfd.c36
-rw-r--r--drivers/clk/imx/clk-pll14xx.c54
-rw-r--r--drivers/clk/imx/clk-pllv1.c31
-rw-r--r--drivers/clk/imx/clk-pllv2.c26
-rw-r--r--drivers/clk/imx/clk-pllv3.c72
-rw-r--r--drivers/clk/imx/clk-sccg-pll.c53
-rw-r--r--drivers/clk/imx/clk-vf610.c9
-rw-r--r--drivers/clk/imx/clk.h106
-rw-r--r--drivers/clk/loongson/Makefile3
-rw-r--r--drivers/clk/loongson/clk-ls1b200.c152
-rw-r--r--drivers/clk/mvebu/armada-38x.c2
-rw-r--r--drivers/clk/mvebu/armada-xp.c2
-rw-r--r--drivers/clk/mvebu/common.c26
-rw-r--r--drivers/clk/mvebu/corediv.c43
-rw-r--r--drivers/clk/mxs/clk-div.c36
-rw-r--r--drivers/clk/mxs/clk-frac.c32
-rw-r--r--drivers/clk/mxs/clk-imx23.c13
-rw-r--r--drivers/clk/mxs/clk-imx28.c21
-rw-r--r--drivers/clk/mxs/clk-lcdif.c20
-rw-r--r--drivers/clk/mxs/clk-pll.c32
-rw-r--r--drivers/clk/mxs/clk-ref.c40
-rw-r--r--drivers/clk/mxs/clk.h2
-rw-r--r--drivers/clk/rockchip/Makefile6
-rw-r--r--drivers/clk/rockchip/clk-cpu.c82
-rw-r--r--drivers/clk/rockchip/clk-inverter.c107
-rw-r--r--drivers/clk/rockchip/clk-mmc-phase.c192
-rw-r--r--drivers/clk/rockchip/clk-muxgrf.c95
-rw-r--r--drivers/clk/rockchip/clk-pll.c1075
-rw-r--r--drivers/clk/rockchip/clk-rk3188.c363
-rw-r--r--drivers/clk/rockchip/clk-rk3288.c309
-rw-r--r--drivers/clk/rockchip/clk-rk3399.c1654
-rw-r--r--drivers/clk/rockchip/clk-rk3568.c1741
-rw-r--r--drivers/clk/rockchip/clk-rk3588.c2530
-rw-r--r--drivers/clk/rockchip/clk.c520
-rw-r--r--drivers/clk/rockchip/clk.h628
-rw-r--r--drivers/clk/rockchip/rst-rk3588.c855
-rw-r--r--drivers/clk/rockchip/softrst.c126
-rw-r--r--drivers/clk/sifive/Kconfig18
-rw-r--r--drivers/clk/sifive/Makefile2
-rw-r--r--drivers/clk/sifive/fu540-prci.c87
-rw-r--r--drivers/clk/sifive/fu540-prci.h16
-rw-r--r--drivers/clk/sifive/fu740-prci.c121
-rw-r--r--drivers/clk/sifive/fu740-prci.h21
-rw-r--r--drivers/clk/sifive/sifive-prci.c586
-rw-r--r--drivers/clk/sifive/sifive-prci.h298
-rw-r--r--drivers/clk/socfpga/clk-gate-a10.c38
-rw-r--r--drivers/clk/socfpga/clk-periph-a10.c28
-rw-r--r--drivers/clk/socfpga/clk-pll-a10.c32
-rw-r--r--drivers/clk/socfpga/clk.c90
-rw-r--r--drivers/clk/socfpga/clk.h6
-rw-r--r--drivers/clk/starfive/Makefile3
-rw-r--r--drivers/clk/starfive/clk.h64
-rw-r--r--drivers/clk/starfive/jh7100-clkgen.c364
-rw-r--r--drivers/clk/stm32/Makefile1
-rw-r--r--drivers/clk/stm32/clk-stm32-core.c680
-rw-r--r--drivers/clk/stm32/clk-stm32-core.h188
-rw-r--r--drivers/clk/stm32/clk-stm32mp13.c1611
-rw-r--r--drivers/clk/stm32/reset-stm32.c122
-rw-r--r--drivers/clk/stm32/reset-stm32.h8
-rw-r--r--drivers/clk/stm32/stm32mp13_rcc.h1748
-rw-r--r--drivers/clk/tegra/clk-divider.c25
-rw-r--r--drivers/clk/tegra/clk-periph.c44
-rw-r--r--drivers/clk/tegra/clk-pll-out.c30
-rw-r--r--drivers/clk/tegra/clk-pll.c56
-rw-r--r--drivers/clk/tegra/clk-tegra124.c21
-rw-r--r--drivers/clk/tegra/clk-tegra20.c19
-rw-r--r--drivers/clk/tegra/clk-tegra30.c21
-rw-r--r--drivers/clk/tegra/clk.c2
-rw-r--r--drivers/clk/tegra/clk.h6
-rw-r--r--drivers/clk/ti-sci-clk.c630
-rw-r--r--drivers/clk/vexpress/clk-sp810.c28
-rw-r--r--drivers/clk/zynq/clkc.c121
-rw-r--r--drivers/clk/zynqmp/clk-divider-zynqmp.c34
-rw-r--r--drivers/clk/zynqmp/clk-gate-zynqmp.c37
-rw-r--r--drivers/clk/zynqmp/clk-mux-zynqmp.c34
-rw-r--r--drivers/clk/zynqmp/clk-pll-zynqmp.c52
-rw-r--r--drivers/clk/zynqmp/clk-zynqmp.h2
-rw-r--r--drivers/clk/zynqmp/clkc.c17
162 files changed, 29314 insertions, 4557 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index c05e065651..d2a61329e1 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -1,13 +1,33 @@
# SPDX-License-Identifier: GPL-2.0-only
config HAVE_CLK
bool
+ help
+ The <linux/clk.h> calls support software clock gating and
+ thus are a key power management tool on many systems.
+
+config HAVE_LEGACY_CLK
+ select HAVE_CLK
+ bool
+ help
+ Select this option when the clock API in <linux/clk.h> is implemented
+ by platform/architecture code. This method is deprecated. Modern
+ code should select COMMON_CLK instead and not define a custom
+ 'struct clk'.
config CLKDEV_LOOKUP
bool
config COMMON_CLK
+ bool "Common Clock Framework"
+ depends on !HAVE_LEGACY_CLK
select HAVE_CLK
- bool
+ select CLKDEV_LOOKUP
+ help
+ The common clock framework is a single definition of struct
+ clk, useful across many platforms, as well as an
+ implementation of the clock API in include/linux/clk.h.
+ Architectures utilizing the common struct clk should select
+ this option.
config COMMON_CLK_OF_PROVIDER
bool
@@ -19,3 +39,49 @@ config CLK_SOCFPGA
bool
select COMMON_CLK_OF_PROVIDER
default y if ARCH_SOCFPGA && OFDEVICE
+
+if COMMON_CLK
+
+config COMMON_CLK_STM32F
+ bool "STM32F4 and STM32F7 clock driver" if COMPILE_TEST
+ depends on ARCH_STM32
+ help
+ Support for stm32f4 and stm32f7 SoC families clocks
+
+config COMMON_CLK_STM32MP135
+ def_bool ARCH_STM32MP13
+ help
+ Support for stm32mp135 SoC family clocks
+
+config COMMON_CLK_STM32MP157
+ def_bool ARCH_STM32MP157
+ help
+ Support for stm32mp157 SoC family clocks
+
+config COMMON_CLK_SCMI
+ tristate "Clock driver controlled via SCMI interface"
+ depends on ARM_SCMI_PROTOCOL || COMPILE_TEST
+ help
+ This driver provides support for clocks that are controlled
+ by firmware that implements the SCMI interface.
+
+ This driver uses SCMI Message Protocol to interact with the
+ firmware providing all the clock controls.
+
+config TI_SCI_CLK
+ tristate "TI System Control Interface clock drivers"
+ depends on TI_SCI_PROTOCOL
+ default ARCH_K3
+ help
+ This adds the clock driver support over TI System Control Interface.
+ If you wish to use clock resources from the PMMC firmware, say Y.
+ Otherwise, say N.
+
+config COMMON_CLK_GPIO
+ bool
+ default y
+ depends on COMMON_CLK_OF_PROVIDER
+
+source "drivers/clk/sifive/Kconfig"
+
+endif
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 09032744a0..764539e91e 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -2,7 +2,7 @@
obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed.o clk-divider.o clk-fixed-factor.o \
clk-mux.o clk-gate.o clk-composite.o \
clk-fractional-divider.o clk-conf.o \
- clk-gate-shared.o clk-gpio.o \
+ clk-gate-shared.o \
clk-bulk.o
obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o
@@ -17,6 +17,17 @@ obj-$(CONFIG_SOC_QCA_AR9331) += clk-ar933x.o
obj-$(CONFIG_SOC_QCA_AR9344) += clk-ar9344.o
obj-$(CONFIG_ARCH_IMX) += imx/
obj-$(CONFIG_COMMON_CLK_AT91) += at91/
-obj-$(CONFIG_ARCH_STM32MP) += clk-stm32mp1.o
+obj-$(CONFIG_COMMON_CLK_STM32MP157) += clk-stm32mp1.o
+obj-$(CONFIG_ARCH_STM32) += stm32/
obj-$(CONFIG_MACH_VEXPRESS) += vexpress/
+obj-$(CONFIG_MACH_MIPS_LOONGSON)+= loongson/
obj-$(CONFIG_ARCH_LAYERSCAPE) += clk-qoric.o
+obj-y += analogbits/
+obj-$(CONFIG_CLK_SIFIVE) += sifive/
+obj-$(CONFIG_SOC_STARFIVE) += starfive/
+obj-$(CONFIG_COMMON_CLK_STM32F) += clk-stm32f4.o
+obj-$(CONFIG_MACH_RPI_COMMON) += clk-rpi.o
+obj-y += bcm/
+obj-$(CONFIG_COMMON_CLK_SCMI) += clk-scmi.o
+obj-$(CONFIG_COMMON_CLK_GPIO) += clk-gpio.o
+obj-$(CONFIG_TI_SCI_CLK) += ti-sci-clk.o
diff --git a/drivers/clk/analogbits/Makefile b/drivers/clk/analogbits/Makefile
new file mode 100644
index 0000000000..e8a2ecdd50
--- /dev/null
+++ b/drivers/clk/analogbits/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-y += wrpll-cln28hpc.o
diff --git a/drivers/clk/analogbits/wrpll-cln28hpc.c b/drivers/clk/analogbits/wrpll-cln28hpc.c
new file mode 100644
index 0000000000..1aafaf2e65
--- /dev/null
+++ b/drivers/clk/analogbits/wrpll-cln28hpc.c
@@ -0,0 +1,367 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2018-2019 SiFive, Inc.
+ * Wesley Terpstra
+ * Paul Walmsley
+ *
+ * This library supports configuration parsing and reprogramming of
+ * the CLN28HPC variant of the Analog Bits Wide Range PLL. The
+ * intention is for this library to be reusable for any device that
+ * integrates this PLL; thus the register structure and programming
+ * details are expected to be provided by a separate IP block driver.
+ *
+ * The bulk of this code is primarily useful for clock configurations
+ * that must operate at arbitrary rates, as opposed to clock configurations
+ * that are restricted by software or manufacturer guidance to a small,
+ * pre-determined set of performance points.
+ *
+ * References:
+ * - Analog Bits "Wide Range PLL Datasheet", version 2015.10.01
+ * - SiFive FU540-C000 Manual v1p0, Chapter 7 "Clocking and Reset"
+ * https://static.dev.sifive.com/FU540-C000-v1.0.pdf
+ */
+
+#include <linux/kernel.h>
+#include <stdio.h>
+#include <linux/printk.h>
+#include <linux/bug.h>
+#include <linux/err.h>
+#include <linux/log2.h>
+#include <linux/math64.h>
+#include <linux/clk/analogbits-wrpll-cln28hpc.h>
+
+/* MIN_INPUT_FREQ: minimum input clock frequency, in Hz (Fref_min) */
+#define MIN_INPUT_FREQ 7000000
+
+/* MAX_INPUT_FREQ: maximum input clock frequency, in Hz (Fref_max) */
+#define MAX_INPUT_FREQ 600000000
+
+/* MIN_POST_DIVIDE_REF_FREQ: minimum post-divider reference frequency, in Hz */
+#define MIN_POST_DIVR_FREQ 7000000
+
+/* MAX_POST_DIVIDE_REF_FREQ: maximum post-divider reference frequency, in Hz */
+#define MAX_POST_DIVR_FREQ 200000000
+
+/* MIN_VCO_FREQ: minimum VCO frequency, in Hz (Fvco_min) */
+#define MIN_VCO_FREQ 2400000000UL
+
+/* MAX_VCO_FREQ: maximum VCO frequency, in Hz (Fvco_max) */
+#define MAX_VCO_FREQ 4800000000ULL
+
+/* MAX_DIVQ_DIVISOR: maximum output divisor. Selected by DIVQ = 6 */
+#define MAX_DIVQ_DIVISOR 64
+
+/* MAX_DIVR_DIVISOR: maximum reference divisor. Selected by DIVR = 63 */
+#define MAX_DIVR_DIVISOR 64
+
+/* MAX_LOCK_US: maximum PLL lock time, in microseconds (tLOCK_max) */
+#define MAX_LOCK_US 70
+
+/*
+ * ROUND_SHIFT: number of bits to shift to avoid precision loss in the rounding
+ * algorithm
+ */
+#define ROUND_SHIFT 20
+
+/*
+ * Private functions
+ */
+
+/**
+ * __wrpll_calc_filter_range() - determine PLL loop filter bandwidth
+ * @post_divr_freq: input clock rate after the R divider
+ *
+ * Select the value to be presented to the PLL RANGE input signals, based
+ * on the input clock frequency after the post-R-divider @post_divr_freq.
+ * This code follows the recommendations in the PLL datasheet for filter
+ * range selection.
+ *
+ * Return: The RANGE value to be presented to the PLL configuration inputs,
+ * or a negative return code upon error.
+ */
+static int __wrpll_calc_filter_range(unsigned long post_divr_freq)
+{
+ if (post_divr_freq < MIN_POST_DIVR_FREQ ||
+ post_divr_freq > MAX_POST_DIVR_FREQ) {
+ WARN(1, "%s: post-divider reference freq out of range: %lu",
+ __func__, post_divr_freq);
+ return -ERANGE;
+ }
+
+ switch (post_divr_freq) {
+ case 0 ... 10999999:
+ return 1;
+ case 11000000 ... 17999999:
+ return 2;
+ case 18000000 ... 29999999:
+ return 3;
+ case 30000000 ... 49999999:
+ return 4;
+ case 50000000 ... 79999999:
+ return 5;
+ case 80000000 ... 129999999:
+ return 6;
+ }
+
+ return 7;
+}
+
+/**
+ * __wrpll_calc_fbdiv() - return feedback fixed divide value
+ * @c: ptr to a struct wrpll_cfg record to read from
+ *
+ * The internal feedback path includes a fixed by-two divider; the
+ * external feedback path does not. Return the appropriate divider
+ * value (2 or 1) depending on whether internal or external feedback
+ * is enabled. This code doesn't test for invalid configurations
+ * (e.g. both or neither of WRPLL_FLAGS_*_FEEDBACK are set); it relies
+ * on the caller to do so.
+ *
+ * Context: Any context. Caller must protect the memory pointed to by
+ * @c from simultaneous modification.
+ *
+ * Return: 2 if internal feedback is enabled or 1 if external feedback
+ * is enabled.
+ */
+static u8 __wrpll_calc_fbdiv(const struct wrpll_cfg *c)
+{
+ return (c->flags & WRPLL_FLAGS_INT_FEEDBACK_MASK) ? 2 : 1;
+}
+
+/**
+ * __wrpll_calc_divq() - determine DIVQ based on target PLL output clock rate
+ * @target_rate: target PLL output clock rate
+ * @vco_rate: pointer to a u64 to store the computed VCO rate into
+ *
+ * Determine a reasonable value for the PLL Q post-divider, based on the
+ * target output rate @target_rate for the PLL. Along with returning the
+ * computed Q divider value as the return value, this function stores the
+ * desired target VCO rate into the variable pointed to by @vco_rate.
+ *
+ * Context: Any context. Caller must protect the memory pointed to by
+ * @vco_rate from simultaneous access or modification.
+ *
+ * Return: a positive integer DIVQ value to be programmed into the hardware
+ * upon success, or 0 upon error (since 0 is an invalid DIVQ value)
+ */
+static u8 __wrpll_calc_divq(u32 target_rate, u64 *vco_rate)
+{
+ u64 s;
+ u8 divq = 0;
+
+ if (!vco_rate) {
+ WARN_ON(1);
+ goto wcd_out;
+ }
+
+ s = div_u64(MAX_VCO_FREQ, target_rate);
+ if (s <= 1) {
+ divq = 1;
+ *vco_rate = MAX_VCO_FREQ;
+ } else if (s > MAX_DIVQ_DIVISOR) {
+ divq = ilog2(MAX_DIVQ_DIVISOR);
+ *vco_rate = MIN_VCO_FREQ;
+ } else {
+ divq = ilog2(s);
+ *vco_rate = (u64)target_rate << divq;
+ }
+
+wcd_out:
+ return divq;
+}
+
+/**
+ * __wrpll_update_parent_rate() - update PLL data when parent rate changes
+ * @c: ptr to a struct wrpll_cfg record to write PLL data to
+ * @parent_rate: PLL input refclk rate (pre-R-divider)
+ *
+ * Pre-compute some data used by the PLL configuration algorithm when
+ * the PLL's reference clock rate changes. The intention is to avoid
+ * computation when the parent rate remains constant - expected to be
+ * the common case.
+ *
+ * Returns: 0 upon success or -ERANGE if the reference clock rate is
+ * out of range.
+ */
+static int __wrpll_update_parent_rate(struct wrpll_cfg *c,
+ unsigned long parent_rate)
+{
+ u8 max_r_for_parent;
+
+ if (parent_rate > MAX_INPUT_FREQ || parent_rate < MIN_POST_DIVR_FREQ)
+ return -ERANGE;
+
+ c->parent_rate = parent_rate;
+ max_r_for_parent = div_u64(parent_rate, MIN_POST_DIVR_FREQ);
+ c->max_r = min_t(u8, MAX_DIVR_DIVISOR, max_r_for_parent);
+
+ c->init_r = DIV_ROUND_UP_ULL(parent_rate, MAX_POST_DIVR_FREQ);
+
+ return 0;
+}
+
+/**
+ * wrpll_configure() - compute PLL configuration for a target rate
+ * @c: ptr to a struct wrpll_cfg record to write into
+ * @target_rate: target PLL output clock rate (post-Q-divider)
+ * @parent_rate: PLL input refclk rate (pre-R-divider)
+ *
+ * Compute the appropriate PLL signal configuration values and store
+ * in PLL context @c. PLL reprogramming is not glitchless, so the
+ * caller should switch any downstream logic to a different clock
+ * source or clock-gate it before presenting these values to the PLL
+ * configuration signals.
+ *
+ * The caller must pass this function a pre-initialized struct
+ * wrpll_cfg record: either initialized to zero (with the
+ * exception of the .name and .flags fields) or read from the PLL.
+ *
+ * Context: Any context. Caller must protect the memory pointed to by @c
+ * from simultaneous access or modification.
+ *
+ * Return: 0 upon success; anything else upon failure.
+ */
+int wrpll_configure_for_rate(struct wrpll_cfg *c, u32 target_rate,
+ unsigned long parent_rate)
+{
+ unsigned long ratio;
+ u64 target_vco_rate, delta, best_delta, f_pre_div, vco, vco_pre;
+ u32 best_f, f, post_divr_freq;
+ u8 fbdiv, divq, best_r, r;
+ int range;
+
+ if (c->flags == 0) {
+ WARN(1, "%s called with uninitialized PLL config", __func__);
+ return -EINVAL;
+ }
+
+ /* Initialize rounding data if it hasn't been initialized already */
+ if (parent_rate != c->parent_rate) {
+ if (__wrpll_update_parent_rate(c, parent_rate)) {
+ pr_err("%s: PLL input rate is out of range\n",
+ __func__);
+ return -ERANGE;
+ }
+ }
+
+ c->flags &= ~WRPLL_FLAGS_RESET_MASK;
+
+ /* Put the PLL into bypass if the user requests the parent clock rate */
+ if (target_rate == parent_rate) {
+ c->flags |= WRPLL_FLAGS_BYPASS_MASK;
+ return 0;
+ }
+
+ c->flags &= ~WRPLL_FLAGS_BYPASS_MASK;
+
+ /* Calculate the Q shift and target VCO rate */
+ divq = __wrpll_calc_divq(target_rate, &target_vco_rate);
+ if (!divq)
+ return -1;
+ c->divq = divq;
+
+ /* Precalculate the pre-Q divider target ratio */
+ ratio = div64_u64((target_vco_rate << ROUND_SHIFT), parent_rate);
+
+ fbdiv = __wrpll_calc_fbdiv(c);
+ best_r = 0;
+ best_f = 0;
+ best_delta = MAX_VCO_FREQ;
+
+ /*
+ * Consider all values for R which land within
+ * [MIN_POST_DIVR_FREQ, MAX_POST_DIVR_FREQ]; prefer smaller R
+ */
+ for (r = c->init_r; r <= c->max_r; ++r) {
+ f_pre_div = ratio * r;
+ f = (f_pre_div + (1 << ROUND_SHIFT)) >> ROUND_SHIFT;
+ f >>= (fbdiv - 1);
+
+ post_divr_freq = div_u64(parent_rate, r);
+ vco_pre = fbdiv * post_divr_freq;
+ vco = vco_pre * f;
+
+ /* Ensure rounding didn't take us out of range */
+ if (vco > target_vco_rate) {
+ --f;
+ vco = vco_pre * f;
+ } else if (vco < MIN_VCO_FREQ) {
+ ++f;
+ vco = vco_pre * f;
+ }
+
+ delta = abs(target_rate - vco);
+ if (delta < best_delta) {
+ best_delta = delta;
+ best_r = r;
+ best_f = f;
+ }
+ }
+
+ c->divr = best_r - 1;
+ c->divf = best_f - 1;
+
+ post_divr_freq = div_u64(parent_rate, best_r);
+
+ /* Pick the best PLL jitter filter */
+ range = __wrpll_calc_filter_range(post_divr_freq);
+ if (range < 0)
+ return range;
+ c->range = range;
+
+ return 0;
+}
+
+/**
+ * wrpll_calc_output_rate() - calculate the PLL's target output rate
+ * @c: ptr to a struct wrpll_cfg record to read from
+ * @parent_rate: PLL refclk rate
+ *
+ * Given a pointer to the PLL's current input configuration @c and the
+ * PLL's input reference clock rate @parent_rate (before the R
+ * pre-divider), calculate the PLL's output clock rate (after the Q
+ * post-divider).
+ *
+ * Context: Any context. Caller must protect the memory pointed to by @c
+ * from simultaneous modification.
+ *
+ * Return: the PLL's output clock rate, in Hz. The return value from
+ * this function is intended to be convenient to pass directly
+ * to the Linux clock framework; thus there is no explicit
+ * error return value.
+ */
+unsigned long wrpll_calc_output_rate(const struct wrpll_cfg *c,
+ unsigned long parent_rate)
+{
+ u8 fbdiv;
+ u64 n;
+
+ if (c->flags & WRPLL_FLAGS_EXT_FEEDBACK_MASK) {
+ WARN(1, "external feedback mode not yet supported");
+ return ULONG_MAX;
+ }
+
+ fbdiv = __wrpll_calc_fbdiv(c);
+ n = parent_rate * fbdiv * (c->divf + 1);
+ n = div_u64(n, c->divr + 1);
+ n >>= c->divq;
+
+ return n;
+}
+
+/**
+ * wrpll_calc_max_lock_us() - return the time for the PLL to lock
+ * @c: ptr to a struct wrpll_cfg record to read from
+ *
+ * Return the minimum amount of time (in microseconds) that the caller
+ * must wait after reprogramming the PLL to ensure that it is locked
+ * to the input frequency and stable. This is likely to depend on the DIVR
+ * value; this is under discussion with the manufacturer.
+ *
+ * Return: the minimum amount of time the caller must wait for the PLL
+ * to lock (in microseconds)
+ */
+unsigned int wrpll_calc_max_lock_us(const struct wrpll_cfg *c)
+{
+ return MAX_LOCK_US;
+}
diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile
index 423605f452..083555b4d2 100644
--- a/drivers/clk/at91/Makefile
+++ b/drivers/clk/at91/Makefile
@@ -15,8 +15,11 @@ obj-$(CONFIG_HAVE_AT91_H32MX) += clk-h32mx.o
obj-$(CONFIG_HAVE_AT91_GENERATED_CLK) += clk-generated.o
obj-$(CONFIG_HAVE_AT91_I2S_MUX_CLK) += clk-i2s-mux.o
obj-$(CONFIG_HAVE_AT91_SAM9X60_PLL) += clk-sam9x60-pll.o
-obj-$(CONFIG_SOC_AT91SAM9) += at91sam9260.o at91sam9rl.o at91sam9x5.o dt-compat.o
+obj-$(CONFIG_SOC_AT91RM9200) += at91rm9200.o
+obj-$(CONFIG_SOC_AT91SAM9) += at91sam9260.o at91sam9rl.o at91sam9x5.o
+obj-$(CONFIG_SOC_AT91SAM9) += at91sam9g45.o
+obj-$(CONFIG_SOC_AT91SAM9) += at91sam9n12.o at91sam9x5.o
obj-$(CONFIG_SOC_SAM9X60) += sam9x60.o
+obj-$(CONFIG_SOC_SAMA5D3) += sama5d3.o
obj-$(CONFIG_SOC_SAMA5D4) += sama5d4.o
-obj-$(CONFIG_SOC_SAMA5D3) += dt-compat.o
obj-$(CONFIG_SOC_SAMA5D2) += sama5d2.o
diff --git a/drivers/clk/at91/at91rm9200.c b/drivers/clk/at91/at91rm9200.c
new file mode 100644
index 0000000000..df75a93edb
--- /dev/null
+++ b/drivers/clk/at91/at91rm9200.c
@@ -0,0 +1,218 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/clk-provider.h>
+#include <mfd/syscon.h>
+#include <linux/slab.h>
+#include <stdio.h>
+
+#include <dt-bindings/clock/at91.h>
+
+#include "pmc.h"
+
+static DEFINE_SPINLOCK(rm9200_mck_lock);
+
+struct sck {
+ char *n;
+ char *p;
+ u8 id;
+};
+
+struct pck {
+ char *n;
+ u8 id;
+};
+
+static const struct clk_master_characteristics rm9200_mck_characteristics = {
+ .output = { .min = 0, .max = 80000000 },
+ .divisors = { 1, 2, 3, 4 },
+};
+
+static u8 rm9200_pll_out[] = { 0, 2 };
+
+static const struct clk_range rm9200_pll_outputs[] = {
+ { .min = 80000000, .max = 160000000 },
+ { .min = 150000000, .max = 180000000 },
+};
+
+static const struct clk_pll_characteristics rm9200_pll_characteristics = {
+ .input = { .min = 1000000, .max = 32000000 },
+ .num_output = ARRAY_SIZE(rm9200_pll_outputs),
+ .output = rm9200_pll_outputs,
+ .out = rm9200_pll_out,
+};
+
+static const struct sck at91rm9200_systemck[] = {
+ { .n = "udpck", .p = "usbck", .id = 1 },
+ { .n = "uhpck", .p = "usbck", .id = 4 },
+ { .n = "pck0", .p = "prog0", .id = 8 },
+ { .n = "pck1", .p = "prog1", .id = 9 },
+ { .n = "pck2", .p = "prog2", .id = 10 },
+ { .n = "pck3", .p = "prog3", .id = 11 },
+};
+
+static const struct pck at91rm9200_periphck[] = {
+ { .n = "pioA_clk", .id = 2 },
+ { .n = "pioB_clk", .id = 3 },
+ { .n = "pioC_clk", .id = 4 },
+ { .n = "pioD_clk", .id = 5 },
+ { .n = "usart0_clk", .id = 6 },
+ { .n = "usart1_clk", .id = 7 },
+ { .n = "usart2_clk", .id = 8 },
+ { .n = "usart3_clk", .id = 9 },
+ { .n = "mci0_clk", .id = 10 },
+ { .n = "udc_clk", .id = 11 },
+ { .n = "twi0_clk", .id = 12 },
+ { .n = "spi0_clk", .id = 13 },
+ { .n = "ssc0_clk", .id = 14 },
+ { .n = "ssc1_clk", .id = 15 },
+ { .n = "ssc2_clk", .id = 16 },
+ { .n = "tc0_clk", .id = 17 },
+ { .n = "tc1_clk", .id = 18 },
+ { .n = "tc2_clk", .id = 19 },
+ { .n = "tc3_clk", .id = 20 },
+ { .n = "tc4_clk", .id = 21 },
+ { .n = "tc5_clk", .id = 22 },
+ { .n = "ohci_clk", .id = 23 },
+ { .n = "macb0_clk", .id = 24 },
+};
+
+static void __init at91rm9200_pmc_setup(struct device_node *np)
+{
+ const char *slowxtal_name, *mainxtal_name;
+ struct pmc_data *at91rm9200_pmc;
+ u32 usb_div[] = { 1, 2, 0, 0 };
+ const char *parent_names[6];
+ struct regmap *regmap;
+ struct clk_hw *hw;
+ int i;
+ bool bypass;
+
+ i = of_property_match_string(np, "clock-names", "slow_xtal");
+ if (i < 0)
+ return;
+
+ slowxtal_name = of_clk_get_parent_name(np, i);
+
+ i = of_property_match_string(np, "clock-names", "main_xtal");
+ if (i < 0)
+ return;
+ mainxtal_name = of_clk_get_parent_name(np, i);
+
+ regmap = device_node_to_regmap(np);
+ if (IS_ERR(regmap))
+ return;
+
+ at91rm9200_pmc = pmc_data_allocate(PMC_PLLBCK + 1,
+ nck(at91rm9200_systemck),
+ nck(at91rm9200_periphck), 0, 4);
+ if (!at91rm9200_pmc)
+ return;
+
+ bypass = of_property_read_bool(np, "atmel,osc-bypass");
+
+ hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
+ bypass);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ hw = at91_clk_register_rm9200_main(regmap, "mainck", "main_osc");
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91rm9200_pmc->chws[PMC_MAIN] = hw;
+
+ hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
+ &at91rm9200_pll_layout,
+ &rm9200_pll_characteristics);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91rm9200_pmc->chws[PMC_PLLACK] = hw;
+
+ hw = at91_clk_register_pll(regmap, "pllbck", "mainck", 1,
+ &at91rm9200_pll_layout,
+ &rm9200_pll_characteristics);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91rm9200_pmc->chws[PMC_PLLBCK] = hw;
+
+ parent_names[0] = slowxtal_name;
+ parent_names[1] = "mainck";
+ parent_names[2] = "pllack";
+ parent_names[3] = "pllbck";
+ hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
+ parent_names,
+ &at91rm9200_master_layout,
+ &rm9200_mck_characteristics,
+ &rm9200_mck_lock);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ hw = at91_clk_register_master_div(regmap, "masterck_div",
+ "masterck_pres",
+ &at91rm9200_master_layout,
+ &rm9200_mck_characteristics,
+ &rm9200_mck_lock, CLK_SET_RATE_GATE);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91rm9200_pmc->chws[PMC_MCK] = hw;
+
+ hw = at91rm9200_clk_register_usb(regmap, "usbck", "pllbck", usb_div);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ parent_names[0] = slowxtal_name;
+ parent_names[1] = "mainck";
+ parent_names[2] = "pllack";
+ parent_names[3] = "pllbck";
+ for (i = 0; i < 4; i++) {
+ char name[6];
+
+ snprintf(name, sizeof(name), "prog%d", i);
+
+ hw = at91_clk_register_programmable(regmap, name,
+ parent_names, 4, i,
+ &at91rm9200_programmable_layout,
+ NULL);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91rm9200_pmc->pchws[i] = hw;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(at91rm9200_systemck); i++) {
+ hw = at91_clk_register_system(regmap, at91rm9200_systemck[i].n,
+ at91rm9200_systemck[i].p,
+ at91rm9200_systemck[i].id, 0);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91rm9200_pmc->shws[at91rm9200_systemck[i].id] = hw;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(at91rm9200_periphck); i++) {
+ hw = at91_clk_register_peripheral(regmap,
+ at91rm9200_periphck[i].n,
+ "masterck_div",
+ at91rm9200_periphck[i].id);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91rm9200_pmc->phws[at91rm9200_periphck[i].id] = hw;
+ }
+
+ of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91rm9200_pmc);
+
+ return;
+
+err_free:
+ kfree(at91rm9200_pmc);
+}
+/*
+ * While the TCB can be used as the clocksource, the system timer is most likely
+ * to be used instead. However, the pinctrl driver doesn't support probe
+ * deferring properly. Once this is fixed, this can be switched to a platform
+ * driver.
+ */
+CLK_OF_DECLARE(at91rm9200_pmc, "atmel,at91rm9200-pmc", at91rm9200_pmc_setup);
diff --git a/drivers/clk/at91/at91sam9260.c b/drivers/clk/at91/at91sam9260.c
index 066dedf2a1..c94cd95566 100644
--- a/drivers/clk/at91/at91sam9260.c
+++ b/drivers/clk/at91/at91sam9260.c
@@ -1,13 +1,8 @@
-// SPDX-License-Identifier: GPL-2.0
-
-#include <driver.h>
-#include <regmap.h>
-#include <stdio.h>
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/clk-provider.h>
#include <mfd/syscon.h>
-
-#include <linux/clk.h>
#include <linux/slab.h>
-#include <linux/types.h>
+#include <stdio.h>
#include <dt-bindings/clock/at91.h>
@@ -38,6 +33,8 @@ struct at91sam926x_data {
bool has_slck;
};
+static DEFINE_SPINLOCK(at91sam9260_mck_lock);
+
static const struct clk_master_characteristics sam9260_mck_characteristics = {
.output = { .min = 0, .max = 105000000 },
.divisors = { 1, 2, 4, 0 },
@@ -224,8 +221,8 @@ static const struct sck at91sam9261_systemck[] = {
{ .n = "pck1", .p = "prog1", .id = 9 },
{ .n = "pck2", .p = "prog2", .id = 10 },
{ .n = "pck3", .p = "prog3", .id = 11 },
- { .n = "hclk0", .p = "masterck", .id = 16 },
- { .n = "hclk1", .p = "masterck", .id = 17 },
+ { .n = "hclk0", .p = "masterck_div", .id = 16 },
+ { .n = "hclk1", .p = "masterck_div", .id = 17 },
};
static const struct pck at91sam9261_periphck[] = {
@@ -339,7 +336,7 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
const char *parent_names[6];
const char *slck_name;
struct regmap *regmap;
- struct clk *hw;
+ struct clk_hw *hw;
int i;
bool bypass;
@@ -358,9 +355,10 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
if (IS_ERR(regmap))
return;
- at91sam9260_pmc = pmc_data_allocate(PMC_MAIN + 1,
+ at91sam9260_pmc = pmc_data_allocate(PMC_PLLBCK + 1,
ndck(data->sck, data->num_sck),
- ndck(data->pck, data->num_pck), 0);
+ ndck(data->pck, data->num_pck),
+ 0, data->num_progck);
if (!at91sam9260_pmc)
return;
@@ -378,7 +376,10 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
at91sam9260_pmc->chws[PMC_MAIN] = hw;
if (data->has_slck) {
- hw = clk_fixed("slow_rc_osc", 32768);
+ hw = clk_hw_register_fixed_rate_with_accuracy(NULL,
+ "slow_rc_osc",
+ NULL, 0, 32768,
+ 50000000);
if (IS_ERR(hw))
goto err_free;
@@ -401,19 +402,34 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
if (IS_ERR(hw))
goto err_free;
+ at91sam9260_pmc->chws[PMC_PLLACK] = hw;
+
hw = at91_clk_register_pll(regmap, "pllbck", "mainck", 1,
data->pllb_layout,
data->pllb_characteristics);
if (IS_ERR(hw))
goto err_free;
+ at91sam9260_pmc->chws[PMC_PLLBCK] = hw;
+
parent_names[0] = slck_name;
parent_names[1] = "mainck";
parent_names[2] = "pllack";
parent_names[3] = "pllbck";
- hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
- &at91rm9200_master_layout,
- data->mck_characteristics);
+ hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
+ parent_names,
+ &at91rm9200_master_layout,
+ data->mck_characteristics,
+ &at91sam9260_mck_lock);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ hw = at91_clk_register_master_div(regmap, "masterck_div",
+ "masterck_pres",
+ &at91rm9200_master_layout,
+ data->mck_characteristics,
+ &at91sam9260_mck_lock,
+ CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
@@ -428,21 +444,24 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
parent_names[2] = "pllack";
parent_names[3] = "pllbck";
for (i = 0; i < data->num_progck; i++) {
- char *name;
+ char name[6];
- name = xasprintf("prog%d", i);
+ snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
parent_names, 4, i,
- &at91rm9200_programmable_layout);
+ &at91rm9200_programmable_layout,
+ NULL);
if (IS_ERR(hw))
goto err_free;
+
+ at91sam9260_pmc->pchws[i] = hw;
}
for (i = 0; i < data->num_sck; i++) {
hw = at91_clk_register_system(regmap, data->sck[i].n,
data->sck[i].p,
- data->sck[i].id);
+ data->sck[i].id, 0);
if (IS_ERR(hw))
goto err_free;
@@ -452,7 +471,7 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
for (i = 0; i < data->num_pck; i++) {
hw = at91_clk_register_peripheral(regmap,
data->pck[i].n,
- "masterck",
+ "masterck_div",
data->pck[i].id);
if (IS_ERR(hw))
goto err_free;
@@ -460,38 +479,38 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
at91sam9260_pmc->phws[data->pck[i].id] = hw;
}
- of_clk_add_provider(np, of_clk_hw_pmc_get, at91sam9260_pmc);
+ of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9260_pmc);
return;
err_free:
- pmc_data_free(at91sam9260_pmc);
+ kfree(at91sam9260_pmc);
}
static void __init at91sam9260_pmc_setup(struct device_node *np)
{
at91sam926x_pmc_setup(np, &at91sam9260_data);
}
-CLK_OF_DECLARE_DRIVER(at91sam9260_pmc, "atmel,at91sam9260-pmc",
- at91sam9260_pmc_setup);
+
+CLK_OF_DECLARE(at91sam9260_pmc, "atmel,at91sam9260-pmc", at91sam9260_pmc_setup);
static void __init at91sam9261_pmc_setup(struct device_node *np)
{
at91sam926x_pmc_setup(np, &at91sam9261_data);
}
-CLK_OF_DECLARE_DRIVER(at91sam9261_pmc, "atmel,at91sam9261-pmc",
- at91sam9261_pmc_setup);
+
+CLK_OF_DECLARE(at91sam9261_pmc, "atmel,at91sam9261-pmc", at91sam9261_pmc_setup);
static void __init at91sam9263_pmc_setup(struct device_node *np)
{
at91sam926x_pmc_setup(np, &at91sam9263_data);
}
-CLK_OF_DECLARE_DRIVER(at91sam9263_pmc, "atmel,at91sam9263-pmc",
- at91sam9263_pmc_setup);
+
+CLK_OF_DECLARE(at91sam9263_pmc, "atmel,at91sam9263-pmc", at91sam9263_pmc_setup);
static void __init at91sam9g20_pmc_setup(struct device_node *np)
{
at91sam926x_pmc_setup(np, &at91sam9g20_data);
}
-CLK_OF_DECLARE_DRIVER(at91sam9g20_pmc, "atmel,at91sam9g20-pmc",
- at91sam9g20_pmc_setup);
+
+CLK_OF_DECLARE(at91sam9g20_pmc, "atmel,at91sam9g20-pmc", at91sam9g20_pmc_setup);
diff --git a/drivers/clk/at91/at91sam9g45.c b/drivers/clk/at91/at91sam9g45.c
new file mode 100644
index 0000000000..fedf961393
--- /dev/null
+++ b/drivers/clk/at91/at91sam9g45.c
@@ -0,0 +1,237 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/clk-provider.h>
+#include <mfd/syscon.h>
+#include <linux/slab.h>
+#include <stdio.h>
+
+#include <dt-bindings/clock/at91.h>
+
+#include "pmc.h"
+
+static DEFINE_SPINLOCK(at91sam9g45_mck_lock);
+
+static const struct clk_master_characteristics mck_characteristics = {
+ .output = { .min = 0, .max = 133333333 },
+ .divisors = { 1, 2, 4, 3 },
+};
+
+static u8 plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 };
+
+static u16 plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 };
+
+static const struct clk_range plla_outputs[] = {
+ { .min = 745000000, .max = 800000000 },
+ { .min = 695000000, .max = 750000000 },
+ { .min = 645000000, .max = 700000000 },
+ { .min = 595000000, .max = 650000000 },
+ { .min = 545000000, .max = 600000000 },
+ { .min = 495000000, .max = 555000000 },
+ { .min = 445000000, .max = 500000000 },
+ { .min = 400000000, .max = 450000000 },
+};
+
+static const struct clk_pll_characteristics plla_characteristics = {
+ .input = { .min = 2000000, .max = 32000000 },
+ .num_output = ARRAY_SIZE(plla_outputs),
+ .output = plla_outputs,
+ .icpll = plla_icpll,
+ .out = plla_out,
+};
+
+static const struct {
+ char *n;
+ char *p;
+ unsigned long flags;
+ u8 id;
+} at91sam9g45_systemck[] = {
+ /*
+ * ddrck feeds DDR controller and is enabled by bootloader thus we need
+ * to keep it enabled in case there is no Linux consumer for it.
+ */
+ { .n = "ddrck", .p = "masterck_div", .id = 2, .flags = CLK_IS_CRITICAL },
+ { .n = "uhpck", .p = "usbck", .id = 6 },
+ { .n = "pck0", .p = "prog0", .id = 8 },
+ { .n = "pck1", .p = "prog1", .id = 9 },
+};
+
+struct pck {
+ char *n;
+ u8 id;
+};
+
+static const struct pck at91sam9g45_periphck[] = {
+ { .n = "pioA_clk", .id = 2, },
+ { .n = "pioB_clk", .id = 3, },
+ { .n = "pioC_clk", .id = 4, },
+ { .n = "pioDE_clk", .id = 5, },
+ { .n = "trng_clk", .id = 6, },
+ { .n = "usart0_clk", .id = 7, },
+ { .n = "usart1_clk", .id = 8, },
+ { .n = "usart2_clk", .id = 9, },
+ { .n = "usart3_clk", .id = 10, },
+ { .n = "mci0_clk", .id = 11, },
+ { .n = "twi0_clk", .id = 12, },
+ { .n = "twi1_clk", .id = 13, },
+ { .n = "spi0_clk", .id = 14, },
+ { .n = "spi1_clk", .id = 15, },
+ { .n = "ssc0_clk", .id = 16, },
+ { .n = "ssc1_clk", .id = 17, },
+ { .n = "tcb0_clk", .id = 18, },
+ { .n = "pwm_clk", .id = 19, },
+ { .n = "adc_clk", .id = 20, },
+ { .n = "dma0_clk", .id = 21, },
+ { .n = "uhphs_clk", .id = 22, },
+ { .n = "lcd_clk", .id = 23, },
+ { .n = "ac97_clk", .id = 24, },
+ { .n = "macb0_clk", .id = 25, },
+ { .n = "isi_clk", .id = 26, },
+ { .n = "udphs_clk", .id = 27, },
+ { .n = "aestdessha_clk", .id = 28, },
+ { .n = "mci1_clk", .id = 29, },
+ { .n = "vdec_clk", .id = 30, },
+};
+
+static void __init at91sam9g45_pmc_setup(struct device_node *np)
+{
+ const char *slck_name, *mainxtal_name;
+ struct pmc_data *at91sam9g45_pmc;
+ const char *parent_names[6];
+ struct regmap *regmap;
+ struct clk_hw *hw;
+ int i;
+ bool bypass;
+
+ i = of_property_match_string(np, "clock-names", "slow_clk");
+ if (i < 0)
+ return;
+
+ slck_name = of_clk_get_parent_name(np, i);
+
+ i = of_property_match_string(np, "clock-names", "main_xtal");
+ if (i < 0)
+ return;
+ mainxtal_name = of_clk_get_parent_name(np, i);
+
+ regmap = device_node_to_regmap(np);
+ if (IS_ERR(regmap))
+ return;
+
+ at91sam9g45_pmc = pmc_data_allocate(PMC_PLLACK + 1,
+ nck(at91sam9g45_systemck),
+ nck(at91sam9g45_periphck), 0, 2);
+ if (!at91sam9g45_pmc)
+ return;
+
+ bypass = of_property_read_bool(np, "atmel,osc-bypass");
+
+ hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
+ bypass);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ hw = at91_clk_register_rm9200_main(regmap, "mainck", "main_osc");
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91sam9g45_pmc->chws[PMC_MAIN] = hw;
+
+ hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
+ &at91rm9200_pll_layout, &plla_characteristics);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ hw = at91_clk_register_plldiv(regmap, "plladivck", "pllack");
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91sam9g45_pmc->chws[PMC_PLLACK] = hw;
+
+ hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91sam9g45_pmc->chws[PMC_UTMI] = hw;
+
+ parent_names[0] = slck_name;
+ parent_names[1] = "mainck";
+ parent_names[2] = "plladivck";
+ parent_names[3] = "utmick";
+ hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
+ parent_names,
+ &at91rm9200_master_layout,
+ &mck_characteristics,
+ &at91sam9g45_mck_lock);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ hw = at91_clk_register_master_div(regmap, "masterck_div",
+ "masterck_pres",
+ &at91rm9200_master_layout,
+ &mck_characteristics,
+ &at91sam9g45_mck_lock,
+ CLK_SET_RATE_GATE);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91sam9g45_pmc->chws[PMC_MCK] = hw;
+
+ parent_names[0] = "plladivck";
+ parent_names[1] = "utmick";
+ hw = at91sam9x5_clk_register_usb(regmap, "usbck", parent_names, 2);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ parent_names[0] = slck_name;
+ parent_names[1] = "mainck";
+ parent_names[2] = "plladivck";
+ parent_names[3] = "utmick";
+ parent_names[4] = "masterck_div";
+ for (i = 0; i < 2; i++) {
+ char name[6];
+
+ snprintf(name, sizeof(name), "prog%d", i);
+
+ hw = at91_clk_register_programmable(regmap, name,
+ parent_names, 5, i,
+ &at91sam9g45_programmable_layout,
+ NULL);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91sam9g45_pmc->pchws[i] = hw;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(at91sam9g45_systemck); i++) {
+ hw = at91_clk_register_system(regmap, at91sam9g45_systemck[i].n,
+ at91sam9g45_systemck[i].p,
+ at91sam9g45_systemck[i].id,
+ at91sam9g45_systemck[i].flags);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91sam9g45_pmc->shws[at91sam9g45_systemck[i].id] = hw;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(at91sam9g45_periphck); i++) {
+ hw = at91_clk_register_peripheral(regmap,
+ at91sam9g45_periphck[i].n,
+ "masterck_div",
+ at91sam9g45_periphck[i].id);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91sam9g45_pmc->phws[at91sam9g45_periphck[i].id] = hw;
+ }
+
+ of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9g45_pmc);
+
+ return;
+
+err_free:
+ kfree(at91sam9g45_pmc);
+}
+/*
+ * The TCB is used as the clocksource so its clock is needed early. This means
+ * this can't be a platform driver.
+ */
+CLK_OF_DECLARE(at91sam9g45_pmc, "atmel,at91sam9g45-pmc", at91sam9g45_pmc_setup);
diff --git a/drivers/clk/at91/at91sam9n12.c b/drivers/clk/at91/at91sam9n12.c
new file mode 100644
index 0000000000..bb075de9fd
--- /dev/null
+++ b/drivers/clk/at91/at91sam9n12.c
@@ -0,0 +1,264 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/clk-provider.h>
+#include <mfd/syscon.h>
+#include <linux/slab.h>
+#include <stdio.h>
+
+#include <dt-bindings/clock/at91.h>
+
+#include "pmc.h"
+
+static DEFINE_SPINLOCK(at91sam9n12_mck_lock);
+
+static const struct clk_master_characteristics mck_characteristics = {
+ .output = { .min = 0, .max = 133333333 },
+ .divisors = { 1, 2, 4, 3 },
+ .have_div3_pres = 1,
+};
+
+static u8 plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 };
+
+static u16 plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 };
+
+static const struct clk_range plla_outputs[] = {
+ { .min = 745000000, .max = 800000000 },
+ { .min = 695000000, .max = 750000000 },
+ { .min = 645000000, .max = 700000000 },
+ { .min = 595000000, .max = 650000000 },
+ { .min = 545000000, .max = 600000000 },
+ { .min = 495000000, .max = 555000000 },
+ { .min = 445000000, .max = 500000000 },
+ { .min = 400000000, .max = 450000000 },
+};
+
+static const struct clk_pll_characteristics plla_characteristics = {
+ .input = { .min = 2000000, .max = 32000000 },
+ .num_output = ARRAY_SIZE(plla_outputs),
+ .output = plla_outputs,
+ .icpll = plla_icpll,
+ .out = plla_out,
+};
+
+static u8 pllb_out[] = { 0 };
+
+static const struct clk_range pllb_outputs[] = {
+ { .min = 30000000, .max = 100000000 },
+};
+
+static const struct clk_pll_characteristics pllb_characteristics = {
+ .input = { .min = 2000000, .max = 32000000 },
+ .num_output = ARRAY_SIZE(pllb_outputs),
+ .output = pllb_outputs,
+ .out = pllb_out,
+};
+
+static const struct {
+ char *n;
+ char *p;
+ unsigned long flags;
+ u8 id;
+} at91sam9n12_systemck[] = {
+ /*
+ * ddrck feeds DDR controller and is enabled by bootloader thus we need
+ * to keep it enabled in case there is no Linux consumer for it.
+ */
+ { .n = "ddrck", .p = "masterck_div", .id = 2, .flags = CLK_IS_CRITICAL },
+ { .n = "lcdck", .p = "masterck_div", .id = 3 },
+ { .n = "uhpck", .p = "usbck", .id = 6 },
+ { .n = "udpck", .p = "usbck", .id = 7 },
+ { .n = "pck0", .p = "prog0", .id = 8 },
+ { .n = "pck1", .p = "prog1", .id = 9 },
+};
+
+static const struct clk_pcr_layout at91sam9n12_pcr_layout = {
+ .offset = 0x10c,
+ .cmd = BIT(12),
+ .pid_mask = GENMASK(5, 0),
+ .div_mask = GENMASK(17, 16),
+};
+
+struct pck {
+ char *n;
+ u8 id;
+};
+
+static const struct pck at91sam9n12_periphck[] = {
+ { .n = "pioAB_clk", .id = 2, },
+ { .n = "pioCD_clk", .id = 3, },
+ { .n = "fuse_clk", .id = 4, },
+ { .n = "usart0_clk", .id = 5, },
+ { .n = "usart1_clk", .id = 6, },
+ { .n = "usart2_clk", .id = 7, },
+ { .n = "usart3_clk", .id = 8, },
+ { .n = "twi0_clk", .id = 9, },
+ { .n = "twi1_clk", .id = 10, },
+ { .n = "mci0_clk", .id = 12, },
+ { .n = "spi0_clk", .id = 13, },
+ { .n = "spi1_clk", .id = 14, },
+ { .n = "uart0_clk", .id = 15, },
+ { .n = "uart1_clk", .id = 16, },
+ { .n = "tcb_clk", .id = 17, },
+ { .n = "pwm_clk", .id = 18, },
+ { .n = "adc_clk", .id = 19, },
+ { .n = "dma0_clk", .id = 20, },
+ { .n = "uhphs_clk", .id = 22, },
+ { .n = "udphs_clk", .id = 23, },
+ { .n = "lcdc_clk", .id = 25, },
+ { .n = "sha_clk", .id = 27, },
+ { .n = "ssc0_clk", .id = 28, },
+ { .n = "aes_clk", .id = 29, },
+ { .n = "trng_clk", .id = 30, },
+};
+
+static void __init at91sam9n12_pmc_setup(struct device_node *np)
+{
+ struct clk_range range = CLK_RANGE(0, 0);
+ const char *slck_name, *mainxtal_name;
+ struct pmc_data *at91sam9n12_pmc;
+ const char *parent_names[6];
+ struct regmap *regmap;
+ struct clk_hw *hw;
+ int i;
+ bool bypass;
+
+ i = of_property_match_string(np, "clock-names", "slow_clk");
+ if (i < 0)
+ return;
+
+ slck_name = of_clk_get_parent_name(np, i);
+
+ i = of_property_match_string(np, "clock-names", "main_xtal");
+ if (i < 0)
+ return;
+ mainxtal_name = of_clk_get_parent_name(np, i);
+
+ regmap = device_node_to_regmap(np);
+ if (IS_ERR(regmap))
+ return;
+
+ at91sam9n12_pmc = pmc_data_allocate(PMC_PLLBCK + 1,
+ nck(at91sam9n12_systemck), 31, 0, 2);
+ if (!at91sam9n12_pmc)
+ return;
+
+ hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
+ 50000000);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ bypass = of_property_read_bool(np, "atmel,osc-bypass");
+
+ hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
+ bypass);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ parent_names[0] = "main_rc_osc";
+ parent_names[1] = "main_osc";
+ hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91sam9n12_pmc->chws[PMC_MAIN] = hw;
+
+ hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
+ &at91rm9200_pll_layout, &plla_characteristics);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ hw = at91_clk_register_plldiv(regmap, "plladivck", "pllack");
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91sam9n12_pmc->chws[PMC_PLLACK] = hw;
+
+ hw = at91_clk_register_pll(regmap, "pllbck", "mainck", 1,
+ &at91rm9200_pll_layout, &pllb_characteristics);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91sam9n12_pmc->chws[PMC_PLLBCK] = hw;
+
+ parent_names[0] = slck_name;
+ parent_names[1] = "mainck";
+ parent_names[2] = "plladivck";
+ parent_names[3] = "pllbck";
+ hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
+ parent_names,
+ &at91sam9x5_master_layout,
+ &mck_characteristics,
+ &at91sam9n12_mck_lock);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ hw = at91_clk_register_master_div(regmap, "masterck_div",
+ "masterck_pres",
+ &at91sam9x5_master_layout,
+ &mck_characteristics,
+ &at91sam9n12_mck_lock,
+ CLK_SET_RATE_GATE);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91sam9n12_pmc->chws[PMC_MCK] = hw;
+
+ hw = at91sam9n12_clk_register_usb(regmap, "usbck", "pllbck");
+ if (IS_ERR(hw))
+ goto err_free;
+
+ parent_names[0] = slck_name;
+ parent_names[1] = "mainck";
+ parent_names[2] = "plladivck";
+ parent_names[3] = "pllbck";
+ parent_names[4] = "masterck_div";
+ for (i = 0; i < 2; i++) {
+ char name[6];
+
+ snprintf(name, sizeof(name), "prog%d", i);
+
+ hw = at91_clk_register_programmable(regmap, name,
+ parent_names, 5, i,
+ &at91sam9x5_programmable_layout,
+ NULL);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91sam9n12_pmc->pchws[i] = hw;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(at91sam9n12_systemck); i++) {
+ hw = at91_clk_register_system(regmap, at91sam9n12_systemck[i].n,
+ at91sam9n12_systemck[i].p,
+ at91sam9n12_systemck[i].id,
+ at91sam9n12_systemck[i].flags);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91sam9n12_pmc->shws[at91sam9n12_systemck[i].id] = hw;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(at91sam9n12_periphck); i++) {
+ hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
+ &at91sam9n12_pcr_layout,
+ at91sam9n12_periphck[i].n,
+ "masterck_div",
+ at91sam9n12_periphck[i].id,
+ &range, INT_MIN, 0);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ at91sam9n12_pmc->phws[at91sam9n12_periphck[i].id] = hw;
+ }
+
+ of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9n12_pmc);
+
+ return;
+
+err_free:
+ kfree(at91sam9n12_pmc);
+}
+/*
+ * The TCB is used as the clocksource so its clock is needed early. This means
+ * this can't be a platform driver.
+ */
+CLK_OF_DECLARE(at91sam9n12_pmc, "atmel,at91sam9n12-pmc", at91sam9n12_pmc_setup);
diff --git a/drivers/clk/at91/at91sam9rl.c b/drivers/clk/at91/at91sam9rl.c
index ff47f94a8d..95b02d86d5 100644
--- a/drivers/clk/at91/at91sam9rl.c
+++ b/drivers/clk/at91/at91sam9rl.c
@@ -1,18 +1,15 @@
-// SPDX-License-Identifier: GPL-2.0
-
-#include <driver.h>
-#include <regmap.h>
-#include <stdio.h>
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/clk-provider.h>
#include <mfd/syscon.h>
-
-#include <linux/clk.h>
#include <linux/slab.h>
-#include <linux/types.h>
+#include <stdio.h>
#include <dt-bindings/clock/at91.h>
#include "pmc.h"
+static DEFINE_SPINLOCK(sam9rl_mck_lock);
+
static const struct clk_master_characteristics sam9rl_mck_characteristics = {
.output = { .min = 0, .max = 94000000 },
.divisors = { 1, 2, 4, 0 },
@@ -75,7 +72,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
struct pmc_data *at91sam9rl_pmc;
const char *parent_names[6];
struct regmap *regmap;
- struct clk *hw;
+ struct clk_hw *hw;
int i;
i = of_property_match_string(np, "clock-names", "slow_clk");
@@ -93,9 +90,9 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
if (IS_ERR(regmap))
return;
- at91sam9rl_pmc = pmc_data_allocate(PMC_MAIN + 1,
+ at91sam9rl_pmc = pmc_data_allocate(PMC_PLLACK + 1,
nck(at91sam9rl_systemck),
- nck(at91sam9rl_periphck), 0);
+ nck(at91sam9rl_periphck), 0, 2);
if (!at91sam9rl_pmc)
return;
@@ -111,6 +108,8 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
if (IS_ERR(hw))
goto err_free;
+ at91sam9rl_pmc->chws[PMC_PLLACK] = hw;
+
hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
if (IS_ERR(hw))
goto err_free;
@@ -121,9 +120,19 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "pllack";
parent_names[3] = "utmick";
- hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
- &at91rm9200_master_layout,
- &sam9rl_mck_characteristics);
+ hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
+ parent_names,
+ &at91rm9200_master_layout,
+ &sam9rl_mck_characteristics,
+ &sam9rl_mck_lock);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ hw = at91_clk_register_master_div(regmap, "masterck_div",
+ "masterck_pres",
+ &at91rm9200_master_layout,
+ &sam9rl_mck_characteristics,
+ &sam9rl_mck_lock, CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
@@ -133,23 +142,26 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "pllack";
parent_names[3] = "utmick";
- parent_names[4] = "masterck";
+ parent_names[4] = "masterck_div";
for (i = 0; i < 2; i++) {
- char *name;
+ char name[6];
- name = xasprintf("prog%d", i);
+ snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
parent_names, 5, i,
- &at91rm9200_programmable_layout);
+ &at91rm9200_programmable_layout,
+ NULL);
if (IS_ERR(hw))
goto err_free;
+
+ at91sam9rl_pmc->pchws[i] = hw;
}
for (i = 0; i < ARRAY_SIZE(at91sam9rl_systemck); i++) {
hw = at91_clk_register_system(regmap, at91sam9rl_systemck[i].n,
at91sam9rl_systemck[i].p,
- at91sam9rl_systemck[i].id);
+ at91sam9rl_systemck[i].id, 0);
if (IS_ERR(hw))
goto err_free;
@@ -159,7 +171,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
for (i = 0; i < ARRAY_SIZE(at91sam9rl_periphck); i++) {
hw = at91_clk_register_peripheral(regmap,
at91sam9rl_periphck[i].n,
- "masterck",
+ "masterck_div",
at91sam9rl_periphck[i].id);
if (IS_ERR(hw))
goto err_free;
@@ -167,11 +179,12 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
at91sam9rl_pmc->phws[at91sam9rl_periphck[i].id] = hw;
}
- of_clk_add_provider(np, of_clk_hw_pmc_get, at91sam9rl_pmc);
+ of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9rl_pmc);
return;
err_free:
- pmc_data_free(at91sam9rl_pmc);
+ kfree(at91sam9rl_pmc);
}
-CLK_OF_DECLARE_DRIVER(at91sam9rl_pmc, "atmel,at91sam9rl-pmc", at91sam9rl_pmc_setup);
+
+CLK_OF_DECLARE(at91sam9rl_pmc, "atmel,at91sam9rl-pmc", at91sam9rl_pmc_setup);
diff --git a/drivers/clk/at91/at91sam9x5.c b/drivers/clk/at91/at91sam9x5.c
index baa71aa105..f4dc7ceeea 100644
--- a/drivers/clk/at91/at91sam9x5.c
+++ b/drivers/clk/at91/at91sam9x5.c
@@ -1,18 +1,15 @@
-// SPDX-License-Identifier: GPL-2.0
-
-#include <driver.h>
-#include <regmap.h>
-#include <stdio.h>
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/clk-provider.h>
#include <mfd/syscon.h>
-
-#include <linux/clk.h>
#include <linux/slab.h>
-#include <linux/types.h>
+#include <stdio.h>
#include <dt-bindings/clock/at91.h>
#include "pmc.h"
+static DEFINE_SPINLOCK(mck_lock);
+
static const struct clk_master_characteristics mck_characteristics = {
.output = { .min = 0, .max = 133333333 },
.divisors = { 1, 2, 4, 3 },
@@ -45,9 +42,14 @@ static const struct clk_pll_characteristics plla_characteristics = {
static const struct {
char *n;
char *p;
+ unsigned long flags;
u8 id;
} at91sam9x5_systemck[] = {
- { .n = "ddrck", .p = "masterck", .id = 2 },
+ /*
+ * ddrck feeds DDR controller and is enabled by bootloader thus we need
+ * to keep it enabled in case there is no Linux consumer for it.
+ */
+ { .n = "ddrck", .p = "masterck_div", .id = 2, .flags = CLK_IS_CRITICAL },
{ .n = "smdck", .p = "smdclk", .id = 4 },
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "udpck", .p = "usbck", .id = 7 },
@@ -137,7 +139,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
struct pmc_data *at91sam9x5_pmc;
const char *parent_names[6];
struct regmap *regmap;
- struct clk *hw;
+ struct clk_hw *hw;
int i;
bool bypass;
@@ -156,8 +158,8 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
if (IS_ERR(regmap))
return;
- at91sam9x5_pmc = pmc_data_allocate(PMC_MAIN + 1,
- nck(at91sam9x5_systemck), 31, 0);
+ at91sam9x5_pmc = pmc_data_allocate(PMC_PLLACK + 1,
+ nck(at91sam9x5_systemck), 31, 0, 2);
if (!at91sam9x5_pmc)
return;
@@ -190,6 +192,8 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
if (IS_ERR(hw))
goto err_free;
+ at91sam9x5_pmc->chws[PMC_PLLACK] = hw;
+
hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
if (IS_ERR(hw))
goto err_free;
@@ -200,9 +204,18 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
- hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
- &at91sam9x5_master_layout,
- &mck_characteristics);
+ hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
+ parent_names,
+ &at91sam9x5_master_layout,
+ &mck_characteristics, &mck_lock);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ hw = at91_clk_register_master_div(regmap, "masterck_div",
+ "masterck_pres",
+ &at91sam9x5_master_layout,
+ &mck_characteristics, &mck_lock,
+ CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
@@ -222,23 +235,27 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
- parent_names[4] = "masterck";
+ parent_names[4] = "masterck_div";
for (i = 0; i < 2; i++) {
- char *name;
+ char name[6];
- name = xasprintf("prog%d", i);
+ snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
parent_names, 5, i,
- &at91sam9x5_programmable_layout);
+ &at91sam9x5_programmable_layout,
+ NULL);
if (IS_ERR(hw))
goto err_free;
+
+ at91sam9x5_pmc->pchws[i] = hw;
}
for (i = 0; i < ARRAY_SIZE(at91sam9x5_systemck); i++) {
hw = at91_clk_register_system(regmap, at91sam9x5_systemck[i].n,
at91sam9x5_systemck[i].p,
- at91sam9x5_systemck[i].id);
+ at91sam9x5_systemck[i].id,
+ at91sam9x5_systemck[i].flags);
if (IS_ERR(hw))
goto err_free;
@@ -246,7 +263,8 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
}
if (has_lcdck) {
- hw = at91_clk_register_system(regmap, "lcdck", "masterck", 3);
+ hw = at91_clk_register_system(regmap, "lcdck", "masterck_div",
+ 3, 0);
if (IS_ERR(hw))
goto err_free;
@@ -254,12 +272,12 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
}
for (i = 0; i < ARRAY_SIZE(at91sam9x5_periphck); i++) {
- hw = at91_clk_register_sam9x5_peripheral(regmap,
+ hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&at91sam9x5_pcr_layout,
at91sam9x5_periphck[i].n,
- "masterck",
+ "masterck_div",
at91sam9x5_periphck[i].id,
- &range);
+ &range, INT_MIN, 0);
if (IS_ERR(hw))
goto err_free;
@@ -267,57 +285,57 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
}
for (i = 0; extra_pcks[i].id; i++) {
- hw = at91_clk_register_sam9x5_peripheral(regmap,
+ hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&at91sam9x5_pcr_layout,
extra_pcks[i].n,
- "masterck",
+ "masterck_div",
extra_pcks[i].id,
- &range);
+ &range, INT_MIN, 0);
if (IS_ERR(hw))
goto err_free;
at91sam9x5_pmc->phws[extra_pcks[i].id] = hw;
}
- of_clk_add_provider(np, of_clk_hw_pmc_get, at91sam9x5_pmc);
+ of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9x5_pmc);
return;
err_free:
- pmc_data_free(at91sam9x5_pmc);
+ kfree(at91sam9x5_pmc);
}
static void __init at91sam9g15_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9g15_periphck, true);
}
-CLK_OF_DECLARE_DRIVER(at91sam9g15_pmc, "atmel,at91sam9g15-pmc",
- at91sam9g15_pmc_setup);
+
+CLK_OF_DECLARE(at91sam9g15_pmc, "atmel,at91sam9g15-pmc", at91sam9g15_pmc_setup);
static void __init at91sam9g25_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9g25_periphck, false);
}
-CLK_OF_DECLARE_DRIVER(at91sam9g25_pmc, "atmel,at91sam9g25-pmc",
- at91sam9g25_pmc_setup);
+
+CLK_OF_DECLARE(at91sam9g25_pmc, "atmel,at91sam9g25-pmc", at91sam9g25_pmc_setup);
static void __init at91sam9g35_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9g35_periphck, true);
}
-CLK_OF_DECLARE_DRIVER(at91sam9g35_pmc, "atmel,at91sam9g35-pmc",
- at91sam9g35_pmc_setup);
+
+CLK_OF_DECLARE(at91sam9g35_pmc, "atmel,at91sam9g35-pmc", at91sam9g35_pmc_setup);
static void __init at91sam9x25_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9x25_periphck, false);
}
-CLK_OF_DECLARE_DRIVER(at91sam9x25_pmc, "atmel,at91sam9x25-pmc",
- at91sam9x25_pmc_setup);
+
+CLK_OF_DECLARE(at91sam9x25_pmc, "atmel,at91sam9x25-pmc", at91sam9x25_pmc_setup);
static void __init at91sam9x35_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9x35_periphck, true);
}
-CLK_OF_DECLARE_DRIVER(at91sam9x35_pmc, "atmel,at91sam9x35-pmc",
- at91sam9x35_pmc_setup);
+
+CLK_OF_DECLARE(at91sam9x35_pmc, "atmel,at91sam9x35-pmc", at91sam9x35_pmc_setup);
diff --git a/drivers/clk/at91/clk-audio-pll.c b/drivers/clk/at91/clk-audio-pll.c
index 47bff32fe8..71976567ea 100644
--- a/drivers/clk/at91/clk-audio-pll.c
+++ b/drivers/clk/at91/clk-audio-pll.c
@@ -30,14 +30,14 @@
* parent - fixed parent. No clk_set_parent support
*/
-#include <common.h>
-#include <clock.h>
-#include <of.h>
-#include <linux/list.h>
#include <linux/clk.h>
+#include <linux/printk.h>
+#include <linux/clk-provider.h>
#include <linux/clk/at91_pmc.h>
+#include <of.h>
#include <mfd/syscon.h>
-#include <regmap.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
#include "pmc.h"
@@ -57,35 +57,32 @@
#define AUDIO_PLL_FOUT_MAX 700000000UL
struct clk_audio_frac {
- struct clk clk;
+ struct clk_hw hw;
struct regmap *regmap;
u32 fracr;
u8 nd;
- const char *parent_name;
};
struct clk_audio_pad {
- struct clk clk;
+ struct clk_hw hw;
struct regmap *regmap;
u8 qdaudio;
u8 div;
- const char *parent_name;
};
struct clk_audio_pmc {
- struct clk clk;
+ struct clk_hw hw;
struct regmap *regmap;
u8 qdpmc;
- const char *parent_name;
};
-#define to_clk_audio_frac(clk) container_of(clk, struct clk_audio_frac, clk)
-#define to_clk_audio_pad(clk) container_of(clk, struct clk_audio_pad, clk)
-#define to_clk_audio_pmc(clk) container_of(clk, struct clk_audio_pmc, clk)
+#define to_clk_audio_frac(hw) container_of(hw, struct clk_audio_frac, hw)
+#define to_clk_audio_pad(hw) container_of(hw, struct clk_audio_pad, hw)
+#define to_clk_audio_pmc(hw) container_of(hw, struct clk_audio_pmc, hw)
-static int clk_audio_pll_frac_enable(struct clk *clk)
+static int clk_audio_pll_frac_enable(struct clk_hw *hw)
{
- struct clk_audio_frac *frac = to_clk_audio_frac(clk);
+ struct clk_audio_frac *frac = to_clk_audio_frac(hw);
regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0,
AT91_PMC_AUDIO_PLL_RESETN, 0);
@@ -108,9 +105,9 @@ static int clk_audio_pll_frac_enable(struct clk *clk)
return 0;
}
-static int clk_audio_pll_pad_enable(struct clk *clk)
+static int clk_audio_pll_pad_enable(struct clk_hw *hw)
{
- struct clk_audio_pad *apad_ck = to_clk_audio_pad(clk);
+ struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw);
regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL1,
AT91_PMC_AUDIO_PLL_QDPAD_MASK,
@@ -121,9 +118,9 @@ static int clk_audio_pll_pad_enable(struct clk *clk)
return 0;
}
-static int clk_audio_pll_pmc_enable(struct clk *clk)
+static int clk_audio_pll_pmc_enable(struct clk_hw *hw)
{
- struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(clk);
+ struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw);
regmap_update_bits(apmc_ck->regmap, AT91_PMC_AUDIO_PLL0,
AT91_PMC_AUDIO_PLL_PMCEN |
@@ -133,9 +130,9 @@ static int clk_audio_pll_pmc_enable(struct clk *clk)
return 0;
}
-static void clk_audio_pll_frac_disable(struct clk *clk)
+static void clk_audio_pll_frac_disable(struct clk_hw *hw)
{
- struct clk_audio_frac *frac = to_clk_audio_frac(clk);
+ struct clk_audio_frac *frac = to_clk_audio_frac(hw);
regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0,
AT91_PMC_AUDIO_PLL_PLLEN, 0);
@@ -144,17 +141,17 @@ static void clk_audio_pll_frac_disable(struct clk *clk)
AT91_PMC_AUDIO_PLL_RESETN, 0);
}
-static void clk_audio_pll_pad_disable(struct clk *clk)
+static void clk_audio_pll_pad_disable(struct clk_hw *hw)
{
- struct clk_audio_pad *apad_ck = to_clk_audio_pad(clk);
+ struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw);
regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL0,
AT91_PMC_AUDIO_PLL_PADEN, 0);
}
-static void clk_audio_pll_pmc_disable(struct clk *clk)
+static void clk_audio_pll_pmc_disable(struct clk_hw *hw)
{
- struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(clk);
+ struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw);
regmap_update_bits(apmc_ck->regmap, AT91_PMC_AUDIO_PLL0,
AT91_PMC_AUDIO_PLL_PMCEN, 0);
@@ -174,10 +171,10 @@ static unsigned long clk_audio_pll_fout(unsigned long parent_rate,
return parent_rate * (nd + 1) + fr;
}
-static unsigned long clk_audio_pll_frac_recalc_rate(struct clk *clk,
+static unsigned long clk_audio_pll_frac_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_audio_frac *frac = to_clk_audio_frac(clk);
+ struct clk_audio_frac *frac = to_clk_audio_frac(hw);
unsigned long fout;
fout = clk_audio_pll_fout(parent_rate, frac->nd, frac->fracr);
@@ -188,10 +185,10 @@ static unsigned long clk_audio_pll_frac_recalc_rate(struct clk *clk,
return fout;
}
-static unsigned long clk_audio_pll_pad_recalc_rate(struct clk *clk,
+static unsigned long clk_audio_pll_pad_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_audio_pad *apad_ck = to_clk_audio_pad(clk);
+ struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw);
unsigned long apad_rate = 0;
if (apad_ck->qdaudio && apad_ck->div)
@@ -203,10 +200,10 @@ static unsigned long clk_audio_pll_pad_recalc_rate(struct clk *clk,
return apad_rate;
}
-static unsigned long clk_audio_pll_pmc_recalc_rate(struct clk *clk,
+static unsigned long clk_audio_pll_pmc_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(clk);
+ struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw);
unsigned long apmc_rate = 0;
apmc_rate = parent_rate / (apmc_ck->qdpmc + 1);
@@ -245,10 +242,10 @@ static int clk_audio_pll_frac_compute_frac(unsigned long rate,
return 0;
}
-static long clk_audio_pll_pad_round_rate(struct clk *clk, unsigned long rate,
+static long clk_audio_pll_pad_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
- struct clk *pclk = clk_get_parent(clk);
+ struct clk_hw *pclk = clk_hw_get_parent(hw);
long best_rate = -EINVAL;
unsigned long best_parent_rate;
unsigned long tmp_qd;
@@ -278,7 +275,7 @@ static long clk_audio_pll_pad_round_rate(struct clk *clk, unsigned long rate,
if (div == 2 && tmp_qd % 3 == 0)
continue;
- best_parent_rate = clk_round_rate(pclk,
+ best_parent_rate = clk_hw_round_rate(pclk,
rate * tmp_qd * div);
tmp_rate = best_parent_rate / (div * tmp_qd);
tmp_diff = abs(rate - tmp_rate);
@@ -296,10 +293,10 @@ static long clk_audio_pll_pad_round_rate(struct clk *clk, unsigned long rate,
return best_rate;
}
-static long clk_audio_pll_pmc_round_rate(struct clk *clk, unsigned long rate,
+static long clk_audio_pll_pmc_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
- struct clk *pclk = clk_get_parent(clk);
+ struct clk_hw *pclk = clk_hw_get_parent(hw);
long best_rate = -EINVAL;
unsigned long best_parent_rate = 0;
u32 tmp_qd = 0, div;
@@ -313,10 +310,10 @@ static long clk_audio_pll_pmc_round_rate(struct clk *clk, unsigned long rate,
if (!rate)
return 0;
- best_parent_rate = clk_round_rate(pclk, 1);
+ best_parent_rate = clk_round_rate(&pclk->clk, 1);
div = max(best_parent_rate / rate, 1UL);
for (; div <= AUDIO_PLL_QDPMC_MAX; div++) {
- best_parent_rate = clk_round_rate(pclk, rate * div);
+ best_parent_rate = clk_round_rate(&pclk->clk, rate * div);
tmp_rate = best_parent_rate / div;
tmp_diff = abs(rate - tmp_rate);
@@ -336,10 +333,10 @@ static long clk_audio_pll_pmc_round_rate(struct clk *clk, unsigned long rate,
return best_rate;
}
-static int clk_audio_pll_frac_set_rate(struct clk *clk, unsigned long rate,
+static int clk_audio_pll_frac_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_audio_frac *frac = to_clk_audio_frac(clk);
+ struct clk_audio_frac *frac = to_clk_audio_frac(hw);
unsigned long fracr, nd;
int ret;
@@ -359,10 +356,10 @@ static int clk_audio_pll_frac_set_rate(struct clk *clk, unsigned long rate,
return 0;
}
-static int clk_audio_pll_pad_set_rate(struct clk *clk, unsigned long rate,
+static int clk_audio_pll_pad_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_audio_pad *apad_ck = to_clk_audio_pad(clk);
+ struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw);
u8 tmp_div;
pr_debug("A PLL/PAD: %s, rate = %lu (parent_rate = %lu)\n", __func__,
@@ -383,10 +380,10 @@ static int clk_audio_pll_pad_set_rate(struct clk *clk, unsigned long rate,
return 0;
}
-static int clk_audio_pll_pmc_set_rate(struct clk *clk, unsigned long rate,
+static int clk_audio_pll_pmc_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(clk);
+ struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw);
if (!rate)
return -EINVAL;
@@ -422,91 +419,94 @@ static const struct clk_ops audio_pll_pmc_ops = {
.set_rate = clk_audio_pll_pmc_set_rate,
};
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_audio_pll_frac(struct regmap *regmap, const char *name,
const char *parent_name)
{
struct clk_audio_frac *frac_ck;
+ struct clk_init_data init = {};
int ret;
frac_ck = kzalloc(sizeof(*frac_ck), GFP_KERNEL);
if (!frac_ck)
return ERR_PTR(-ENOMEM);
- frac_ck->clk.name = name;
- frac_ck->clk.ops = &audio_pll_frac_ops;
- frac_ck->parent_name = parent_name;
- frac_ck->clk.parent_names = &frac_ck->parent_name;
- frac_ck->clk.num_parents = 1;
- /* frac_ck->clk.flags = CLK_SET_RATE_GATE; */
+ init.name = name;
+ init.ops = &audio_pll_frac_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = CLK_SET_RATE_GATE;
+ frac_ck->hw.init = &init;
frac_ck->regmap = regmap;
- ret = clk_register(&frac_ck->clk);
+ ret = clk_hw_register(NULL, &frac_ck->hw);
if (ret) {
kfree(frac_ck);
return ERR_PTR(ret);
}
- return &frac_ck->clk;
+ return &frac_ck->hw;
}
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_audio_pll_pad(struct regmap *regmap, const char *name,
const char *parent_name)
{
struct clk_audio_pad *apad_ck;
+ struct clk_init_data init;
int ret;
apad_ck = kzalloc(sizeof(*apad_ck), GFP_KERNEL);
if (!apad_ck)
return ERR_PTR(-ENOMEM);
- apad_ck->clk.name = name;
- apad_ck->clk.ops = &audio_pll_pad_ops;
- apad_ck->parent_name = parent_name;
- apad_ck->clk.parent_names = &apad_ck->parent_name;
- apad_ck->clk.num_parents = 1;
- /* apad_ck->clk.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
- CLK_SET_RATE_PARENT; */
+ init.name = name;
+ init.ops = &audio_pll_pad_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
+ CLK_SET_RATE_PARENT;
+ apad_ck->hw.init = &init;
apad_ck->regmap = regmap;
- ret = clk_register(&apad_ck->clk);
+ ret = clk_hw_register(NULL, &apad_ck->hw);
if (ret) {
kfree(apad_ck);
return ERR_PTR(ret);
}
- return &apad_ck->clk;
+ return &apad_ck->hw;
}
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_audio_pll_pmc(struct regmap *regmap, const char *name,
const char *parent_name)
{
struct clk_audio_pmc *apmc_ck;
+ struct clk_init_data init;
int ret;
apmc_ck = kzalloc(sizeof(*apmc_ck), GFP_KERNEL);
if (!apmc_ck)
return ERR_PTR(-ENOMEM);
- apmc_ck->clk.name = name;
- apmc_ck->clk.ops = &audio_pll_pmc_ops;
- apmc_ck->parent_name = parent_name;
- apmc_ck->clk.parent_names = &apmc_ck->parent_name;
- apmc_ck->clk.num_parents = 1;
- /* apmc_ck.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
- CLK_SET_RATE_PARENT; */
+ init.name = name;
+ init.ops = &audio_pll_pmc_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
+ CLK_SET_RATE_PARENT;
+ apmc_ck->hw.init = &init;
apmc_ck->regmap = regmap;
- ret = clk_register(&apmc_ck->clk);
+ ret = clk_hw_register(NULL, &apmc_ck->hw);
if (ret) {
kfree(apmc_ck);
return ERR_PTR(ret);
}
- return &apmc_ck->clk;
+ return &apmc_ck->hw;
}
diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c
index 56b800facb..e59cff2bdf 100644
--- a/drivers/clk/at91/clk-generated.c
+++ b/drivers/clk/at91/clk-generated.c
@@ -6,80 +6,99 @@
* Based on clk-programmable & clk-peripheral drivers by Boris BREZILLON.
*/
-#include <common.h>
-#include <clock.h>
-#include <io.h>
-#include <linux/list.h>
-#include <linux/clk.h>
+#include <linux/bitfield.h>
+#include <linux/printk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/clk/at91_pmc.h>
+#include <of.h>
#include <mfd/syscon.h>
-#include <regmap.h>
-#include <linux/bitfield.h>
+#include <linux/regmap.h>
#include "pmc.h"
#define GENERATED_MAX_DIV 255
-#define GCK_INDEX_DT_AUDIO_PLL 5
-
struct clk_generated {
- struct clk hw;
+ struct clk_hw hw;
struct regmap *regmap;
struct clk_range range;
+ spinlock_t *lock;
+ u32 *mux_table;
u32 id;
u32 gckdiv;
const struct clk_pcr_layout *layout;
+ struct at91_clk_pms pms;
u8 parent_id;
- bool audio_pll_allowed;
+ int chg_pid;
};
#define to_clk_generated(hw) \
container_of(hw, struct clk_generated, hw)
-static int clk_generated_enable(struct clk *hw)
+static int clk_generated_set(struct clk_generated *gck, int status)
{
- struct clk_generated *gck = to_clk_generated(hw);
-
- pr_debug("GCLK: %s, gckdiv = %d, parent id = %d\n",
- __func__, gck->gckdiv, gck->parent_id);
+ unsigned long flags;
+ unsigned int enable = status ? AT91_PMC_PCR_GCKEN : 0;
+ spin_lock_irqsave(gck->lock, flags);
regmap_write(gck->regmap, gck->layout->offset,
(gck->id & gck->layout->pid_mask));
regmap_update_bits(gck->regmap, gck->layout->offset,
AT91_PMC_PCR_GCKDIV_MASK | gck->layout->gckcss_mask |
- gck->layout->cmd | AT91_PMC_PCR_GCKEN,
+ gck->layout->cmd | enable,
field_prep(gck->layout->gckcss_mask, gck->parent_id) |
gck->layout->cmd |
FIELD_PREP(AT91_PMC_PCR_GCKDIV_MASK, gck->gckdiv) |
- AT91_PMC_PCR_GCKEN);
+ enable);
+ spin_unlock_irqrestore(gck->lock, flags);
+
return 0;
}
-static void clk_generated_disable(struct clk *hw)
+static int clk_generated_enable(struct clk_hw *hw)
{
struct clk_generated *gck = to_clk_generated(hw);
+ pr_debug("GCLK: %s, gckdiv = %d, parent id = %d\n",
+ __func__, gck->gckdiv, gck->parent_id);
+
+ clk_generated_set(gck, 1);
+
+ return 0;
+}
+
+static void clk_generated_disable(struct clk_hw *hw)
+{
+ struct clk_generated *gck = to_clk_generated(hw);
+ unsigned long flags;
+
+ spin_lock_irqsave(gck->lock, flags);
regmap_write(gck->regmap, gck->layout->offset,
(gck->id & gck->layout->pid_mask));
regmap_update_bits(gck->regmap, gck->layout->offset,
gck->layout->cmd | AT91_PMC_PCR_GCKEN,
gck->layout->cmd);
+ spin_unlock_irqrestore(gck->lock, flags);
}
-static int clk_generated_is_enabled(struct clk *hw)
+static int clk_generated_is_enabled(struct clk_hw *hw)
{
struct clk_generated *gck = to_clk_generated(hw);
+ unsigned long flags;
unsigned int status;
+ spin_lock_irqsave(gck->lock, flags);
regmap_write(gck->regmap, gck->layout->offset,
(gck->id & gck->layout->pid_mask));
regmap_read(gck->regmap, gck->layout->offset, &status);
+ spin_unlock_irqrestore(gck->lock, flags);
- return status & AT91_PMC_PCR_GCKEN ? 1 : 0;
+ return !!(status & AT91_PMC_PCR_GCKEN);
}
static unsigned long
-clk_generated_recalc_rate(struct clk *hw,
+clk_generated_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_generated *gck = to_clk_generated(hw);
@@ -88,18 +107,22 @@ clk_generated_recalc_rate(struct clk *hw,
}
/* No modification of hardware as we have the flag CLK_SET_PARENT_GATE set */
-static int clk_generated_set_parent(struct clk *hw, u8 index)
+static int clk_generated_set_parent(struct clk_hw *hw, u8 index)
{
struct clk_generated *gck = to_clk_generated(hw);
- if (index >= clk_get_num_parents(hw))
+ if (index >= clk_hw_get_num_parents(hw))
return -EINVAL;
- gck->parent_id = index;
+ if (gck->mux_table)
+ gck->parent_id = clk_mux_index_to_val(gck->mux_table, 0, index);
+ else
+ gck->parent_id = index;
+
return 0;
}
-static int clk_generated_get_parent(struct clk *hw)
+static int clk_generated_get_parent(struct clk_hw *hw)
{
struct clk_generated *gck = to_clk_generated(hw);
@@ -107,7 +130,7 @@ static int clk_generated_get_parent(struct clk *hw)
}
/* No modification of hardware as we have the flag CLK_SET_RATE_GATE set */
-static int clk_generated_set_rate(struct clk *hw,
+static int clk_generated_set_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long parent_rate)
{
@@ -150,53 +173,58 @@ static const struct clk_ops generated_ops = {
static void clk_generated_startup(struct clk_generated *gck)
{
u32 tmp;
+ unsigned long flags;
+ spin_lock_irqsave(gck->lock, flags);
regmap_write(gck->regmap, gck->layout->offset,
(gck->id & gck->layout->pid_mask));
regmap_read(gck->regmap, gck->layout->offset, &tmp);
+ spin_unlock_irqrestore(gck->lock, flags);
gck->parent_id = field_get(gck->layout->gckcss_mask, tmp);
gck->gckdiv = FIELD_GET(AT91_PMC_PCR_GCKDIV_MASK, tmp);
}
-struct clk * __init
-at91_clk_register_generated(struct regmap *regmap,
+struct clk_hw * __init
+at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
const struct clk_pcr_layout *layout,
const char *name, const char **parent_names,
- u8 num_parents, u8 id, bool pll_audio,
- const struct clk_range *range)
+ u32 *mux_table, u8 num_parents, u8 id,
+ const struct clk_range *range,
+ int chg_pid)
{
- size_t parents_array_size;
struct clk_generated *gck;
- struct clk *hw;
+ struct clk_init_data init;
+ struct clk_hw *hw;
int ret;
gck = kzalloc(sizeof(*gck), GFP_KERNEL);
if (!gck)
return ERR_PTR(-ENOMEM);
- gck->id = id;
- gck->hw.name = name;
- gck->hw.ops = &generated_ops;
+ init.name = name;
+ init.ops = &generated_ops;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+ init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
+ if (chg_pid >= 0)
+ init.flags |= CLK_SET_RATE_PARENT;
- parents_array_size = num_parents * sizeof(gck->hw.parent_names[0]);
- gck->hw.parent_names = xmemdup(parent_names, parents_array_size);
- gck->hw.num_parents = num_parents;
-
- /* gck->hw.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | CLK_SET_PARENT; */
+ gck->id = id;
+ gck->hw.init = &init;
gck->regmap = regmap;
+ gck->lock = lock;
gck->range = *range;
- gck->audio_pll_allowed = pll_audio;
+ gck->chg_pid = chg_pid;
gck->layout = layout;
+ gck->mux_table = mux_table;
clk_generated_startup(gck);
hw = &gck->hw;
- ret = clk_register(&gck->hw);
+ ret = clk_hw_register(NULL, &gck->hw);
if (ret) {
kfree(gck);
hw = ERR_PTR(ret);
- } else {
- pmc_register_id(id);
}
return hw;
diff --git a/drivers/clk/at91/clk-h32mx.c b/drivers/clk/at91/clk-h32mx.c
index 6052886cca..e5b98692a9 100644
--- a/drivers/clk/at91/clk-h32mx.c
+++ b/drivers/clk/at91/clk-h32mx.c
@@ -7,27 +7,26 @@
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
*/
-#include <common.h>
-#include <clock.h>
-#include <linux/list.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/clk/at91_pmc.h>
-#include <regmap.h>
-
+#include <of.h>
+#include <linux/regmap.h>
+#include <mfd/syscon.h>
+#include <linux/printk.h>
#include "pmc.h"
#define H32MX_MAX_FREQ 90000000
struct clk_sama5d4_h32mx {
- struct clk hw;
+ struct clk_hw hw;
struct regmap *regmap;
- const char *parent;
};
#define to_clk_sama5d4_h32mx(hw) container_of(hw, struct clk_sama5d4_h32mx, hw)
-static unsigned long clk_sama5d4_h32mx_recalc_rate(struct clk *hw,
+static unsigned long clk_sama5d4_h32mx_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_sama5d4_h32mx *h32mxclk = to_clk_sama5d4_h32mx(hw);
@@ -42,7 +41,7 @@ static unsigned long clk_sama5d4_h32mx_recalc_rate(struct clk *hw,
return parent_rate;
}
-static long clk_sama5d4_h32mx_round_rate(struct clk *hw, unsigned long rate,
+static long clk_sama5d4_h32mx_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
unsigned long div;
@@ -59,7 +58,7 @@ static long clk_sama5d4_h32mx_round_rate(struct clk *hw, unsigned long rate,
return *parent_rate;
}
-static int clk_sama5d4_h32mx_set_rate(struct clk *hw, unsigned long rate,
+static int clk_sama5d4_h32mx_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_sama5d4_h32mx *h32mxclk = to_clk_sama5d4_h32mx(hw);
@@ -83,27 +82,28 @@ static const struct clk_ops h32mx_ops = {
.set_rate = clk_sama5d4_h32mx_set_rate,
};
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_h32mx(struct regmap *regmap, const char *name,
const char *parent_name)
{
struct clk_sama5d4_h32mx *h32mxclk;
+ struct clk_init_data init;
int ret;
h32mxclk = kzalloc(sizeof(*h32mxclk), GFP_KERNEL);
if (!h32mxclk)
return ERR_PTR(-ENOMEM);
- h32mxclk->parent = parent_name;
- h32mxclk->hw.name = name;
- h32mxclk->hw.ops = &h32mx_ops;
- h32mxclk->hw.parent_names = &h32mxclk->parent;
- h32mxclk->hw.num_parents = 1;
- /* h32mxclk.hw.flags = CLK_SET_RATE_GATE; */
+ init.name = name;
+ init.ops = &h32mx_ops;
+ init.parent_names = parent_name ? &parent_name : NULL;
+ init.num_parents = parent_name ? 1 : 0;
+ init.flags = CLK_SET_RATE_GATE;
+ h32mxclk->hw.init = &init;
h32mxclk->regmap = regmap;
- ret = clk_register(&h32mxclk->hw);
+ ret = clk_hw_register(NULL, &h32mxclk->hw);
if (ret) {
kfree(h32mxclk);
return ERR_PTR(ret);
diff --git a/drivers/clk/at91/clk-i2s-mux.c b/drivers/clk/at91/clk-i2s-mux.c
index 1418ec8662..71ef2e6386 100644
--- a/drivers/clk/at91/clk-i2s-mux.c
+++ b/drivers/clk/at91/clk-i2s-mux.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2018 Microchip Technology Inc,
* Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
@@ -6,33 +6,27 @@
*
*/
-#include <common.h>
-#include <clock.h>
+#include <linux/clk-provider.h>
#include <of.h>
-#include <linux/list.h>
-#include <linux/clk.h>
-#include <linux/clk/at91_pmc.h>
#include <mfd/syscon.h>
-#include <regmap.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
#include <soc/at91/atmel-sfr.h>
#include "pmc.h"
-#define I2S_MUX_SOURCE_MAX 2
-
struct clk_i2s_mux {
- struct clk clk;
+ struct clk_hw hw;
struct regmap *regmap;
u8 bus_id;
- const char *parent_names[I2S_MUX_SOURCE_MAX];
};
-#define to_clk_i2s_mux(clk) container_of(clk, struct clk_i2s_mux, clk)
+#define to_clk_i2s_mux(hw) container_of(hw, struct clk_i2s_mux, hw)
-static int clk_i2s_mux_get_parent(struct clk *clk)
+static int clk_i2s_mux_get_parent(struct clk_hw *hw)
{
- struct clk_i2s_mux *mux = to_clk_i2s_mux(clk);
+ struct clk_i2s_mux *mux = to_clk_i2s_mux(hw);
u32 val;
regmap_read(mux->regmap, AT91_SFR_I2SCLKSEL, &val);
@@ -40,26 +34,25 @@ static int clk_i2s_mux_get_parent(struct clk *clk)
return (val & BIT(mux->bus_id)) >> mux->bus_id;
}
-static int clk_i2s_mux_set_parent(struct clk *clk, u8 index)
+static int clk_i2s_mux_set_parent(struct clk_hw *hw, u8 index)
{
- struct clk_i2s_mux *mux = to_clk_i2s_mux(clk);
+ struct clk_i2s_mux *mux = to_clk_i2s_mux(hw);
return regmap_update_bits(mux->regmap, AT91_SFR_I2SCLKSEL,
BIT(mux->bus_id), index << mux->bus_id);
}
static const struct clk_ops clk_i2s_mux_ops = {
- .set_rate = clk_parent_set_rate,
- .round_rate = clk_parent_round_rate,
.get_parent = clk_i2s_mux_get_parent,
.set_parent = clk_i2s_mux_set_parent,
};
-struct clk * __init
+struct clk_hw * __init
at91_clk_i2s_mux_register(struct regmap *regmap, const char *name,
const char * const *parent_names,
unsigned int num_parents, u8 bus_id)
{
+ struct clk_init_data init = {};
struct clk_i2s_mux *i2s_ck;
int ret;
@@ -67,21 +60,20 @@ at91_clk_i2s_mux_register(struct regmap *regmap, const char *name,
if (!i2s_ck)
return ERR_PTR(-ENOMEM);
- i2s_ck->clk.name = name;
- i2s_ck->clk.ops = &clk_i2s_mux_ops;
- memcpy(i2s_ck->parent_names, parent_names,
- num_parents * sizeof(i2s_ck->parent_names[0]));
- i2s_ck->clk.parent_names = &i2s_ck->parent_names[0];
- i2s_ck->clk.num_parents = num_parents;
+ init.name = name;
+ init.ops = &clk_i2s_mux_ops;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+ i2s_ck->hw.init = &init;
i2s_ck->bus_id = bus_id;
i2s_ck->regmap = regmap;
- ret = clk_register(&i2s_ck->clk);
+ ret = clk_hw_register(NULL, &i2s_ck->hw);
if (ret) {
kfree(i2s_ck);
return ERR_PTR(ret);
}
- return &i2s_ck->clk;
+ return &i2s_ck->hw;
}
diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c
index 08abb1673b..a1dd327b56 100644
--- a/drivers/clk/at91/clk-main.c
+++ b/drivers/clk/at91/clk-main.c
@@ -2,21 +2,22 @@
/*
* Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
*/
-#include <common.h>
-#include <clock.h>
-#include <linux/list.h>
-#include <linux/clk.h>
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/clk/at91_pmc.h>
+#include <clock.h>
#include <mfd/syscon.h>
-#include <regmap.h>
+#include <linux/regmap.h>
+#include <linux/printk.h>
#include "pmc.h"
#define SLOW_CLOCK_FREQ 32768
#define MAINF_DIV 16
-#define MAINFRDY_TIMEOUT (((MAINF_DIV + 1) * SECOND) / \
+#define MAINFRDY_TIMEOUT (((MAINF_DIV + 1) * USEC_PER_SEC) / \
SLOW_CLOCK_FREQ)
-#define MAINF_LOOP_MIN_WAIT (SECOND / SLOW_CLOCK_FREQ)
+#define MAINF_LOOP_MIN_WAIT (USEC_PER_SEC / SLOW_CLOCK_FREQ)
#define MAINF_LOOP_MAX_WAIT MAINFRDY_TIMEOUT
#define MOR_KEY_MASK (0xff << 16)
@@ -26,36 +27,38 @@
AT91_PMC_OSCBYPASS)) ? 1 : 0)
struct clk_main_osc {
- struct clk clk;
+ struct clk_hw hw;
struct regmap *regmap;
- const char *parent;
+ struct at91_clk_pms pms;
};
-#define to_clk_main_osc(clk) container_of(clk, struct clk_main_osc, clk)
+#define to_clk_main_osc(hw) container_of(hw, struct clk_main_osc, hw)
struct clk_main_rc_osc {
- struct clk clk;
+ struct clk_hw hw;
struct regmap *regmap;
unsigned long frequency;
+ unsigned long accuracy;
+ struct at91_clk_pms pms;
};
-#define to_clk_main_rc_osc(clk) container_of(clk, struct clk_main_rc_osc, clk)
+#define to_clk_main_rc_osc(hw) container_of(hw, struct clk_main_rc_osc, hw)
struct clk_rm9200_main {
- struct clk clk;
+ struct clk_hw hw;
struct regmap *regmap;
- const char *parent;
};
-#define to_clk_rm9200_main(clk) container_of(clk, struct clk_rm9200_main, clk)
+#define to_clk_rm9200_main(hw) container_of(hw, struct clk_rm9200_main, hw)
struct clk_sam9x5_main {
- struct clk clk;
+ struct clk_hw hw;
struct regmap *regmap;
+ struct at91_clk_pms pms;
u8 parent;
};
-#define to_clk_sam9x5_main(clk) container_of(clk, struct clk_sam9x5_main, clk)
+#define to_clk_sam9x5_main(hw) container_of(hw, struct clk_sam9x5_main, hw)
static inline bool clk_main_osc_ready(struct regmap *regmap)
{
@@ -66,9 +69,9 @@ static inline bool clk_main_osc_ready(struct regmap *regmap)
return status & AT91_PMC_MOSCS;
}
-static int clk_main_osc_enable(struct clk *clk)
+static int clk_main_osc_prepare(struct clk_hw *hw)
{
- struct clk_main_osc *osc = to_clk_main_osc(clk);
+ struct clk_main_osc *osc = to_clk_main_osc(hw);
struct regmap *regmap = osc->regmap;
u32 tmp;
@@ -84,14 +87,14 @@ static int clk_main_osc_enable(struct clk *clk)
}
while (!clk_main_osc_ready(regmap))
- barrier();
+ cpu_relax();
return 0;
}
-static void clk_main_osc_disable(struct clk *clk)
+static void clk_main_osc_unprepare(struct clk_hw *hw)
{
- struct clk_main_osc *osc = to_clk_main_osc(clk);
+ struct clk_main_osc *osc = to_clk_main_osc(hw);
struct regmap *regmap = osc->regmap;
u32 tmp;
@@ -106,9 +109,9 @@ static void clk_main_osc_disable(struct clk *clk)
regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_KEY);
}
-static int clk_main_osc_is_enabled(struct clk *clk)
+static int clk_main_osc_is_prepared(struct clk_hw *hw)
{
- struct clk_main_osc *osc = to_clk_main_osc(clk);
+ struct clk_main_osc *osc = to_clk_main_osc(hw);
struct regmap *regmap = osc->regmap;
u32 tmp, status;
@@ -122,45 +125,52 @@ static int clk_main_osc_is_enabled(struct clk *clk)
}
static const struct clk_ops main_osc_ops = {
- .enable = clk_main_osc_enable,
- .disable = clk_main_osc_disable,
- .is_enabled = clk_main_osc_is_enabled,
+ .enable = clk_main_osc_prepare,
+ .disable = clk_main_osc_unprepare,
+ .is_enabled = clk_main_osc_is_prepared,
};
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_main_osc(struct regmap *regmap,
const char *name,
const char *parent_name,
bool bypass)
{
struct clk_main_osc *osc;
+ struct clk_init_data init;
+ struct clk_hw *hw;
int ret;
if (!name || !parent_name)
return ERR_PTR(-EINVAL);
- osc = xzalloc(sizeof(*osc));
+ osc = kzalloc(sizeof(*osc), GFP_KERNEL);
+ if (!osc)
+ return ERR_PTR(-ENOMEM);
- osc->parent = parent_name;
- osc->clk.name = name;
- osc->clk.ops = &main_osc_ops;
- osc->clk.parent_names = &osc->parent;
- osc->clk.num_parents = 1;
+ init.name = name;
+ init.ops = &main_osc_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = CLK_IGNORE_UNUSED;
+
+ osc->hw.init = &init;
osc->regmap = regmap;
if (bypass)
- regmap_write_bits(regmap,
- AT91_CKGR_MOR, MOR_KEY_MASK |
- AT91_PMC_MOSCEN,
- AT91_PMC_OSCBYPASS | AT91_PMC_KEY);
+ regmap_update_bits(regmap,
+ AT91_CKGR_MOR, MOR_KEY_MASK |
+ AT91_PMC_OSCBYPASS,
+ AT91_PMC_OSCBYPASS | AT91_PMC_KEY);
- ret = clk_register(&osc->clk);
+ hw = &osc->hw;
+ ret = clk_hw_register(NULL, &osc->hw);
if (ret) {
- free(osc);
- return ERR_PTR(ret);
+ kfree(osc);
+ hw = ERR_PTR(ret);
}
- return &osc->clk;
+ return hw;
}
static bool clk_main_rc_osc_ready(struct regmap *regmap)
@@ -169,31 +179,31 @@ static bool clk_main_rc_osc_ready(struct regmap *regmap)
regmap_read(regmap, AT91_PMC_SR, &status);
- return status & AT91_PMC_MOSCRCS;
+ return !!(status & AT91_PMC_MOSCRCS);
}
-static int clk_main_rc_osc_enable(struct clk *clk)
+static int clk_main_rc_osc_prepare(struct clk_hw *hw)
{
- struct clk_main_rc_osc *osc = to_clk_main_rc_osc(clk);
+ struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
struct regmap *regmap = osc->regmap;
unsigned int mor;
regmap_read(regmap, AT91_CKGR_MOR, &mor);
if (!(mor & AT91_PMC_MOSCRCEN))
- regmap_write_bits(regmap, AT91_CKGR_MOR,
- MOR_KEY_MASK | AT91_PMC_MOSCRCEN,
- AT91_PMC_MOSCRCEN | AT91_PMC_KEY);
+ regmap_update_bits(regmap, AT91_CKGR_MOR,
+ MOR_KEY_MASK | AT91_PMC_MOSCRCEN,
+ AT91_PMC_MOSCRCEN | AT91_PMC_KEY);
while (!clk_main_rc_osc_ready(regmap))
- barrier();
+ cpu_relax();
return 0;
}
-static void clk_main_rc_osc_disable(struct clk *clk)
+static void clk_main_rc_osc_unprepare(struct clk_hw *hw)
{
- struct clk_main_rc_osc *osc = to_clk_main_rc_osc(clk);
+ struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
struct regmap *regmap = osc->regmap;
unsigned int mor;
@@ -202,13 +212,13 @@ static void clk_main_rc_osc_disable(struct clk *clk)
if (!(mor & AT91_PMC_MOSCRCEN))
return;
- regmap_write_bits(regmap, AT91_CKGR_MOR,
- MOR_KEY_MASK | AT91_PMC_MOSCRCEN, AT91_PMC_KEY);
+ regmap_update_bits(regmap, AT91_CKGR_MOR,
+ MOR_KEY_MASK | AT91_PMC_MOSCRCEN, AT91_PMC_KEY);
}
-static int clk_main_rc_osc_is_enabled(struct clk *clk)
+static int clk_main_rc_osc_is_prepared(struct clk_hw *hw)
{
- struct clk_main_rc_osc *osc = to_clk_main_rc_osc(clk);
+ struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
struct regmap *regmap = osc->regmap;
unsigned int mor, status;
@@ -218,61 +228,71 @@ static int clk_main_rc_osc_is_enabled(struct clk *clk)
return (mor & AT91_PMC_MOSCRCEN) && (status & AT91_PMC_MOSCRCS);
}
-static unsigned long clk_main_rc_osc_recalc_rate(struct clk *clk,
+static unsigned long clk_main_rc_osc_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_main_rc_osc *osc = to_clk_main_rc_osc(clk);
+ struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
return osc->frequency;
}
static const struct clk_ops main_rc_osc_ops = {
- .enable = clk_main_rc_osc_enable,
- .disable = clk_main_rc_osc_disable,
- .is_enabled = clk_main_rc_osc_is_enabled,
+ .enable = clk_main_rc_osc_prepare,
+ .disable = clk_main_rc_osc_unprepare,
+ .is_enabled = clk_main_rc_osc_is_prepared,
.recalc_rate = clk_main_rc_osc_recalc_rate,
};
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_main_rc_osc(struct regmap *regmap,
const char *name,
u32 frequency, u32 accuracy)
{
- int ret;
struct clk_main_rc_osc *osc;
+ struct clk_init_data init;
+ struct clk_hw *hw;
+ int ret;
if (!name || !frequency)
return ERR_PTR(-EINVAL);
- osc = xzalloc(sizeof(*osc));
+ osc = kzalloc(sizeof(*osc), GFP_KERNEL);
+ if (!osc)
+ return ERR_PTR(-ENOMEM);
- osc->clk.name = name;
- osc->clk.ops = &main_rc_osc_ops;
- osc->clk.parent_names = NULL;
- osc->clk.num_parents = 0;
+ init.name = name;
+ init.ops = &main_rc_osc_ops;
+ init.parent_names = NULL;
+ init.num_parents = 0;
+ init.flags = CLK_IGNORE_UNUSED;
+ osc->hw.init = &init;
osc->regmap = regmap;
osc->frequency = frequency;
+ osc->accuracy = accuracy;
- ret = clk_register(&osc->clk);
+ hw = &osc->hw;
+ ret = clk_hw_register(NULL, hw);
if (ret) {
kfree(osc);
- return ERR_PTR(ret);
+ hw = ERR_PTR(ret);
}
- return &osc->clk;
+ return hw;
}
static int clk_main_probe_frequency(struct regmap *regmap)
{
+ u64 start_time;
unsigned int mcfr;
- uint64_t start = get_time_ns();
+ start_time = get_time_ns();
do {
regmap_read(regmap, AT91_CKGR_MCFR, &mcfr);
if (mcfr & AT91_PMC_MAINRDY)
return 0;
- } while (!is_timeout(start, MAINFRDY_TIMEOUT * USECOND));
+ udelay(MAINF_LOOP_MIN_WAIT);
+ } while (!is_timeout(start_time, MAINFRDY_TIMEOUT * NSEC_PER_USEC));
return -ETIMEDOUT;
}
@@ -293,44 +313,46 @@ static unsigned long clk_main_recalc_rate(struct regmap *regmap,
return ((mcfr & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV;
}
-static int clk_rm9200_main_enable(struct clk *clk)
+static int clk_rm9200_main_prepare(struct clk_hw *hw)
{
- struct clk_rm9200_main *clkmain = to_clk_rm9200_main(clk);
+ struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
return clk_main_probe_frequency(clkmain->regmap);
}
-static int clk_rm9200_main_is_enabled(struct clk *clk)
+static int clk_rm9200_main_is_prepared(struct clk_hw *hw)
{
- struct clk_rm9200_main *clkmain = to_clk_rm9200_main(clk);
+ struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
unsigned int status;
regmap_read(clkmain->regmap, AT91_CKGR_MCFR, &status);
- return status & AT91_PMC_MAINRDY ? 1 : 0;
+ return !!(status & AT91_PMC_MAINRDY);
}
-static unsigned long clk_rm9200_main_recalc_rate(struct clk *clk,
+static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_rm9200_main *clkmain = to_clk_rm9200_main(clk);
+ struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
return clk_main_recalc_rate(clkmain->regmap, parent_rate);
}
static const struct clk_ops rm9200_main_ops = {
- .enable = clk_rm9200_main_enable,
- .is_enabled = clk_rm9200_main_is_enabled,
+ .enable = clk_rm9200_main_prepare,
+ .is_enabled = clk_rm9200_main_is_prepared,
.recalc_rate = clk_rm9200_main_recalc_rate,
};
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_rm9200_main(struct regmap *regmap,
const char *name,
const char *parent_name)
{
- int ret;
struct clk_rm9200_main *clkmain;
+ struct clk_init_data init;
+ struct clk_hw *hw;
+ int ret;
if (!name)
return ERR_PTR(-EINVAL);
@@ -338,22 +360,27 @@ at91_clk_register_rm9200_main(struct regmap *regmap,
if (!parent_name)
return ERR_PTR(-EINVAL);
- clkmain = xzalloc(sizeof(*clkmain));
+ clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
+ if (!clkmain)
+ return ERR_PTR(-ENOMEM);
- clkmain->parent = parent_name;
- clkmain->clk.name = name;
- clkmain->clk.ops = &rm9200_main_ops;
- clkmain->clk.parent_names = &clkmain->parent;
- clkmain->clk.num_parents = 1;
+ init.name = name;
+ init.ops = &rm9200_main_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = 0;
+
+ clkmain->hw.init = &init;
clkmain->regmap = regmap;
- ret = clk_register(&clkmain->clk);
+ hw = &clkmain->hw;
+ ret = clk_hw_register(NULL, &clkmain->hw);
if (ret) {
kfree(clkmain);
- return ERR_PTR(ret);
+ hw = ERR_PTR(ret);
}
- return &clkmain->clk;
+ return hw;
}
static inline bool clk_sam9x5_main_ready(struct regmap *regmap)
@@ -362,38 +389,38 @@ static inline bool clk_sam9x5_main_ready(struct regmap *regmap)
regmap_read(regmap, AT91_PMC_SR, &status);
- return status & AT91_PMC_MOSCSELS ? 1 : 0;
+ return !!(status & AT91_PMC_MOSCSELS);
}
-static int clk_sam9x5_main_enable(struct clk *clk)
+static int clk_sam9x5_main_prepare(struct clk_hw *hw)
{
- struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(clk);
+ struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
struct regmap *regmap = clkmain->regmap;
while (!clk_sam9x5_main_ready(regmap))
- barrier();
+ cpu_relax();
return clk_main_probe_frequency(regmap);
}
-static int clk_sam9x5_main_is_enabled(struct clk *clk)
+static int clk_sam9x5_main_is_prepared(struct clk_hw *hw)
{
- struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(clk);
+ struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
return clk_sam9x5_main_ready(clkmain->regmap);
}
-static unsigned long clk_sam9x5_main_recalc_rate(struct clk *clk,
+static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(clk);
+ struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
return clk_main_recalc_rate(clkmain->regmap, parent_rate);
}
-static int clk_sam9x5_main_set_parent(struct clk *clk, u8 index)
+static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index)
{
- struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(clk);
+ struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
struct regmap *regmap = clkmain->regmap;
unsigned int tmp;
@@ -401,22 +428,27 @@ static int clk_sam9x5_main_set_parent(struct clk *clk, u8 index)
return -EINVAL;
regmap_read(regmap, AT91_CKGR_MOR, &tmp);
- tmp &= ~MOR_KEY_MASK;
if (index && !(tmp & AT91_PMC_MOSCSEL))
- regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_MOSCSEL);
+ tmp = AT91_PMC_MOSCSEL;
else if (!index && (tmp & AT91_PMC_MOSCSEL))
- regmap_write(regmap, AT91_CKGR_MOR, tmp & ~AT91_PMC_MOSCSEL);
+ tmp = 0;
+ else
+ return 0;
+
+ regmap_update_bits(regmap, AT91_CKGR_MOR,
+ AT91_PMC_MOSCSEL | MOR_KEY_MASK,
+ tmp | AT91_PMC_KEY);
while (!clk_sam9x5_main_ready(regmap))
- barrier();
+ cpu_relax();
return 0;
}
-static int clk_sam9x5_main_get_parent(struct clk *clk)
+static int clk_sam9x5_main_get_parent(struct clk_hw *hw)
{
- struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(clk);
+ struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
unsigned int status;
regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status);
@@ -425,23 +457,24 @@ static int clk_sam9x5_main_get_parent(struct clk *clk)
}
static const struct clk_ops sam9x5_main_ops = {
- .enable = clk_sam9x5_main_enable,
- .is_enabled = clk_sam9x5_main_is_enabled,
+ .enable = clk_sam9x5_main_prepare,
+ .is_enabled = clk_sam9x5_main_is_prepared,
.recalc_rate = clk_sam9x5_main_recalc_rate,
.set_parent = clk_sam9x5_main_set_parent,
.get_parent = clk_sam9x5_main_get_parent,
};
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_sam9x5_main(struct regmap *regmap,
const char *name,
const char **parent_names,
int num_parents)
{
- int ret;
- unsigned int status;
- size_t parents_array_size;
struct clk_sam9x5_main *clkmain;
+ struct clk_init_data init;
+ unsigned int status;
+ struct clk_hw *hw;
+ int ret;
if (!name)
return ERR_PTR(-EINVAL);
@@ -449,25 +482,27 @@ at91_clk_register_sam9x5_main(struct regmap *regmap,
if (!parent_names || !num_parents)
return ERR_PTR(-EINVAL);
- clkmain = xzalloc(sizeof(*clkmain));
-
- clkmain->clk.name = name;
- clkmain->clk.ops = &sam9x5_main_ops;
- parents_array_size = num_parents * sizeof (clkmain->clk.parent_names[0]);
- clkmain->clk.parent_names = xmemdup(parent_names, parents_array_size);
- clkmain->clk.num_parents = num_parents;
+ clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
+ if (!clkmain)
+ return ERR_PTR(-ENOMEM);
- /* init.flags = CLK_SET_PARENT_GATE; */
+ init.name = name;
+ init.ops = &sam9x5_main_ops;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+ init.flags = CLK_SET_PARENT_GATE;
+ clkmain->hw.init = &init;
clkmain->regmap = regmap;
regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status);
clkmain->parent = clk_main_parent_select(status);
- ret = clk_register(&clkmain->clk);
+ hw = &clkmain->hw;
+ ret = clk_hw_register(NULL, &clkmain->hw);
if (ret) {
kfree(clkmain);
- return ERR_PTR(ret);
+ hw = ERR_PTR(ret);
}
- return &clkmain->clk;
+ return hw;
}
diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c
index 4e3b512aaa..db5e235b6b 100644
--- a/drivers/clk/at91/clk-master.c
+++ b/drivers/clk/at91/clk-master.c
@@ -2,145 +2,462 @@
/*
* Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
*/
-#include <common.h>
-#include <clock.h>
-#include <linux/list.h>
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/clk.h>
#include <linux/clk/at91_pmc.h>
+#include <of.h>
#include <mfd/syscon.h>
-#include <regmap.h>
+#include <linux/regmap.h>
+#include <linux/printk.h>
#include "pmc.h"
-#define MASTER_SOURCE_MAX 4
-
#define MASTER_PRES_MASK 0x7
#define MASTER_PRES_MAX MASTER_PRES_MASK
#define MASTER_DIV_SHIFT 8
-#define MASTER_DIV_MASK 0x3
+#define MASTER_DIV_MASK 0x7
+
+#define PMC_MCR_CSS_SHIFT (16)
+
+#define MASTER_MAX_ID 4
-#define to_clk_master(clk) container_of(clk, struct clk_master, clk)
+#define to_clk_master(hw) container_of(hw, struct clk_master, hw)
struct clk_master {
- struct clk clk;
+ struct clk_hw hw;
struct regmap *regmap;
+ spinlock_t *lock;
const struct clk_master_layout *layout;
const struct clk_master_characteristics *characteristics;
- const char *parents[MASTER_SOURCE_MAX];
+ struct at91_clk_pms pms;
+ u32 *mux_table;
u32 mckr;
+ int chg_pid;
+ u8 id;
+ u8 parent;
+ u8 div;
};
-static inline bool clk_master_ready(struct regmap *regmap)
+static inline bool clk_master_ready(struct clk_master *master)
{
+ unsigned int bit = master->id ? AT91_PMC_MCKXRDY : AT91_PMC_MCKRDY;
unsigned int status;
- regmap_read(regmap, AT91_PMC_SR, &status);
+ regmap_read(master->regmap, AT91_PMC_SR, &status);
- return status & AT91_PMC_MCKRDY ? 1 : 0;
+ return !!(status & bit);
}
-static int clk_master_enable(struct clk *clk)
+static int clk_master_prepare(struct clk_hw *hw)
{
- struct clk_master *master = to_clk_master(clk);
+ struct clk_master *master = to_clk_master(hw);
+ unsigned long flags;
+
+ spin_lock_irqsave(master->lock, flags);
+
+ while (!clk_master_ready(master))
+ cpu_relax();
- while (!clk_master_ready(master->regmap))
- barrier();
+ spin_unlock_irqrestore(master->lock, flags);
return 0;
}
-static int clk_master_is_enabled(struct clk *clk)
+static int clk_master_is_prepared(struct clk_hw *hw)
{
- struct clk_master *master = to_clk_master(clk);
+ struct clk_master *master = to_clk_master(hw);
+ unsigned long flags;
+ bool status;
- return clk_master_ready(master->regmap);
+ spin_lock_irqsave(master->lock, flags);
+ status = clk_master_ready(master);
+ spin_unlock_irqrestore(master->lock, flags);
+
+ return status;
}
-static unsigned long clk_master_recalc_rate(struct clk *clk,
- unsigned long parent_rate)
+static unsigned long clk_master_div_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
{
- u8 pres;
u8 div;
- unsigned long rate = parent_rate;
- struct clk_master *master = to_clk_master(clk);
+ unsigned long flags, rate = parent_rate;
+ struct clk_master *master = to_clk_master(hw);
const struct clk_master_layout *layout = master->layout;
const struct clk_master_characteristics *characteristics =
master->characteristics;
unsigned int mckr;
+ spin_lock_irqsave(master->lock, flags);
regmap_read(master->regmap, master->layout->offset, &mckr);
+ spin_unlock_irqrestore(master->lock, flags);
+
mckr &= layout->mask;
- pres = (mckr >> layout->pres_shift) & MASTER_PRES_MASK;
div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
- if (characteristics->have_div3_pres && pres == MASTER_PRES_MAX)
- rate /= 3;
- else
- rate >>= pres;
-
rate /= characteristics->divisors[div];
if (rate < characteristics->output.min)
- pr_warn("master clk is underclocked");
+ pr_warn("master clk div is underclocked");
else if (rate > characteristics->output.max)
- pr_warn("master clk is overclocked");
+ pr_warn("master clk div is overclocked");
return rate;
}
-static int clk_master_get_parent(struct clk *clk)
+static const struct clk_ops master_div_ops = {
+ .enable = clk_master_prepare,
+ .is_enabled = clk_master_is_prepared,
+ .recalc_rate = clk_master_div_recalc_rate,
+};
+
+static unsigned long clk_master_div_recalc_rate_chg(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_master *master = to_clk_master(hw);
+
+ return DIV_ROUND_CLOSEST_ULL(parent_rate, master->div);
+}
+
+static const struct clk_ops master_div_ops_chg = {
+ .enable = clk_master_prepare,
+ .is_enabled = clk_master_is_prepared,
+ .recalc_rate = clk_master_div_recalc_rate_chg,
+};
+
+static unsigned long clk_master_pres_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_master *master = to_clk_master(hw);
+ const struct clk_master_characteristics *characteristics =
+ master->characteristics;
+ unsigned long flags;
+ unsigned int val, pres;
+
+ spin_lock_irqsave(master->lock, flags);
+ regmap_read(master->regmap, master->layout->offset, &val);
+ spin_unlock_irqrestore(master->lock, flags);
+
+ val &= master->layout->mask;
+ pres = (val >> master->layout->pres_shift) & MASTER_PRES_MASK;
+ if (pres == MASTER_PRES_MAX && characteristics->have_div3_pres)
+ pres = 3;
+ else
+ pres = (1 << pres);
+
+ return DIV_ROUND_CLOSEST_ULL(parent_rate, pres);
+}
+
+static int clk_master_pres_get_parent(struct clk_hw *hw)
{
- struct clk_master *master = to_clk_master(clk);
+ struct clk_master *master = to_clk_master(hw);
+ unsigned long flags;
unsigned int mckr;
+ spin_lock_irqsave(master->lock, flags);
regmap_read(master->regmap, master->layout->offset, &mckr);
+ spin_unlock_irqrestore(master->lock, flags);
+
+ mckr &= master->layout->mask;
return mckr & AT91_PMC_CSS;
}
-static const struct clk_ops master_ops = {
- .enable = clk_master_enable,
- .is_enabled = clk_master_is_enabled,
- .recalc_rate = clk_master_recalc_rate,
- .get_parent = clk_master_get_parent,
+static const struct clk_ops master_pres_ops = {
+ .enable = clk_master_prepare,
+ .is_enabled = clk_master_is_prepared,
+ .recalc_rate = clk_master_pres_recalc_rate,
+ .get_parent = clk_master_pres_get_parent,
};
-struct clk * __init
-at91_clk_register_master(struct regmap *regmap,
- const char *name, int num_parents,
- const char **parent_names,
- const struct clk_master_layout *layout,
- const struct clk_master_characteristics *characteristics)
+static struct clk_hw * __init
+at91_clk_register_master_internal(struct regmap *regmap,
+ const char *name, int num_parents,
+ const char **parent_names,
+ const struct clk_master_layout *layout,
+ const struct clk_master_characteristics *characteristics,
+ const struct clk_ops *ops, spinlock_t *lock, u32 flags)
{
- int ret;
- const size_t parent_names_size = num_parents * sizeof(parent_names[0]);
struct clk_master *master;
+ struct clk_init_data init;
+ struct clk_hw *hw;
+ unsigned int mckr;
+ unsigned long irqflags;
+ int ret;
- if (!name || !num_parents || !parent_names)
+ if (!name || !num_parents || !parent_names || !lock)
return ERR_PTR(-EINVAL);
- master = xzalloc(sizeof(*master));
+ master = kzalloc(sizeof(*master), GFP_KERNEL);
+ if (!master)
+ return ERR_PTR(-ENOMEM);
- master->clk.name = name;
- master->clk.ops = &master_ops;
- memcpy(master->parents, parent_names, parent_names_size);
- master->clk.parent_names = master->parents;
- master->clk.num_parents = num_parents;
+ init.name = name;
+ init.ops = ops;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+ init.flags = flags;
+ master->hw.init = &init;
master->layout = layout;
master->characteristics = characteristics;
master->regmap = regmap;
+ master->lock = lock;
+
+ if (ops == &master_div_ops_chg) {
+ spin_lock_irqsave(master->lock, irqflags);
+ regmap_read(master->regmap, master->layout->offset, &mckr);
+ spin_unlock_irqrestore(master->lock, irqflags);
- ret = clk_register(&master->clk);
+ mckr &= layout->mask;
+ mckr = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
+ master->div = characteristics->divisors[mckr];
+ }
+
+ hw = &master->hw;
+ ret = clk_hw_register(NULL, &master->hw);
if (ret) {
kfree(master);
- return ERR_PTR(ret);
+ hw = ERR_PTR(ret);
}
- return &master->clk;
+ return hw;
+}
+
+struct clk_hw * __init
+at91_clk_register_master_pres(struct regmap *regmap,
+ const char *name, int num_parents,
+ const char **parent_names,
+ const struct clk_master_layout *layout,
+ const struct clk_master_characteristics *characteristics,
+ spinlock_t *lock)
+{
+ return at91_clk_register_master_internal(regmap, name, num_parents,
+ parent_names, layout,
+ characteristics,
+ &master_pres_ops,
+ lock, CLK_SET_RATE_GATE);
+}
+
+struct clk_hw * __init
+at91_clk_register_master_div(struct regmap *regmap,
+ const char *name, const char *parent_name,
+ const struct clk_master_layout *layout,
+ const struct clk_master_characteristics *characteristics,
+ spinlock_t *lock, u32 flags)
+{
+ const struct clk_ops *ops;
+
+ if (flags & CLK_SET_RATE_GATE)
+ ops = &master_div_ops;
+ else
+ ops = &master_div_ops_chg;
+
+ return at91_clk_register_master_internal(regmap, name, 1,
+ &parent_name, layout,
+ characteristics, ops,
+ lock, flags);
+}
+
+static unsigned long
+clk_sama7g5_master_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_master *master = to_clk_master(hw);
+
+ return DIV_ROUND_CLOSEST_ULL(parent_rate, (1 << master->div));
+}
+
+static int clk_sama7g5_master_get_parent(struct clk_hw *hw)
+{
+ struct clk_master *master = to_clk_master(hw);
+ unsigned long flags;
+ u8 index;
+
+ spin_lock_irqsave(master->lock, flags);
+ index = clk_mux_val_to_index(&master->hw, master->mux_table, 0,
+ master->parent);
+ spin_unlock_irqrestore(master->lock, flags);
+
+ return index;
+}
+
+static int clk_sama7g5_master_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct clk_master *master = to_clk_master(hw);
+ unsigned long flags;
+
+ if (index >= clk_hw_get_num_parents(hw))
+ return -EINVAL;
+
+ spin_lock_irqsave(master->lock, flags);
+ master->parent = clk_mux_index_to_val(master->mux_table, 0, index);
+ spin_unlock_irqrestore(master->lock, flags);
+
+ return 0;
+}
+
+static void clk_sama7g5_master_set(struct clk_master *master,
+ unsigned int status)
+{
+ unsigned long flags;
+ unsigned int val, cparent;
+ unsigned int enable = status ? AT91_PMC_MCR_V2_EN : 0;
+ unsigned int parent = master->parent << PMC_MCR_CSS_SHIFT;
+ unsigned int div = master->div << MASTER_DIV_SHIFT;
+
+ spin_lock_irqsave(master->lock, flags);
+
+ regmap_write(master->regmap, AT91_PMC_MCR_V2,
+ AT91_PMC_MCR_V2_ID(master->id));
+ regmap_read(master->regmap, AT91_PMC_MCR_V2, &val);
+ regmap_update_bits(master->regmap, AT91_PMC_MCR_V2,
+ enable | AT91_PMC_MCR_V2_CSS | AT91_PMC_MCR_V2_DIV |
+ AT91_PMC_MCR_V2_CMD | AT91_PMC_MCR_V2_ID_MSK,
+ enable | parent | div | AT91_PMC_MCR_V2_CMD |
+ AT91_PMC_MCR_V2_ID(master->id));
+
+ cparent = (val & AT91_PMC_MCR_V2_CSS) >> PMC_MCR_CSS_SHIFT;
+
+ /* Wait here only if parent is being changed. */
+ while ((cparent != master->parent) && !clk_master_ready(master))
+ cpu_relax();
+
+ spin_unlock_irqrestore(master->lock, flags);
+}
+
+static int clk_sama7g5_master_enable(struct clk_hw *hw)
+{
+ struct clk_master *master = to_clk_master(hw);
+
+ clk_sama7g5_master_set(master, 1);
+
+ return 0;
+}
+
+static void clk_sama7g5_master_disable(struct clk_hw *hw)
+{
+ struct clk_master *master = to_clk_master(hw);
+ unsigned long flags;
+
+ spin_lock_irqsave(master->lock, flags);
+
+ regmap_write(master->regmap, AT91_PMC_MCR_V2, master->id);
+ regmap_update_bits(master->regmap, AT91_PMC_MCR_V2,
+ AT91_PMC_MCR_V2_EN | AT91_PMC_MCR_V2_CMD |
+ AT91_PMC_MCR_V2_ID_MSK,
+ AT91_PMC_MCR_V2_CMD |
+ AT91_PMC_MCR_V2_ID(master->id));
+
+ spin_unlock_irqrestore(master->lock, flags);
+}
+
+static int clk_sama7g5_master_is_enabled(struct clk_hw *hw)
+{
+ struct clk_master *master = to_clk_master(hw);
+ unsigned long flags;
+ unsigned int val;
+
+ spin_lock_irqsave(master->lock, flags);
+
+ regmap_write(master->regmap, AT91_PMC_MCR_V2, master->id);
+ regmap_read(master->regmap, AT91_PMC_MCR_V2, &val);
+
+ spin_unlock_irqrestore(master->lock, flags);
+
+ return !!(val & AT91_PMC_MCR_V2_EN);
}
+static int clk_sama7g5_master_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_master *master = to_clk_master(hw);
+ unsigned long div, flags;
+
+ div = DIV_ROUND_CLOSEST(parent_rate, rate);
+ if ((div > (1 << (MASTER_PRES_MAX - 1))) || (div & (div - 1)))
+ return -EINVAL;
+
+ if (div == 3)
+ div = MASTER_PRES_MAX;
+ else if (div)
+ div = ffs(div) - 1;
+
+ spin_lock_irqsave(master->lock, flags);
+ master->div = div;
+ spin_unlock_irqrestore(master->lock, flags);
+
+ return 0;
+}
+
+static const struct clk_ops sama7g5_master_ops = {
+ .enable = clk_sama7g5_master_enable,
+ .disable = clk_sama7g5_master_disable,
+ .is_enabled = clk_sama7g5_master_is_enabled,
+ .recalc_rate = clk_sama7g5_master_recalc_rate,
+ .set_rate = clk_sama7g5_master_set_rate,
+ .get_parent = clk_sama7g5_master_get_parent,
+ .set_parent = clk_sama7g5_master_set_parent,
+};
+
+struct clk_hw * __init
+at91_clk_sama7g5_register_master(struct regmap *regmap,
+ const char *name, int num_parents,
+ const char **parent_names,
+ u32 *mux_table,
+ spinlock_t *lock, u8 id,
+ bool critical, int chg_pid)
+{
+ struct clk_master *master;
+ struct clk_hw *hw;
+ struct clk_init_data init;
+ unsigned long flags;
+ unsigned int val;
+ int ret;
+
+ if (!name || !num_parents || !parent_names || !mux_table ||
+ !lock || id > MASTER_MAX_ID)
+ return ERR_PTR(-EINVAL);
+
+ master = kzalloc(sizeof(*master), GFP_KERNEL);
+ if (!master)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &sama7g5_master_ops;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+ init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
+ if (chg_pid >= 0)
+ init.flags |= CLK_SET_RATE_PARENT;
+ if (critical)
+ init.flags |= CLK_IS_CRITICAL;
+
+ master->hw.init = &init;
+ master->regmap = regmap;
+ master->id = id;
+ master->chg_pid = chg_pid;
+ master->lock = lock;
+ master->mux_table = mux_table;
+
+ spin_lock_irqsave(master->lock, flags);
+ regmap_write(master->regmap, AT91_PMC_MCR_V2, master->id);
+ regmap_read(master->regmap, AT91_PMC_MCR_V2, &val);
+ master->parent = (val & AT91_PMC_MCR_V2_CSS) >> PMC_MCR_CSS_SHIFT;
+ master->div = (val & AT91_PMC_MCR_V2_DIV) >> MASTER_DIV_SHIFT;
+ spin_unlock_irqrestore(master->lock, flags);
+
+ hw = &master->hw;
+ ret = clk_hw_register(NULL, &master->hw);
+ if (ret) {
+ kfree(master);
+ hw = ERR_PTR(ret);
+ }
+
+ return hw;
+}
const struct clk_master_layout at91rm9200_master_layout = {
.mask = 0x31F,
diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c
index 2b9008eb2c..bd4b50b142 100644
--- a/drivers/clk/at91/clk-peripheral.c
+++ b/drivers/clk/at91/clk-peripheral.c
@@ -3,51 +3,51 @@
* Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
*/
-#include <common.h>
-#include <clock.h>
-#include <linux/list.h>
-#include <linux/clk.h>
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/clk/at91_pmc.h>
+#include <of.h>
#include <mfd/syscon.h>
-#include <regmap.h>
+#include <linux/regmap.h>
#include "pmc.h"
+DEFINE_SPINLOCK(pmc_pcr_lock);
+
#define PERIPHERAL_ID_MIN 2
#define PERIPHERAL_ID_MAX 31
#define PERIPHERAL_MASK(id) (1 << ((id) & PERIPHERAL_ID_MAX))
-#define PERIPHERAL_RSHIFT_MASK 0x3
-#define PERIPHERAL_RSHIFT(val) (((val) >> 16) & PERIPHERAL_RSHIFT_MASK)
-
#define PERIPHERAL_MAX_SHIFT 3
struct clk_peripheral {
- struct clk clk;
+ struct clk_hw hw;
struct regmap *regmap;
u32 id;
- const char *parent;
};
-#define to_clk_peripheral(clk) container_of(clk, struct clk_peripheral, clk)
+#define to_clk_peripheral(hw) container_of(hw, struct clk_peripheral, hw)
struct clk_sam9x5_peripheral {
- struct clk clk;
+ struct clk_hw hw;
struct regmap *regmap;
struct clk_range range;
+ spinlock_t *lock;
u32 id;
u32 div;
const struct clk_pcr_layout *layout;
+ struct at91_clk_pms pms;
bool auto_div;
- const char *parent;
+ int chg_pid;
};
-#define to_clk_sam9x5_peripheral(clk) \
- container_of(clk, struct clk_sam9x5_peripheral, clk)
+#define to_clk_sam9x5_peripheral(hw) \
+ container_of(hw, struct clk_sam9x5_peripheral, hw)
-static int clk_peripheral_enable(struct clk *clk)
+static int clk_peripheral_enable(struct clk_hw *hw)
{
- struct clk_peripheral *periph = to_clk_peripheral(clk);
+ struct clk_peripheral *periph = to_clk_peripheral(hw);
int offset = AT91_PMC_PCER;
u32 id = periph->id;
@@ -60,9 +60,9 @@ static int clk_peripheral_enable(struct clk *clk)
return 0;
}
-static void clk_peripheral_disable(struct clk *clk)
+static void clk_peripheral_disable(struct clk_hw *hw)
{
- struct clk_peripheral *periph = to_clk_peripheral(clk);
+ struct clk_peripheral *periph = to_clk_peripheral(hw);
int offset = AT91_PMC_PCDR;
u32 id = periph->id;
@@ -73,9 +73,9 @@ static void clk_peripheral_disable(struct clk *clk)
regmap_write(periph->regmap, offset, PERIPHERAL_MASK(id));
}
-static int clk_peripheral_is_enabled(struct clk *clk)
+static int clk_peripheral_is_enabled(struct clk_hw *hw)
{
- struct clk_peripheral *periph = to_clk_peripheral(clk);
+ struct clk_peripheral *periph = to_clk_peripheral(hw);
int offset = AT91_PMC_PCSR;
unsigned int status;
u32 id = periph->id;
@@ -95,42 +95,45 @@ static const struct clk_ops peripheral_ops = {
.is_enabled = clk_peripheral_is_enabled,
};
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_peripheral(struct regmap *regmap, const char *name,
const char *parent_name, u32 id)
{
- int ret;
struct clk_peripheral *periph;
+ struct clk_init_data init;
+ struct clk_hw *hw;
+ int ret;
if (!name || !parent_name || id > PERIPHERAL_ID_MAX)
return ERR_PTR(-EINVAL);
- periph = xzalloc(sizeof(*periph));
-
- periph->clk.name = name;
- periph->clk.ops = &peripheral_ops;
+ periph = kzalloc(sizeof(*periph), GFP_KERNEL);
+ if (!periph)
+ return ERR_PTR(-ENOMEM);
- if (parent_name) {
- periph->parent = parent_name;
- periph->clk.parent_names = &periph->parent;
- periph->clk.num_parents = 1;
- }
+ init.name = name;
+ init.ops = &peripheral_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = 0;
periph->id = id;
+ periph->hw.init = &init;
periph->regmap = regmap;
- ret = clk_register(&periph->clk);
+ hw = &periph->hw;
+ ret = clk_hw_register(NULL, &periph->hw);
if (ret) {
kfree(periph);
- return ERR_PTR(ret);
+ hw = ERR_PTR(ret);
}
- return &periph->clk;
+ return hw;
}
static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph)
{
- struct clk *parent;
+ struct clk_hw *parent;
unsigned long parent_rate;
int shift = 0;
@@ -138,8 +141,8 @@ static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph)
return;
if (periph->range.max) {
- parent = clk_get_parent(&periph->clk);
- parent_rate = clk_get_rate(parent);
+ parent = clk_hw_get_parent_by_index(&periph->hw, 0);
+ parent_rate = clk_hw_get_rate(parent);
if (!parent_rate)
return;
@@ -153,67 +156,86 @@ static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph)
periph->div = shift;
}
-static int clk_sam9x5_peripheral_enable(struct clk *clk)
+static int clk_sam9x5_peripheral_set(struct clk_sam9x5_peripheral *periph,
+ unsigned int status)
{
- struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(clk);
+ unsigned long flags;
+ unsigned int enable = status ? AT91_PMC_PCR_EN : 0;
if (periph->id < PERIPHERAL_ID_MIN)
return 0;
+ spin_lock_irqsave(periph->lock, flags);
regmap_write(periph->regmap, periph->layout->offset,
(periph->id & periph->layout->pid_mask));
- regmap_write_bits(periph->regmap, periph->layout->offset,
- periph->layout->div_mask | periph->layout->cmd |
- AT91_PMC_PCR_EN,
- field_prep(periph->layout->div_mask, periph->div) |
- periph->layout->cmd |
- AT91_PMC_PCR_EN);
+ regmap_update_bits(periph->regmap, periph->layout->offset,
+ periph->layout->div_mask | periph->layout->cmd |
+ enable,
+ field_prep(periph->layout->div_mask, periph->div) |
+ periph->layout->cmd | enable);
+ spin_unlock_irqrestore(periph->lock, flags);
return 0;
}
-static void clk_sam9x5_peripheral_disable(struct clk *clk)
+static int clk_sam9x5_peripheral_enable(struct clk_hw *hw)
{
- struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(clk);
+ struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
+
+ return clk_sam9x5_peripheral_set(periph, 1);
+}
+
+static void clk_sam9x5_peripheral_disable(struct clk_hw *hw)
+{
+ struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
+ unsigned long flags;
if (periph->id < PERIPHERAL_ID_MIN)
return;
+ spin_lock_irqsave(periph->lock, flags);
regmap_write(periph->regmap, periph->layout->offset,
(periph->id & periph->layout->pid_mask));
- regmap_write_bits(periph->regmap, periph->layout->offset,
- AT91_PMC_PCR_EN | periph->layout->cmd,
- periph->layout->cmd);
+ regmap_update_bits(periph->regmap, periph->layout->offset,
+ AT91_PMC_PCR_EN | periph->layout->cmd,
+ periph->layout->cmd);
+ spin_unlock_irqrestore(periph->lock, flags);
}
-static int clk_sam9x5_peripheral_is_enabled(struct clk *clk)
+static int clk_sam9x5_peripheral_is_enabled(struct clk_hw *hw)
{
- struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(clk);
+ struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
+ unsigned long flags;
unsigned int status;
if (periph->id < PERIPHERAL_ID_MIN)
return 1;
+ spin_lock_irqsave(periph->lock, flags);
regmap_write(periph->regmap, periph->layout->offset,
(periph->id & periph->layout->pid_mask));
regmap_read(periph->regmap, periph->layout->offset, &status);
+ spin_unlock_irqrestore(periph->lock, flags);
- return status & AT91_PMC_PCR_EN ? 1 : 0;
+ return !!(status & AT91_PMC_PCR_EN);
}
static unsigned long
-clk_sam9x5_peripheral_recalc_rate(struct clk *clk,
+clk_sam9x5_peripheral_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(clk);
+ struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
+ unsigned long flags;
unsigned int status;
if (periph->id < PERIPHERAL_ID_MIN)
return parent_rate;
+ spin_lock_irqsave(periph->lock, flags);
regmap_write(periph->regmap, periph->layout->offset,
(periph->id & periph->layout->pid_mask));
regmap_read(periph->regmap, periph->layout->offset, &status);
+ spin_unlock_irqrestore(periph->lock, flags);
if (status & AT91_PMC_PCR_EN) {
periph->div = field_get(periph->layout->div_mask, status);
@@ -225,7 +247,7 @@ clk_sam9x5_peripheral_recalc_rate(struct clk *clk,
return parent_rate >> periph->div;
}
-static long clk_sam9x5_peripheral_round_rate(struct clk *clk,
+static long clk_sam9x5_peripheral_round_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long *parent_rate)
{
@@ -234,7 +256,7 @@ static long clk_sam9x5_peripheral_round_rate(struct clk *clk,
unsigned long best_diff;
unsigned long cur_rate = *parent_rate;
unsigned long cur_diff;
- struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(clk);
+ struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max)
return *parent_rate;
@@ -271,12 +293,12 @@ static long clk_sam9x5_peripheral_round_rate(struct clk *clk,
return best_rate;
}
-static int clk_sam9x5_peripheral_set_rate(struct clk *clk,
+static int clk_sam9x5_peripheral_set_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long parent_rate)
{
int shift;
- struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(clk);
+ struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max) {
if (parent_rate == rate)
return 0;
@@ -307,45 +329,64 @@ static const struct clk_ops sam9x5_peripheral_ops = {
.set_rate = clk_sam9x5_peripheral_set_rate,
};
-struct clk * __init
-at91_clk_register_sam9x5_peripheral(struct regmap *regmap,
+static const struct clk_ops sam9x5_peripheral_chg_ops = {
+ .enable = clk_sam9x5_peripheral_enable,
+ .disable = clk_sam9x5_peripheral_disable,
+ .is_enabled = clk_sam9x5_peripheral_is_enabled,
+ .recalc_rate = clk_sam9x5_peripheral_recalc_rate,
+ .set_rate = clk_sam9x5_peripheral_set_rate,
+};
+
+struct clk_hw * __init
+at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
const struct clk_pcr_layout *layout,
const char *name, const char *parent_name,
- u32 id, const struct clk_range *range)
+ u32 id, const struct clk_range *range,
+ int chg_pid, unsigned long flags)
{
- int ret;
struct clk_sam9x5_peripheral *periph;
+ struct clk_init_data init;
+ struct clk_hw *hw;
+ int ret;
if (!name || !parent_name)
return ERR_PTR(-EINVAL);
- periph = xzalloc(sizeof(*periph));
-
- periph->clk.name = name;
- periph->clk.ops = &sam9x5_peripheral_ops;
+ periph = kzalloc(sizeof(*periph), GFP_KERNEL);
+ if (!periph)
+ return ERR_PTR(-ENOMEM);
- if (parent_name) {
- periph->parent = parent_name;
- periph->clk.parent_names = &periph->parent;
- periph->clk.num_parents = 1;
+ init.name = name;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = flags;
+ if (chg_pid < 0) {
+ init.ops = &sam9x5_peripheral_ops;
+ } else {
+ init.flags |= CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
+ CLK_SET_RATE_PARENT;
+ init.ops = &sam9x5_peripheral_chg_ops;
}
periph->id = id;
+ periph->hw.init = &init;
periph->div = 0;
periph->regmap = regmap;
+ periph->lock = lock;
if (layout->div_mask)
periph->auto_div = true;
periph->layout = layout;
periph->range = *range;
+ periph->chg_pid = chg_pid;
- ret = clk_register(&periph->clk);
+ hw = &periph->hw;
+ ret = clk_hw_register(NULL, &periph->hw);
if (ret) {
kfree(periph);
- return ERR_PTR(ret);
+ hw = ERR_PTR(ret);
+ } else {
+ clk_sam9x5_peripheral_autodiv(periph);
}
- clk_sam9x5_peripheral_autodiv(periph);
- pmc_register_id(id);
-
- return &periph->clk;
+ return hw;
}
diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c
index 5cb156e784..027e1fc773 100644
--- a/drivers/clk/at91/clk-pll.c
+++ b/drivers/clk/at91/clk-pll.c
@@ -3,14 +3,12 @@
* Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
*/
-#include <common.h>
-#include <clock.h>
-#include <of.h>
-#include <linux/list.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/clk/at91_pmc.h>
+#include <of.h>
#include <mfd/syscon.h>
-#include <regmap.h>
+#include <linux/regmap.h>
#include "pmc.h"
@@ -31,10 +29,10 @@
#define PLL_OUT_SHIFT 14
#define PLL_MAX_ID 1
-#define to_clk_pll(clk) container_of(clk, struct clk_pll, clk)
+#define to_clk_pll(hw) container_of(hw, struct clk_pll, hw)
struct clk_pll {
- struct clk clk;
+ struct clk_hw hw;
struct regmap *regmap;
u8 id;
u8 div;
@@ -42,7 +40,7 @@ struct clk_pll {
u16 mul;
const struct clk_pll_layout *layout;
const struct clk_pll_characteristics *characteristics;
- const char *parent;
+ struct at91_clk_pms pms;
};
static inline bool clk_pll_ready(struct regmap *regmap, int id)
@@ -54,9 +52,9 @@ static inline bool clk_pll_ready(struct regmap *regmap, int id)
return status & PLL_STATUS_MASK(id) ? 1 : 0;
}
-static int clk_pll_enable(struct clk *clk)
+static int clk_pll_prepare(struct clk_hw *hw)
{
- struct clk_pll *pll = to_clk_pll(clk);
+ struct clk_pll *pll = to_clk_pll(hw);
struct regmap *regmap = pll->regmap;
const struct clk_pll_layout *layout = pll->layout;
const struct clk_pll_characteristics *characteristics =
@@ -83,39 +81,39 @@ static int clk_pll_enable(struct clk *clk)
out = characteristics->out[pll->range];
if (characteristics->icpll)
- regmap_write_bits(regmap, AT91_PMC_PLLICPR, PLL_ICPR_MASK(id),
+ regmap_update_bits(regmap, AT91_PMC_PLLICPR, PLL_ICPR_MASK(id),
characteristics->icpll[pll->range] << PLL_ICPR_SHIFT(id));
- regmap_write_bits(regmap, offset, layout->pllr_mask,
- pll->div | (PLL_MAX_COUNT << PLL_COUNT_SHIFT) |
- (out << PLL_OUT_SHIFT) |
- ((pll->mul & layout->mul_mask) << layout->mul_shift));
+ regmap_update_bits(regmap, offset, layout->pllr_mask,
+ pll->div | (PLL_MAX_COUNT << PLL_COUNT_SHIFT) |
+ (out << PLL_OUT_SHIFT) |
+ ((pll->mul & layout->mul_mask) << layout->mul_shift));
while (!clk_pll_ready(regmap, pll->id))
- barrier();
+ cpu_relax();
return 0;
}
-static int clk_pll_is_enabled(struct clk *clk)
+static int clk_pll_is_prepared(struct clk_hw *hw)
{
- struct clk_pll *pll = to_clk_pll(clk);
+ struct clk_pll *pll = to_clk_pll(hw);
return clk_pll_ready(pll->regmap, pll->id);
}
-static void clk_pll_disable(struct clk *clk)
+static void clk_pll_unprepare(struct clk_hw *hw)
{
- struct clk_pll *pll = to_clk_pll(clk);
+ struct clk_pll *pll = to_clk_pll(hw);
unsigned int mask = pll->layout->pllr_mask;
- regmap_write_bits(pll->regmap, PLL_REG(pll->id), mask, ~mask);
+ regmap_update_bits(pll->regmap, PLL_REG(pll->id), mask, ~mask);
}
-static unsigned long clk_pll_recalc_rate(struct clk *clk,
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_pll *pll = to_clk_pll(clk);
+ struct clk_pll *pll = to_clk_pll(hw);
if (!pll->div || !pll->mul)
return 0;
@@ -233,19 +231,19 @@ static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate,
return bestrate;
}
-static long clk_pll_round_rate(struct clk *clk, unsigned long rate,
- unsigned long *parent_rate)
+static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
{
- struct clk_pll *pll = to_clk_pll(clk);
+ struct clk_pll *pll = to_clk_pll(hw);
return clk_pll_get_best_div_mul(pll, rate, *parent_rate,
NULL, NULL, NULL);
}
-static int clk_pll_set_rate(struct clk *clk, unsigned long rate,
+static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_pll *pll = to_clk_pll(clk);
+ struct clk_pll *pll = to_clk_pll(hw);
long ret;
u32 div;
u32 mul;
@@ -264,21 +262,23 @@ static int clk_pll_set_rate(struct clk *clk, unsigned long rate,
}
static const struct clk_ops pll_ops = {
- .enable = clk_pll_enable,
- .disable = clk_pll_disable,
- .is_enabled = clk_pll_is_enabled,
+ .enable = clk_pll_prepare,
+ .disable = clk_pll_unprepare,
+ .is_enabled = clk_pll_is_prepared,
.recalc_rate = clk_pll_recalc_rate,
.round_rate = clk_pll_round_rate,
.set_rate = clk_pll_set_rate,
};
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_pll(struct regmap *regmap, const char *name,
const char *parent_name, u8 id,
const struct clk_pll_layout *layout,
const struct clk_pll_characteristics *characteristics)
{
struct clk_pll *pll;
+ struct clk_hw *hw;
+ struct clk_init_data init;
int offset = PLL_REG(id);
unsigned int pllr;
int ret;
@@ -286,17 +286,18 @@ at91_clk_register_pll(struct regmap *regmap, const char *name,
if (id > PLL_MAX_ID)
return ERR_PTR(-EINVAL);
- pll = xzalloc(sizeof(*pll));
-
- pll->parent = parent_name;
- pll->clk.name = name;
- pll->clk.ops = &pll_ops;
- pll->clk.parent_names = &pll->parent;
- pll->clk.num_parents = 1;
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll)
+ return ERR_PTR(-ENOMEM);
- /* init.flags = CLK_SET_RATE_GATE; */
+ init.name = name;
+ init.ops = &pll_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = CLK_SET_RATE_GATE;
pll->id = id;
+ pll->hw.init = &init;
pll->layout = layout;
pll->characteristics = characteristics;
pll->regmap = regmap;
@@ -304,13 +305,14 @@ at91_clk_register_pll(struct regmap *regmap, const char *name,
pll->div = PLL_DIV(pllr);
pll->mul = PLL_MUL(pllr, layout);
- ret = clk_register(&pll->clk);
+ hw = &pll->hw;
+ ret = clk_hw_register(NULL, &pll->hw);
if (ret) {
kfree(pll);
- return ERR_PTR(ret);
+ hw = ERR_PTR(ret);
}
- return &pll->clk;
+ return hw;
}
diff --git a/drivers/clk/at91/clk-plldiv.c b/drivers/clk/at91/clk-plldiv.c
index 1cbb61bb2c..7fe4411149 100644
--- a/drivers/clk/at91/clk-plldiv.c
+++ b/drivers/clk/at91/clk-plldiv.c
@@ -3,29 +3,26 @@
* Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
*/
-#include <common.h>
-#include <clock.h>
-#include <of.h>
-#include <linux/list.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/clk/at91_pmc.h>
+#include <of.h>
#include <mfd/syscon.h>
-#include <regmap.h>
+#include <linux/regmap.h>
#include "pmc.h"
-#define to_clk_plldiv(hw) container_of(clk, struct clk_plldiv, clk)
+#define to_clk_plldiv(hw) container_of(hw, struct clk_plldiv, hw)
struct clk_plldiv {
- struct clk clk;
+ struct clk_hw hw;
struct regmap *regmap;
- const char *parent;
};
-static unsigned long clk_plldiv_recalc_rate(struct clk *clk,
+static unsigned long clk_plldiv_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_plldiv *plldiv = to_clk_plldiv(clk);
+ struct clk_plldiv *plldiv = to_clk_plldiv(hw);
unsigned int mckr;
regmap_read(plldiv->regmap, AT91_PMC_MCKR, &mckr);
@@ -36,8 +33,8 @@ static unsigned long clk_plldiv_recalc_rate(struct clk *clk,
return parent_rate;
}
-static long clk_plldiv_round_rate(struct clk *clk, unsigned long rate,
- unsigned long *parent_rate)
+static long clk_plldiv_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
{
unsigned long div;
@@ -53,16 +50,16 @@ static long clk_plldiv_round_rate(struct clk *clk, unsigned long rate,
return *parent_rate;
}
-static int clk_plldiv_set_rate(struct clk *clk, unsigned long rate,
+static int clk_plldiv_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_plldiv *plldiv = to_clk_plldiv(clk);
+ struct clk_plldiv *plldiv = to_clk_plldiv(hw);
if ((parent_rate != rate) && (parent_rate / 2 != rate))
return -EINVAL;
- regmap_write_bits(plldiv->regmap, AT91_PMC_MCKR, AT91_PMC_PLLADIV2,
- parent_rate != rate ? AT91_PMC_PLLADIV2 : 0);
+ regmap_update_bits(plldiv->regmap, AT91_PMC_MCKR, AT91_PMC_PLLADIV2,
+ parent_rate != rate ? AT91_PMC_PLLADIV2 : 0);
return 0;
}
@@ -73,33 +70,34 @@ static const struct clk_ops plldiv_ops = {
.set_rate = clk_plldiv_set_rate,
};
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_plldiv(struct regmap *regmap, const char *name,
const char *parent_name)
{
- int ret;
struct clk_plldiv *plldiv;
+ struct clk_hw *hw;
+ struct clk_init_data init;
+ int ret;
- plldiv = xzalloc(sizeof(*plldiv));
-
- plldiv->clk.name = name;
- plldiv->clk.ops = &plldiv_ops;
-
- if (parent_name) {
- plldiv->parent = parent_name;
- plldiv->clk.parent_names = &plldiv->parent;
- plldiv->clk.num_parents = 1;
- }
+ plldiv = kzalloc(sizeof(*plldiv), GFP_KERNEL);
+ if (!plldiv)
+ return ERR_PTR(-ENOMEM);
- /* init.flags = CLK_SET_RATE_GATE; */
+ init.name = name;
+ init.ops = &plldiv_ops;
+ init.parent_names = parent_name ? &parent_name : NULL;
+ init.num_parents = parent_name ? 1 : 0;
+ init.flags = CLK_SET_RATE_GATE;
+ plldiv->hw.init = &init;
plldiv->regmap = regmap;
- ret = clk_register(&plldiv->clk);
+ hw = &plldiv->hw;
+ ret = clk_hw_register(NULL, &plldiv->hw);
if (ret) {
kfree(plldiv);
- return ERR_PTR(ret);
+ hw = ERR_PTR(ret);
}
- return &plldiv->clk;
+ return hw;
}
diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c
index 26c36a882d..3bf13568f5 100644
--- a/drivers/clk/at91/clk-programmable.c
+++ b/drivers/clk/at91/clk-programmable.c
@@ -3,18 +3,15 @@
* Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
*/
-#include <common.h>
-#include <clock.h>
-#include <io.h>
-#include <linux/list.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/clk/at91_pmc.h>
+#include <of.h>
#include <mfd/syscon.h>
-#include <regmap.h>
+#include <linux/regmap.h>
#include "pmc.h"
-#define PROG_SOURCE_MAX 5
#define PROG_ID_MAX 7
#define PROG_STATUS_MASK(id) (1 << ((id) + 8))
@@ -22,19 +19,20 @@
#define PROG_MAX_RM9200_CSS 3
struct clk_programmable {
- struct clk clk;
+ struct clk_hw hw;
struct regmap *regmap;
+ u32 *mux_table;
u8 id;
const struct clk_programmable_layout *layout;
- const char *parent_names[PROG_SOURCE_MAX];
+ struct at91_clk_pms pms;
};
-#define to_clk_programmable(clk) container_of(clk, struct clk_programmable, clk)
+#define to_clk_programmable(hw) container_of(hw, struct clk_programmable, hw)
-static unsigned long clk_programmable_recalc_rate(struct clk *clk,
+static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_programmable *prog = to_clk_programmable(clk);
+ struct clk_programmable *prog = to_clk_programmable(hw);
const struct clk_programmable_layout *layout = prog->layout;
unsigned int pckr;
unsigned long rate;
@@ -49,9 +47,9 @@ static unsigned long clk_programmable_recalc_rate(struct clk *clk,
return rate;
}
-static int clk_programmable_set_parent(struct clk *clk, u8 index)
+static int clk_programmable_set_parent(struct clk_hw *hw, u8 index)
{
- struct clk_programmable *prog = to_clk_programmable(clk);
+ struct clk_programmable *prog = to_clk_programmable(hw);
const struct clk_programmable_layout *layout = prog->layout;
unsigned int mask = layout->css_mask;
unsigned int pckr = index;
@@ -59,6 +57,9 @@ static int clk_programmable_set_parent(struct clk *clk, u8 index)
if (layout->have_slck_mck)
mask |= AT91_PMC_CSSMCK_MCK;
+ if (prog->mux_table)
+ pckr = clk_mux_index_to_val(prog->mux_table, 0, index);
+
if (index > layout->css_mask) {
if (index > PROG_MAX_RM9200_CSS && !layout->have_slck_mck)
return -EINVAL;
@@ -66,14 +67,14 @@ static int clk_programmable_set_parent(struct clk *clk, u8 index)
pckr |= AT91_PMC_CSSMCK_MCK;
}
- regmap_write_bits(prog->regmap, AT91_PMC_PCKR(prog->id), mask, pckr);
+ regmap_update_bits(prog->regmap, AT91_PMC_PCKR(prog->id), mask, pckr);
return 0;
}
-static int clk_programmable_get_parent(struct clk *clk)
+static int clk_programmable_get_parent(struct clk_hw *hw)
{
- struct clk_programmable *prog = to_clk_programmable(clk);
+ struct clk_programmable *prog = to_clk_programmable(hw);
const struct clk_programmable_layout *layout = prog->layout;
unsigned int pckr;
u8 ret;
@@ -85,13 +86,16 @@ static int clk_programmable_get_parent(struct clk *clk)
if (layout->have_slck_mck && (pckr & AT91_PMC_CSSMCK_MCK) && !ret)
ret = PROG_MAX_RM9200_CSS + 1;
+ if (prog->mux_table)
+ ret = clk_mux_val_to_index(&prog->hw, prog->mux_table, 0, ret);
+
return ret;
}
-static int clk_programmable_set_rate(struct clk *clk, unsigned long rate,
+static int clk_programmable_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_programmable *prog = to_clk_programmable(clk);
+ struct clk_programmable *prog = to_clk_programmable(hw);
const struct clk_programmable_layout *layout = prog->layout;
unsigned long div = parent_rate / rate;
int shift = 0;
@@ -114,9 +118,9 @@ static int clk_programmable_set_rate(struct clk *clk, unsigned long rate,
return -EINVAL;
}
- regmap_write_bits(prog->regmap, AT91_PMC_PCKR(prog->id),
- layout->pres_mask << layout->pres_shift,
- shift << layout->pres_shift);
+ regmap_update_bits(prog->regmap, AT91_PMC_PCKR(prog->id),
+ layout->pres_mask << layout->pres_shift,
+ shift << layout->pres_shift);
return 0;
}
@@ -128,13 +132,16 @@ static const struct clk_ops programmable_ops = {
.set_rate = clk_programmable_set_rate,
};
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_programmable(struct regmap *regmap,
const char *name, const char **parent_names,
u8 num_parents, u8 id,
- const struct clk_programmable_layout *layout)
+ const struct clk_programmable_layout *layout,
+ u32 *mux_table)
{
struct clk_programmable *prog;
+ struct clk_hw *hw;
+ struct clk_init_data init;
int ret;
if (id > PROG_ID_MAX)
@@ -144,27 +151,26 @@ at91_clk_register_programmable(struct regmap *regmap,
if (!prog)
return ERR_PTR(-ENOMEM);
- prog->clk.name = name;
- prog->clk.ops = &programmable_ops;
- memcpy(prog->parent_names, parent_names,
- num_parents * sizeof(prog->parent_names[0]));
- prog->clk.parent_names = &prog->parent_names[0];
- prog->clk.num_parents = num_parents;
- /* init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; */
+ init.name = name;
+ init.ops = &programmable_ops;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+ init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
prog->id = id;
prog->layout = layout;
+ prog->hw.init = &init;
prog->regmap = regmap;
+ prog->mux_table = mux_table;
- ret = clk_register(&prog->clk);
+ hw = &prog->hw;
+ ret = clk_hw_register(NULL, &prog->hw);
if (ret) {
kfree(prog);
- return ERR_PTR(ret);
+ hw = ERR_PTR(ret);
}
- pmc_register_pck(id);
-
- return &prog->clk;
+ return hw;
}
const struct clk_programmable_layout at91rm9200_programmable_layout = {
diff --git a/drivers/clk/at91/clk-sam9x60-pll.c b/drivers/clk/at91/clk-sam9x60-pll.c
index 9ca77f8722..c4f1606128 100644
--- a/drivers/clk/at91/clk-sam9x60-pll.c
+++ b/drivers/clk/at91/clk-sam9x60-pll.c
@@ -4,319 +4,654 @@
*
*/
-#include <common.h>
-#include <clock.h>
-#include <of.h>
-#include <linux/list.h>
+#include <linux/bitfield.h>
#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/clk/at91_pmc.h>
+#include <of.h>
#include <mfd/syscon.h>
-#include <regmap.h>
-#include <linux/bitfield.h>
+#include <linux/regmap.h>
#include "pmc.h"
-#define PMC_PLL_CTRL0 0xc
-#define PMC_PLL_CTRL0_DIV_MSK GENMASK(7, 0)
-#define PMC_PLL_CTRL0_ENPLL BIT(28)
-#define PMC_PLL_CTRL0_ENPLLCK BIT(29)
-#define PMC_PLL_CTRL0_ENLOCK BIT(31)
-
-#define PMC_PLL_CTRL1 0x10
-#define PMC_PLL_CTRL1_FRACR_MSK GENMASK(21, 0)
-#define PMC_PLL_CTRL1_MUL_MSK GENMASK(30, 24)
-
-#define PMC_PLL_ACR 0x18
-#define PMC_PLL_ACR_DEFAULT_UPLL 0x12020010UL
-#define PMC_PLL_ACR_DEFAULT_PLLA 0x00020010UL
-#define PMC_PLL_ACR_UTMIVR BIT(12)
-#define PMC_PLL_ACR_UTMIBG BIT(13)
-#define PMC_PLL_ACR_LOOP_FILTER_MSK GENMASK(31, 24)
-
-#define PMC_PLL_UPDT 0x1c
-#define PMC_PLL_UPDT_UPDATE BIT(8)
-
-#define PMC_PLL_ISR0 0xec
+#define PMC_PLL_CTRL0_DIV_MSK GENMASK(7, 0)
+#define PMC_PLL_CTRL1_MUL_MSK GENMASK(31, 24)
+#define PMC_PLL_CTRL1_FRACR_MSK GENMASK(21, 0)
#define PLL_DIV_MAX (FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, UINT_MAX) + 1)
#define UPLL_DIV 2
#define PLL_MUL_MAX (FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, UINT_MAX) + 1)
-#define PLL_MAX_ID 1
+#define FCORE_MIN (600000000)
+#define FCORE_MAX (1200000000)
-struct sam9x60_pll {
- struct clk clk;
+#define PLL_MAX_ID 7
+
+struct sam9x60_pll_core {
struct regmap *regmap;
+ spinlock_t *lock;
const struct clk_pll_characteristics *characteristics;
- u32 frac;
+ const struct clk_pll_layout *layout;
+ struct clk_hw hw;
u8 id;
- u8 div;
+};
+
+struct sam9x60_frac {
+ struct sam9x60_pll_core core;
+ struct at91_clk_pms pms;
+ u32 frac;
u16 mul;
- const char *parent_name;
};
-#define to_sam9x60_pll(clk) container_of(clk, struct sam9x60_pll, clk)
+struct sam9x60_div {
+ struct sam9x60_pll_core core;
+ struct at91_clk_pms pms;
+ u8 div;
+};
+
+#define to_sam9x60_pll_core(hw) container_of(hw, struct sam9x60_pll_core, hw)
+#define to_sam9x60_frac(core) container_of(core, struct sam9x60_frac, core)
+#define to_sam9x60_div(core) container_of(core, struct sam9x60_div, core)
static inline bool sam9x60_pll_ready(struct regmap *regmap, int id)
{
unsigned int status;
- regmap_read(regmap, PMC_PLL_ISR0, &status);
+ regmap_read(regmap, AT91_PMC_PLL_ISR0, &status);
return !!(status & BIT(id));
}
-static int sam9x60_pll_enable(struct clk *clk)
+static bool sam9x60_frac_pll_ready(struct regmap *regmap, u8 id)
{
- struct sam9x60_pll *pll = to_sam9x60_pll(clk);
- struct regmap *regmap = pll->regmap;
- u8 div;
- u16 mul;
- u32 val;
+ return sam9x60_pll_ready(regmap, id);
+}
- regmap_write(regmap, PMC_PLL_UPDT, pll->id);
+static unsigned long sam9x60_frac_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
+ struct sam9x60_frac *frac = to_sam9x60_frac(core);
- regmap_read(regmap, PMC_PLL_CTRL0, &val);
- div = FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, val);
+ return parent_rate * (frac->mul + 1) +
+ DIV_ROUND_CLOSEST_ULL((u64)parent_rate * frac->frac, (1 << 22));
+}
- regmap_read(regmap, PMC_PLL_CTRL1, &val);
- mul = FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, val);
+static int sam9x60_frac_pll_set(struct sam9x60_pll_core *core)
+{
+ struct sam9x60_frac *frac = to_sam9x60_frac(core);
+ struct regmap *regmap = core->regmap;
+ unsigned int val, cfrac, cmul;
+ unsigned long flags;
- if (sam9x60_pll_ready(regmap, pll->id) &&
- (div == pll->div && mul == pll->mul)) {
- return 0;
- }
+ spin_lock_irqsave(core->lock, flags);
+
+ regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
+ AT91_PMC_PLL_UPDT_ID_MSK, core->id);
+ regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val);
+ cmul = (val & core->layout->mul_mask) >> core->layout->mul_shift;
+ cfrac = (val & core->layout->frac_mask) >> core->layout->frac_shift;
+
+ if (sam9x60_frac_pll_ready(regmap, core->id) &&
+ (cmul == frac->mul && cfrac == frac->frac))
+ goto unlock;
/* Recommended value for PMC_PLL_ACR */
- if (pll->characteristics->upll)
- val = PMC_PLL_ACR_DEFAULT_UPLL;
+ if (core->characteristics->upll)
+ val = AT91_PMC_PLL_ACR_DEFAULT_UPLL;
else
- val = PMC_PLL_ACR_DEFAULT_PLLA;
- regmap_write(regmap, PMC_PLL_ACR, val);
+ val = AT91_PMC_PLL_ACR_DEFAULT_PLLA;
+ regmap_write(regmap, AT91_PMC_PLL_ACR, val);
- regmap_write(regmap, PMC_PLL_CTRL1,
- FIELD_PREP(PMC_PLL_CTRL1_MUL_MSK, pll->mul));
+ regmap_write(regmap, AT91_PMC_PLL_CTRL1,
+ (frac->mul << core->layout->mul_shift) |
+ (frac->frac << core->layout->frac_shift));
- if (pll->characteristics->upll) {
+ if (core->characteristics->upll) {
/* Enable the UTMI internal bandgap */
- val |= PMC_PLL_ACR_UTMIBG;
- regmap_write(regmap, PMC_PLL_ACR, val);
+ val |= AT91_PMC_PLL_ACR_UTMIBG;
+ regmap_write(regmap, AT91_PMC_PLL_ACR, val);
udelay(10);
/* Enable the UTMI internal regulator */
- val |= PMC_PLL_ACR_UTMIVR;
- regmap_write(regmap, PMC_PLL_ACR, val);
+ val |= AT91_PMC_PLL_ACR_UTMIVR;
+ regmap_write(regmap, AT91_PMC_PLL_ACR, val);
udelay(10);
}
- regmap_update_bits(regmap, PMC_PLL_UPDT,
- PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE);
+ regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
+ AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
+ AT91_PMC_PLL_UPDT_UPDATE | core->id);
- regmap_write(regmap, PMC_PLL_CTRL0,
- PMC_PLL_CTRL0_ENLOCK | PMC_PLL_CTRL0_ENPLL |
- PMC_PLL_CTRL0_ENPLLCK | pll->div);
+ regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
+ AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL,
+ AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL);
- regmap_update_bits(regmap, PMC_PLL_UPDT,
- PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE);
+ regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
+ AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
+ AT91_PMC_PLL_UPDT_UPDATE | core->id);
- while (!sam9x60_pll_ready(regmap, pll->id))
+ while (!sam9x60_pll_ready(regmap, core->id))
cpu_relax();
+unlock:
+ spin_unlock_irqrestore(core->lock, flags);
+
return 0;
}
-static int sam9x60_pll_is_enabled(struct clk *clk)
+static int sam9x60_frac_pll_prepare(struct clk_hw *hw)
{
- struct sam9x60_pll *pll = to_sam9x60_pll(clk);
+ struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
- return sam9x60_pll_ready(pll->regmap, pll->id);
+ return sam9x60_frac_pll_set(core);
}
-static void sam9x60_pll_disable(struct clk *clk)
+static void sam9x60_frac_pll_unprepare(struct clk_hw *hw)
{
- struct sam9x60_pll *pll = to_sam9x60_pll(clk);
+ struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
+ struct regmap *regmap = core->regmap;
+ unsigned long flags;
- regmap_write(pll->regmap, PMC_PLL_UPDT, pll->id);
+ spin_lock_irqsave(core->lock, flags);
- regmap_update_bits(pll->regmap, PMC_PLL_CTRL0,
- PMC_PLL_CTRL0_ENPLLCK, 0);
+ regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
+ AT91_PMC_PLL_UPDT_ID_MSK, core->id);
- regmap_update_bits(pll->regmap, PMC_PLL_UPDT,
- PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE);
+ regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0, AT91_PMC_PLL_CTRL0_ENPLL, 0);
- regmap_update_bits(pll->regmap, PMC_PLL_CTRL0, PMC_PLL_CTRL0_ENPLL, 0);
+ if (core->characteristics->upll)
+ regmap_update_bits(regmap, AT91_PMC_PLL_ACR,
+ AT91_PMC_PLL_ACR_UTMIBG | AT91_PMC_PLL_ACR_UTMIVR, 0);
- if (pll->characteristics->upll)
- regmap_update_bits(pll->regmap, PMC_PLL_ACR,
- PMC_PLL_ACR_UTMIBG | PMC_PLL_ACR_UTMIVR, 0);
+ regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
+ AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
+ AT91_PMC_PLL_UPDT_UPDATE | core->id);
- regmap_update_bits(pll->regmap, PMC_PLL_UPDT,
- PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE);
+ spin_unlock_irqrestore(core->lock, flags);
}
-static unsigned long sam9x60_pll_recalc_rate(struct clk *clk,
- unsigned long parent_rate)
+static int sam9x60_frac_pll_is_prepared(struct clk_hw *hw)
{
- struct sam9x60_pll *pll = to_sam9x60_pll(clk);
+ struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
- return (parent_rate * (pll->mul + 1)) / (pll->div + 1);
+ return sam9x60_pll_ready(core->regmap, core->id);
}
-static long sam9x60_pll_get_best_div_mul(struct sam9x60_pll *pll,
- unsigned long rate,
- unsigned long parent_rate,
- bool update)
+static long sam9x60_frac_pll_compute_mul_frac(struct sam9x60_pll_core *core,
+ unsigned long rate,
+ unsigned long parent_rate,
+ bool update)
{
- const struct clk_pll_characteristics *characteristics =
- pll->characteristics;
- unsigned long bestremainder = ULONG_MAX;
- unsigned long maxdiv, mindiv, tmpdiv;
- long bestrate = -ERANGE;
- unsigned long bestdiv = 0;
- unsigned long bestmul = 0;
- unsigned long bestfrac = 0;
+ struct sam9x60_frac *frac = to_sam9x60_frac(core);
+ unsigned long tmprate, remainder;
+ unsigned long nmul = 0;
+ unsigned long nfrac = 0;
- if (rate < characteristics->output[0].min ||
- rate > characteristics->output[0].max)
+ if (rate < FCORE_MIN || rate > FCORE_MAX)
return -ERANGE;
- if (!pll->characteristics->upll) {
- mindiv = parent_rate / rate;
- if (mindiv < 2)
- mindiv = 2;
+ /*
+ * Calculate the multiplier associated with the current
+ * divider that provide the closest rate to the requested one.
+ */
+ nmul = mult_frac(rate, 1, parent_rate);
+ tmprate = mult_frac(parent_rate, nmul, 1);
+ remainder = rate - tmprate;
- maxdiv = DIV_ROUND_UP(parent_rate * PLL_MUL_MAX, rate);
- if (maxdiv > PLL_DIV_MAX)
- maxdiv = PLL_DIV_MAX;
- } else {
- mindiv = maxdiv = UPLL_DIV;
+ if (remainder) {
+ nfrac = DIV_ROUND_CLOSEST_ULL((u64)remainder * (1 << 22),
+ parent_rate);
+
+ tmprate += DIV_ROUND_CLOSEST_ULL((u64)nfrac * parent_rate,
+ (1 << 22));
}
- for (tmpdiv = mindiv; tmpdiv <= maxdiv; tmpdiv++) {
- unsigned long remainder;
- unsigned long tmprate;
- unsigned long tmpmul;
- unsigned long tmpfrac = 0;
+ /* Check if resulted rate is a valid. */
+ if (tmprate < FCORE_MIN || tmprate > FCORE_MAX)
+ return -ERANGE;
- /*
- * Calculate the multiplier associated with the current
- * divider that provide the closest rate to the requested one.
- */
- tmpmul = mult_frac(rate, tmpdiv, parent_rate);
- tmprate = mult_frac(parent_rate, tmpmul, tmpdiv);
- remainder = rate - tmprate;
+ if (update) {
+ frac->mul = nmul - 1;
+ frac->frac = nfrac;
+ }
- if (remainder) {
- tmpfrac = DIV_ROUND_CLOSEST_ULL((u64)remainder * tmpdiv * (1 << 22),
- parent_rate);
+ return tmprate;
+}
- tmprate += DIV_ROUND_CLOSEST_ULL((u64)tmpfrac * parent_rate,
- tmpdiv * (1 << 22));
+static long sam9x60_frac_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
- if (tmprate > rate)
- remainder = tmprate - rate;
- else
- remainder = rate - tmprate;
- }
+ return sam9x60_frac_pll_compute_mul_frac(core, rate, *parent_rate, false);
+}
- /*
- * Compare the remainder with the best remainder found until
- * now and elect a new best multiplier/divider pair if the
- * current remainder is smaller than the best one.
- */
- if (remainder < bestremainder) {
- bestremainder = remainder;
- bestdiv = tmpdiv;
- bestmul = tmpmul;
- bestrate = tmprate;
- bestfrac = tmpfrac;
+static int sam9x60_frac_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
+
+ return sam9x60_frac_pll_compute_mul_frac(core, rate, parent_rate, true);
+}
+
+static int sam9x60_frac_pll_set_rate_chg(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
+ struct sam9x60_frac *frac = to_sam9x60_frac(core);
+ struct regmap *regmap = core->regmap;
+ unsigned long irqflags;
+ unsigned int val, cfrac, cmul;
+ long ret;
+
+ ret = sam9x60_frac_pll_compute_mul_frac(core, rate, parent_rate, true);
+ if (ret <= 0)
+ return ret;
+
+ spin_lock_irqsave(core->lock, irqflags);
+
+ regmap_update_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
+ core->id);
+ regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val);
+ cmul = (val & core->layout->mul_mask) >> core->layout->mul_shift;
+ cfrac = (val & core->layout->frac_mask) >> core->layout->frac_shift;
+
+ if (cmul == frac->mul && cfrac == frac->frac)
+ goto unlock;
+
+ regmap_write(regmap, AT91_PMC_PLL_CTRL1,
+ (frac->mul << core->layout->mul_shift) |
+ (frac->frac << core->layout->frac_shift));
+
+ regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
+ AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
+ AT91_PMC_PLL_UPDT_UPDATE | core->id);
+
+ regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
+ AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL,
+ AT91_PMC_PLL_CTRL0_ENLOCK |
+ AT91_PMC_PLL_CTRL0_ENPLL);
+
+ regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
+ AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
+ AT91_PMC_PLL_UPDT_UPDATE | core->id);
+
+ while (!sam9x60_pll_ready(regmap, core->id))
+ cpu_relax();
+
+unlock:
+ spin_unlock_irqrestore(core->lock, irqflags);
+
+ return ret;
+}
+
+static const struct clk_ops sam9x60_frac_pll_ops = {
+ .enable = sam9x60_frac_pll_prepare,
+ .disable = sam9x60_frac_pll_unprepare,
+ .is_enabled = sam9x60_frac_pll_is_prepared,
+ .recalc_rate = sam9x60_frac_pll_recalc_rate,
+ .round_rate = sam9x60_frac_pll_round_rate,
+ .set_rate = sam9x60_frac_pll_set_rate,
+};
+
+static const struct clk_ops sam9x60_frac_pll_ops_chg = {
+ .enable = sam9x60_frac_pll_prepare,
+ .disable = sam9x60_frac_pll_unprepare,
+ .is_enabled = sam9x60_frac_pll_is_prepared,
+ .recalc_rate = sam9x60_frac_pll_recalc_rate,
+ .round_rate = sam9x60_frac_pll_round_rate,
+ .set_rate = sam9x60_frac_pll_set_rate_chg,
+};
+
+/* This function should be called with spinlock acquired. */
+static void sam9x60_div_pll_set_div(struct sam9x60_pll_core *core, u32 div,
+ bool enable)
+{
+ struct regmap *regmap = core->regmap;
+ u32 ena_msk = enable ? core->layout->endiv_mask : 0;
+ u32 ena_val = enable ? (1 << core->layout->endiv_shift) : 0;
+
+ regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
+ core->layout->div_mask | ena_msk,
+ (div << core->layout->div_shift) | ena_val);
+
+ regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
+ AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
+ AT91_PMC_PLL_UPDT_UPDATE | core->id);
+
+ while (!sam9x60_pll_ready(regmap, core->id))
+ cpu_relax();
+}
+
+static int sam9x60_div_pll_set(struct sam9x60_pll_core *core)
+{
+ struct sam9x60_div *div = to_sam9x60_div(core);
+ struct regmap *regmap = core->regmap;
+ unsigned long flags;
+ unsigned int val, cdiv;
+
+ spin_lock_irqsave(core->lock, flags);
+ regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
+ AT91_PMC_PLL_UPDT_ID_MSK, core->id);
+ regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
+ cdiv = (val & core->layout->div_mask) >> core->layout->div_shift;
+
+ /* Stop if enabled an nothing changed. */
+ if (!!(val & core->layout->endiv_mask) && cdiv == div->div)
+ goto unlock;
+
+ sam9x60_div_pll_set_div(core, div->div, 1);
+
+unlock:
+ spin_unlock_irqrestore(core->lock, flags);
+
+ return 0;
+}
+
+static int sam9x60_div_pll_prepare(struct clk_hw *hw)
+{
+ struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
+
+ return sam9x60_div_pll_set(core);
+}
+
+static void sam9x60_div_pll_unprepare(struct clk_hw *hw)
+{
+ struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
+ struct regmap *regmap = core->regmap;
+ unsigned long flags;
+
+ spin_lock_irqsave(core->lock, flags);
+
+ regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
+ AT91_PMC_PLL_UPDT_ID_MSK, core->id);
+
+ regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
+ core->layout->endiv_mask, 0);
+
+ regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
+ AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
+ AT91_PMC_PLL_UPDT_UPDATE | core->id);
+
+ spin_unlock_irqrestore(core->lock, flags);
+}
+
+static int sam9x60_div_pll_is_prepared(struct clk_hw *hw)
+{
+ struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
+ struct regmap *regmap = core->regmap;
+ unsigned long flags;
+ unsigned int val;
+
+ spin_lock_irqsave(core->lock, flags);
+
+ regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
+ AT91_PMC_PLL_UPDT_ID_MSK, core->id);
+ regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
+
+ spin_unlock_irqrestore(core->lock, flags);
+
+ return !!(val & core->layout->endiv_mask);
+}
+
+static unsigned long sam9x60_div_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
+ struct sam9x60_div *div = to_sam9x60_div(core);
+
+ return DIV_ROUND_CLOSEST_ULL(parent_rate, (div->div + 1));
+}
+
+static long sam9x60_div_pll_compute_div(struct sam9x60_pll_core *core,
+ unsigned long *parent_rate,
+ unsigned long rate)
+{
+ const struct clk_pll_characteristics *characteristics =
+ core->characteristics;
+ struct clk_hw *parent = clk_hw_get_parent(&core->hw);
+ unsigned long tmp_rate, tmp_parent_rate, tmp_diff;
+ long best_diff = -1, best_rate = -EINVAL;
+ u32 divid;
+
+ if (!rate)
+ return 0;
+
+ if (rate < characteristics->output[0].min ||
+ rate > characteristics->output[0].max)
+ return -ERANGE;
+
+ for (divid = 1; divid < core->layout->div_mask; divid++) {
+ tmp_parent_rate = clk_hw_round_rate(parent, rate * divid);
+ if (!tmp_parent_rate)
+ continue;
+
+ tmp_rate = DIV_ROUND_CLOSEST_ULL(tmp_parent_rate, divid);
+ tmp_diff = abs(rate - tmp_rate);
+
+ if (best_diff < 0 || best_diff > tmp_diff) {
+ *parent_rate = tmp_parent_rate;
+ best_rate = tmp_rate;
+ best_diff = tmp_diff;
}
- /* We've found a perfect match! */
- if (!remainder)
+ if (!best_diff)
break;
}
- /* Check if bestrate is a valid output rate */
- if (bestrate < characteristics->output[0].min &&
- bestrate > characteristics->output[0].max)
+ if (best_rate < characteristics->output[0].min ||
+ best_rate > characteristics->output[0].max)
return -ERANGE;
- if (update) {
- pll->div = bestdiv - 1;
- pll->mul = bestmul - 1;
- pll->frac = bestfrac;
- }
+ return best_rate;
+}
- return bestrate;
+static long sam9x60_div_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
+
+ return sam9x60_div_pll_compute_div(core, parent_rate, rate);
}
-static long sam9x60_pll_round_rate(struct clk *clk, unsigned long rate,
- unsigned long *parent_rate)
+static int sam9x60_div_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
{
- struct sam9x60_pll *pll = to_sam9x60_pll(clk);
+ struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
+ struct sam9x60_div *div = to_sam9x60_div(core);
+
+ div->div = DIV_ROUND_CLOSEST(parent_rate, rate) - 1;
- return sam9x60_pll_get_best_div_mul(pll, rate, *parent_rate, false);
+ return 0;
}
-static int sam9x60_pll_set_rate(struct clk *clk, unsigned long rate,
- unsigned long parent_rate)
+static int sam9x60_div_pll_set_rate_chg(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
{
- struct sam9x60_pll *pll = to_sam9x60_pll(clk);
+ struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
+ struct sam9x60_div *div = to_sam9x60_div(core);
+ struct regmap *regmap = core->regmap;
+ unsigned long irqflags;
+ unsigned int val, cdiv;
+
+ div->div = DIV_ROUND_CLOSEST(parent_rate, rate) - 1;
- return sam9x60_pll_get_best_div_mul(pll, rate, parent_rate, true);
+ spin_lock_irqsave(core->lock, irqflags);
+ regmap_update_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
+ core->id);
+ regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
+ cdiv = (val & core->layout->div_mask) >> core->layout->div_shift;
+
+ /* Stop if nothing changed. */
+ if (cdiv == div->div)
+ goto unlock;
+
+ sam9x60_div_pll_set_div(core, div->div, 0);
+
+unlock:
+ spin_unlock_irqrestore(core->lock, irqflags);
+
+ return 0;
}
-static const struct clk_ops pll_ops = {
- .enable = sam9x60_pll_enable,
- .disable = sam9x60_pll_disable,
- .is_enabled = sam9x60_pll_is_enabled,
- .recalc_rate = sam9x60_pll_recalc_rate,
- .round_rate = sam9x60_pll_round_rate,
- .set_rate = sam9x60_pll_set_rate,
+static const struct clk_ops sam9x60_div_pll_ops = {
+ .enable = sam9x60_div_pll_prepare,
+ .disable = sam9x60_div_pll_unprepare,
+ .is_enabled = sam9x60_div_pll_is_prepared,
+ .recalc_rate = sam9x60_div_pll_recalc_rate,
+ .round_rate = sam9x60_div_pll_round_rate,
+ .set_rate = sam9x60_div_pll_set_rate,
};
-struct clk * __init
-sam9x60_clk_register_pll(struct regmap *regmap,
- const char *name, const char *parent_name, u8 id,
- const struct clk_pll_characteristics *characteristics)
+static const struct clk_ops sam9x60_div_pll_ops_chg = {
+ .enable = sam9x60_div_pll_prepare,
+ .disable = sam9x60_div_pll_unprepare,
+ .is_enabled = sam9x60_div_pll_is_prepared,
+ .recalc_rate = sam9x60_div_pll_recalc_rate,
+ .round_rate = sam9x60_div_pll_round_rate,
+ .set_rate = sam9x60_div_pll_set_rate_chg,
+};
+
+struct clk_hw * __init
+sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
+ const char *name, const char *parent_name,
+ struct clk_hw *parent_hw, u8 id,
+ const struct clk_pll_characteristics *characteristics,
+ const struct clk_pll_layout *layout, u32 flags)
{
- struct sam9x60_pll *pll;
- unsigned int pllr;
+ struct sam9x60_frac *frac;
+ struct clk_hw *hw;
+ struct clk_init_data init;
+ unsigned long parent_rate, irqflags;
+ unsigned int val;
int ret;
- if (id > PLL_MAX_ID)
+ if (id > PLL_MAX_ID || !lock || !parent_hw)
return ERR_PTR(-EINVAL);
- pll = kzalloc(sizeof(*pll), GFP_KERNEL);
- if (!pll)
+ frac = kzalloc(sizeof(*frac), GFP_KERNEL);
+ if (!frac)
return ERR_PTR(-ENOMEM);
- pll->clk.name = name;
- pll->clk.ops = &pll_ops;
- pll->parent_name = parent_name;
- pll->clk.parent_names = &pll->parent_name;
- pll->clk.num_parents = 1;
- /* pll->clk.flags = CLK_SET_RATE_GATE; */
+ init.name = name;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ if (flags & CLK_SET_RATE_GATE)
+ init.ops = &sam9x60_frac_pll_ops;
+ else
+ init.ops = &sam9x60_frac_pll_ops_chg;
+
+ init.flags = flags;
+
+ frac->core.id = id;
+ frac->core.hw.init = &init;
+ frac->core.characteristics = characteristics;
+ frac->core.layout = layout;
+ frac->core.regmap = regmap;
+ frac->core.lock = lock;
+
+ spin_lock_irqsave(frac->core.lock, irqflags);
+ if (sam9x60_pll_ready(regmap, id)) {
+ regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
+ AT91_PMC_PLL_UPDT_ID_MSK, id);
+ regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val);
+ frac->mul = FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, val);
+ frac->frac = FIELD_GET(PMC_PLL_CTRL1_FRACR_MSK, val);
+ } else {
+ /*
+ * This means the PLL is not setup by bootloaders. In this
+ * case we need to set the minimum rate for it. Otherwise
+ * a clock child of this PLL may be enabled before setting
+ * its rate leading to enabling this PLL with unsupported
+ * rate. This will lead to PLL not being locked at all.
+ */
+ parent_rate = clk_hw_get_rate(parent_hw);
+ if (!parent_rate) {
+ hw = ERR_PTR(-EINVAL);
+ goto free;
+ }
+
+ ret = sam9x60_frac_pll_compute_mul_frac(&frac->core, FCORE_MIN,
+ parent_rate, true);
+ if (ret < 0) {
+ hw = ERR_PTR(ret);
+ goto free;
+ }
+ }
+ spin_unlock_irqrestore(frac->core.lock, irqflags);
+
+ hw = &frac->core.hw;
+ ret = clk_hw_register(NULL, hw);
+ if (ret) {
+ kfree(frac);
+ hw = ERR_PTR(ret);
+ }
+
+ return hw;
+
+free:
+ spin_unlock_irqrestore(frac->core.lock, irqflags);
+ kfree(frac);
+ return hw;
+}
+
+struct clk_hw * __init
+sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
+ const char *name, const char *parent_name, u8 id,
+ const struct clk_pll_characteristics *characteristics,
+ const struct clk_pll_layout *layout, u32 flags)
+{
+ struct sam9x60_div *div;
+ struct clk_hw *hw;
+ struct clk_init_data init;
+ unsigned long irqflags;
+ unsigned int val;
+ int ret;
+
+ /* We only support one changeable PLL. */
+ if (id > PLL_MAX_ID || !lock)
+ return ERR_PTR(-EINVAL);
+
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ if (flags & CLK_SET_RATE_GATE)
+ init.ops = &sam9x60_div_pll_ops;
+ else
+ init.ops = &sam9x60_div_pll_ops_chg;
+ init.flags = flags;
+
+ div->core.id = id;
+ div->core.hw.init = &init;
+ div->core.characteristics = characteristics;
+ div->core.layout = layout;
+ div->core.regmap = regmap;
+ div->core.lock = lock;
+
+ spin_lock_irqsave(div->core.lock, irqflags);
- pll->id = id;
- pll->characteristics = characteristics;
- pll->regmap = regmap;
+ regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
+ AT91_PMC_PLL_UPDT_ID_MSK, id);
+ regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
+ div->div = FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, val);
- regmap_write(regmap, PMC_PLL_UPDT, id);
- regmap_read(regmap, PMC_PLL_CTRL0, &pllr);
- pll->div = FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, pllr);
- regmap_read(regmap, PMC_PLL_CTRL1, &pllr);
- pll->mul = FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, pllr);
+ spin_unlock_irqrestore(div->core.lock, irqflags);
- ret = clk_register(&pll->clk);
+ hw = &div->core.hw;
+ ret = clk_hw_register(NULL, hw);
if (ret) {
- kfree(pll);
- return ERR_PTR(ret);
+ kfree(div);
+ hw = ERR_PTR(ret);
}
- return &pll->clk;
+ return hw;
}
diff --git a/drivers/clk/at91/clk-slow.c b/drivers/clk/at91/clk-slow.c
index 960678db1c..3a070d0d34 100644
--- a/drivers/clk/at91/clk-slow.c
+++ b/drivers/clk/at91/clk-slow.c
@@ -5,28 +5,25 @@
* Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
*/
-#include <common.h>
-#include <clock.h>
-#include <io.h>
-#include <linux/list.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/clk/at91_pmc.h>
+#include <of.h>
#include <mfd/syscon.h>
-#include <regmap.h>
+#include <linux/regmap.h>
#include "pmc.h"
struct clk_sam9260_slow {
- struct clk clk;
+ struct clk_hw hw;
struct regmap *regmap;
- const char *parent_names[2];
};
-#define to_clk_sam9260_slow(clk) container_of(clk, struct clk_sam9260_slow, clk)
+#define to_clk_sam9260_slow(hw) container_of(hw, struct clk_sam9260_slow, hw)
-static int clk_sam9260_slow_get_parent(struct clk *clk)
+static int clk_sam9260_slow_get_parent(struct clk_hw *hw)
{
- struct clk_sam9260_slow *slowck = to_clk_sam9260_slow(clk);
+ struct clk_sam9260_slow *slowck = to_clk_sam9260_slow(hw);
unsigned int status;
regmap_read(slowck->regmap, AT91_PMC_SR, &status);
@@ -38,13 +35,15 @@ static const struct clk_ops sam9260_slow_ops = {
.get_parent = clk_sam9260_slow_get_parent,
};
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_sam9260_slow(struct regmap *regmap,
const char *name,
const char **parent_names,
int num_parents)
{
struct clk_sam9260_slow *slowck;
+ struct clk_hw *hw;
+ struct clk_init_data init;
int ret;
if (!name)
@@ -53,20 +52,25 @@ at91_clk_register_sam9260_slow(struct regmap *regmap,
if (!parent_names || !num_parents)
return ERR_PTR(-EINVAL);
- slowck = xzalloc(sizeof(*slowck));
- slowck->clk.name = name;
- slowck->clk.ops = &sam9260_slow_ops;
- memcpy(slowck->parent_names, parent_names,
- num_parents * sizeof(slowck->parent_names[0]));
- slowck->clk.parent_names = slowck->parent_names;
- slowck->clk.num_parents = num_parents;
+ slowck = kzalloc(sizeof(*slowck), GFP_KERNEL);
+ if (!slowck)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &sam9260_slow_ops;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+ init.flags = 0;
+
+ slowck->hw.init = &init;
slowck->regmap = regmap;
- ret = clk_register(&slowck->clk);
+ hw = &slowck->hw;
+ ret = clk_hw_register(NULL, &slowck->hw);
if (ret) {
kfree(slowck);
- return ERR_PTR(ret);
+ hw = ERR_PTR(ret);
}
- return &slowck->clk;
+ return hw;
}
diff --git a/drivers/clk/at91/clk-smd.c b/drivers/clk/at91/clk-smd.c
index 0027ebc8bb..dc1b150750 100644
--- a/drivers/clk/at91/clk-smd.c
+++ b/drivers/clk/at91/clk-smd.c
@@ -3,35 +3,30 @@
* Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
*/
-#include <common.h>
-#include <clock.h>
-#include <io.h>
-#include <linux/list.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/clk/at91_pmc.h>
+#include <of.h>
#include <mfd/syscon.h>
-#include <regmap.h>
+#include <linux/regmap.h>
#include "pmc.h"
-#define SMD_SOURCE_MAX 2
-
#define SMD_DIV_SHIFT 8
#define SMD_MAX_DIV 0xf
struct at91sam9x5_clk_smd {
- struct clk clk;
+ struct clk_hw hw;
struct regmap *regmap;
- const char *parent_names[SMD_SOURCE_MAX];
};
-#define to_at91sam9x5_clk_smd(clk) \
- container_of(clk, struct at91sam9x5_clk_smd, clk)
+#define to_at91sam9x5_clk_smd(hw) \
+ container_of(hw, struct at91sam9x5_clk_smd, hw)
-static unsigned long at91sam9x5_clk_smd_recalc_rate(struct clk *clk,
+static unsigned long at91sam9x5_clk_smd_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(clk);
+ struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw);
unsigned int smdr;
u8 smddiv;
@@ -41,7 +36,7 @@ static unsigned long at91sam9x5_clk_smd_recalc_rate(struct clk *clk,
return parent_rate / (smddiv + 1);
}
-static long at91sam9x5_clk_smd_round_rate(struct clk *clk, unsigned long rate,
+static long at91sam9x5_clk_smd_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
unsigned long div;
@@ -63,22 +58,22 @@ static long at91sam9x5_clk_smd_round_rate(struct clk *clk, unsigned long rate,
return bestrate;
}
-static int at91sam9x5_clk_smd_set_parent(struct clk *clk, u8 index)
+static int at91sam9x5_clk_smd_set_parent(struct clk_hw *hw, u8 index)
{
- struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(clk);
+ struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw);
if (index > 1)
return -EINVAL;
- regmap_write_bits(smd->regmap, AT91_PMC_SMD, AT91_PMC_SMDS,
- index ? AT91_PMC_SMDS : 0);
+ regmap_update_bits(smd->regmap, AT91_PMC_SMD, AT91_PMC_SMDS,
+ index ? AT91_PMC_SMDS : 0);
return 0;
}
-static int at91sam9x5_clk_smd_get_parent(struct clk *clk)
+static int at91sam9x5_clk_smd_get_parent(struct clk_hw *hw)
{
- struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(clk);
+ struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw);
unsigned int smdr;
regmap_read(smd->regmap, AT91_PMC_SMD, &smdr);
@@ -86,17 +81,17 @@ static int at91sam9x5_clk_smd_get_parent(struct clk *clk)
return smdr & AT91_PMC_SMDS;
}
-static int at91sam9x5_clk_smd_set_rate(struct clk *clk, unsigned long rate,
+static int at91sam9x5_clk_smd_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(clk);
+ struct at91sam9x5_clk_smd *smd = to_at91sam9x5_clk_smd(hw);
unsigned long div = parent_rate / rate;
if (parent_rate % rate || div < 1 || div > (SMD_MAX_DIV + 1))
return -EINVAL;
- regmap_write_bits(smd->regmap, AT91_PMC_SMD, AT91_PMC_SMD_DIV,
- (div - 1) << SMD_DIV_SHIFT);
+ regmap_update_bits(smd->regmap, AT91_PMC_SMD, AT91_PMC_SMD_DIV,
+ (div - 1) << SMD_DIV_SHIFT);
return 0;
}
@@ -109,28 +104,34 @@ static const struct clk_ops at91sam9x5_smd_ops = {
.set_rate = at91sam9x5_clk_smd_set_rate,
};
-struct clk * __init
+struct clk_hw * __init
at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name,
const char **parent_names, u8 num_parents)
{
struct at91sam9x5_clk_smd *smd;
+ struct clk_hw *hw;
+ struct clk_init_data init;
int ret;
- smd = xzalloc(sizeof(*smd));
- smd->clk.name = name;
- smd->clk.ops = &at91sam9x5_smd_ops;
- memcpy(smd->parent_names, parent_names,
- num_parents * sizeof(smd->parent_names[0]));
- smd->clk.parent_names = smd->parent_names;
- smd->clk.num_parents = num_parents;
- /* init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; */
+ smd = kzalloc(sizeof(*smd), GFP_KERNEL);
+ if (!smd)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &at91sam9x5_smd_ops;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+ init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
+
+ smd->hw.init = &init;
smd->regmap = regmap;
- ret = clk_register(&smd->clk);
+ hw = &smd->hw;
+ ret = clk_hw_register(NULL, &smd->hw);
if (ret) {
kfree(smd);
- return ERR_PTR(ret);
+ hw = ERR_PTR(ret);
}
- return &smd->clk;
+ return hw;
}
diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c
index 77f0dff98b..5f367e292a 100644
--- a/drivers/clk/at91/clk-system.c
+++ b/drivers/clk/at91/clk-system.c
@@ -2,14 +2,13 @@
/*
* Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
*/
-#include <common.h>
-#include <clock.h>
-#include <io.h>
-#include <linux/list.h>
-#include <linux/clk.h>
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/clk/at91_pmc.h>
+#include <of.h>
#include <mfd/syscon.h>
-#include <regmap.h>
+#include <linux/regmap.h>
#include "pmc.h"
@@ -17,12 +16,12 @@
#define SYSTEM_MAX_NAME_SZ 32
-#define to_clk_system(clk) container_of(clk, struct clk_system, clk)
+#define to_clk_system(hw) container_of(hw, struct clk_system, hw)
struct clk_system {
- struct clk clk;
+ struct clk_hw hw;
struct regmap *regmap;
+ struct at91_clk_pms pms;
u8 id;
- const char *parent_name;
};
static inline int is_pck(int id)
@@ -36,12 +35,12 @@ static inline bool clk_system_ready(struct regmap *regmap, int id)
regmap_read(regmap, AT91_PMC_SR, &status);
- return status & (1 << id) ? 1 : 0;
+ return !!(status & (1 << id));
}
-static int clk_system_enable(struct clk *clk)
+static int clk_system_prepare(struct clk_hw *hw)
{
- struct clk_system *sys = to_clk_system(clk);
+ struct clk_system *sys = to_clk_system(hw);
regmap_write(sys->regmap, AT91_PMC_SCER, 1 << sys->id);
@@ -49,21 +48,21 @@ static int clk_system_enable(struct clk *clk)
return 0;
while (!clk_system_ready(sys->regmap, sys->id))
- barrier();
+ cpu_relax();
return 0;
}
-static void clk_system_disable(struct clk *clk)
+static void clk_system_unprepare(struct clk_hw *hw)
{
- struct clk_system *sys = to_clk_system(clk);
+ struct clk_system *sys = to_clk_system(hw);
regmap_write(sys->regmap, AT91_PMC_SCDR, 1 << sys->id);
}
-static int clk_system_is_enabled(struct clk *clk)
+static int clk_system_is_prepared(struct clk_hw *hw)
{
- struct clk_system *sys = to_clk_system(clk);
+ struct clk_system *sys = to_clk_system(hw);
unsigned int status;
regmap_read(sys->regmap, AT91_PMC_SCSR, &status);
@@ -76,40 +75,47 @@ static int clk_system_is_enabled(struct clk *clk)
regmap_read(sys->regmap, AT91_PMC_SR, &status);
- return status & (1 << sys->id) ? 1 : 0;
+ return !!(status & (1 << sys->id));
}
static const struct clk_ops system_ops = {
- .enable = clk_system_enable,
- .disable = clk_system_disable,
- .is_enabled = clk_system_is_enabled,
+ .enable = clk_system_prepare,
+ .disable = clk_system_unprepare,
+ .is_enabled = clk_system_is_prepared,
};
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_system(struct regmap *regmap, const char *name,
- const char *parent_name, u8 id)
+ const char *parent_name, u8 id, unsigned long flags)
{
struct clk_system *sys;
+ struct clk_hw *hw;
+ struct clk_init_data init;
int ret;
if (!parent_name || id > SYSTEM_MAX_ID)
return ERR_PTR(-EINVAL);
- sys = xzalloc(sizeof(*sys));
- sys->clk.name = name;
- sys->clk.ops = &system_ops;
- sys->parent_name = parent_name;
- sys->clk.parent_names = &sys->parent_name;
- sys->clk.num_parents = 1;
- /* init.flags = CLK_SET_RATE_PARENT; */
+ sys = kzalloc(sizeof(*sys), GFP_KERNEL);
+ if (!sys)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &system_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = CLK_SET_RATE_PARENT | flags;
+
sys->id = id;
+ sys->hw.init = &init;
sys->regmap = regmap;
- ret = clk_register(&sys->clk);
+ hw = &sys->hw;
+ ret = clk_hw_register(NULL, &sys->hw);
if (ret) {
kfree(sys);
- return ERR_PTR(ret);
+ hw = ERR_PTR(ret);
}
- return &sys->clk;
+ return hw;
}
diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c
index 2cf68593c0..4473dc7c34 100644
--- a/drivers/clk/at91/clk-usb.c
+++ b/drivers/clk/at91/clk-usb.c
@@ -3,19 +3,15 @@
* Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
*/
-#include <common.h>
-#include <clock.h>
-#include <io.h>
-#include <linux/list.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/clk/at91_pmc.h>
+#include <of.h>
#include <mfd/syscon.h>
-#include <regmap.h>
+#include <linux/regmap.h>
#include "pmc.h"
-#define USB_SOURCE_MAX 2
-
#define SAM9X5_USB_DIV_SHIFT 8
#define SAM9X5_USB_MAX_DIV 0xf
@@ -26,29 +22,29 @@
#define SAM9X60_USBS_MASK GENMASK(1, 0)
struct at91sam9x5_clk_usb {
- struct clk clk;
+ struct clk_hw hw;
struct regmap *regmap;
- const char *parent_names[USB_SOURCE_MAX];
+ struct at91_clk_pms pms;
u32 usbs_mask;
+ u8 num_parents;
};
-#define to_at91sam9x5_clk_usb(clk) \
- container_of(clk, struct at91sam9x5_clk_usb, clk)
+#define to_at91sam9x5_clk_usb(hw) \
+ container_of(hw, struct at91sam9x5_clk_usb, hw)
struct at91rm9200_clk_usb {
- struct clk clk;
+ struct clk_hw hw;
struct regmap *regmap;
u32 divisors[4];
- const char *parent_name;
};
-#define to_at91rm9200_clk_usb(clk) \
- container_of(clk, struct at91rm9200_clk_usb, clk)
+#define to_at91rm9200_clk_usb(hw) \
+ container_of(hw, struct at91rm9200_clk_usb, hw)
-static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk *clk,
+static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(clk);
+ struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
unsigned int usbr;
u8 usbdiv;
@@ -58,21 +54,21 @@ static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk *clk,
return DIV_ROUND_CLOSEST(parent_rate, (usbdiv + 1));
}
-static int at91sam9x5_clk_usb_set_parent(struct clk *clk, u8 index)
+static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index)
{
- struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(clk);
+ struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
- if (index > 1)
+ if (index >= usb->num_parents)
return -EINVAL;
- regmap_write_bits(usb->regmap, AT91_PMC_USB, usb->usbs_mask, index);
+ regmap_update_bits(usb->regmap, AT91_PMC_USB, usb->usbs_mask, index);
return 0;
}
-static int at91sam9x5_clk_usb_get_parent(struct clk *clk)
+static int at91sam9x5_clk_usb_get_parent(struct clk_hw *hw)
{
- struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(clk);
+ struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
unsigned int usbr;
regmap_read(usb->regmap, AT91_PMC_USB, &usbr);
@@ -80,10 +76,10 @@ static int at91sam9x5_clk_usb_get_parent(struct clk *clk)
return usbr & usb->usbs_mask;
}
-static int at91sam9x5_clk_usb_set_rate(struct clk *clk, unsigned long rate,
+static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(clk);
+ struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
unsigned long div;
if (!rate)
@@ -93,8 +89,8 @@ static int at91sam9x5_clk_usb_set_rate(struct clk *clk, unsigned long rate,
if (div > SAM9X5_USB_MAX_DIV + 1 || !div)
return -EINVAL;
- regmap_write_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_OHCIUSBDIV,
- (div - 1) << SAM9X5_USB_DIV_SHIFT);
+ regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_OHCIUSBDIV,
+ (div - 1) << SAM9X5_USB_DIV_SHIFT);
return 0;
}
@@ -106,26 +102,26 @@ static const struct clk_ops at91sam9x5_usb_ops = {
.set_rate = at91sam9x5_clk_usb_set_rate,
};
-static int at91sam9n12_clk_usb_enable(struct clk *clk)
+static int at91sam9n12_clk_usb_enable(struct clk_hw *hw)
{
- struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(clk);
+ struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
- regmap_write_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS,
- AT91_PMC_USBS);
+ regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS,
+ AT91_PMC_USBS);
return 0;
}
-static void at91sam9n12_clk_usb_disable(struct clk *clk)
+static void at91sam9n12_clk_usb_disable(struct clk_hw *hw)
{
- struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(clk);
+ struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
- regmap_write_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS, 0);
+ regmap_update_bits(usb->regmap, AT91_PMC_USB, AT91_PMC_USBS, 0);
}
-static int at91sam9n12_clk_usb_is_enabled(struct clk *clk)
+static int at91sam9n12_clk_usb_is_enabled(struct clk_hw *hw)
{
- struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(clk);
+ struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
unsigned int usbr;
regmap_read(usb->regmap, AT91_PMC_USB, &usbr);
@@ -141,37 +137,43 @@ static const struct clk_ops at91sam9n12_usb_ops = {
.set_rate = at91sam9x5_clk_usb_set_rate,
};
-static struct clk * __init
+static struct clk_hw * __init
_at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
const char **parent_names, u8 num_parents,
u32 usbs_mask)
{
struct at91sam9x5_clk_usb *usb;
+ struct clk_hw *hw;
+ struct clk_init_data init;
int ret;
usb = kzalloc(sizeof(*usb), GFP_KERNEL);
- usb->clk.name = name;
- usb->clk.ops = &at91sam9x5_usb_ops;
- memcpy(usb->parent_names, parent_names,
- num_parents * sizeof(usb->parent_names[0]));
- usb->clk.parent_names = usb->parent_names;
- usb->clk.num_parents = num_parents;
- usb->clk.flags = CLK_SET_RATE_PARENT;
- /* init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | */
- /* CLK_SET_RATE_PARENT; */
+ if (!usb)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &at91sam9x5_usb_ops;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+ init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
+ CLK_SET_RATE_PARENT;
+
+ usb->hw.init = &init;
usb->regmap = regmap;
- usb->usbs_mask = SAM9X5_USBS_MASK;
+ usb->usbs_mask = usbs_mask;
+ usb->num_parents = num_parents;
- ret = clk_register(&usb->clk);
+ hw = &usb->hw;
+ ret = clk_hw_register(NULL, &usb->hw);
if (ret) {
kfree(usb);
- return ERR_PTR(ret);
+ hw = ERR_PTR(ret);
}
- return &usb->clk;
+ return hw;
}
-struct clk * __init
+struct clk_hw * __init
at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
const char **parent_names, u8 num_parents)
{
@@ -179,7 +181,7 @@ at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
num_parents, SAM9X5_USBS_MASK);
}
-struct clk * __init
+struct clk_hw * __init
sam9x60_clk_register_usb(struct regmap *regmap, const char *name,
const char **parent_names, u8 num_parents)
{
@@ -187,35 +189,42 @@ sam9x60_clk_register_usb(struct regmap *regmap, const char *name,
num_parents, SAM9X60_USBS_MASK);
}
-struct clk * __init
+struct clk_hw * __init
at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name,
const char *parent_name)
{
struct at91sam9x5_clk_usb *usb;
+ struct clk_hw *hw;
+ struct clk_init_data init;
int ret;
- usb = xzalloc(sizeof(*usb));
- usb->clk.name = name;
- usb->clk.ops = &at91sam9n12_usb_ops;
- usb->parent_names[0] = parent_name;
- usb->clk.parent_names = &usb->parent_names[0];
- usb->clk.num_parents = 1;
- /* init.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT; */
+ usb = kzalloc(sizeof(*usb), GFP_KERNEL);
+ if (!usb)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &at91sam9n12_usb_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT;
+
+ usb->hw.init = &init;
usb->regmap = regmap;
- ret = clk_register(&usb->clk);
+ hw = &usb->hw;
+ ret = clk_hw_register(NULL, &usb->hw);
if (ret) {
kfree(usb);
- return ERR_PTR(ret);
+ hw = ERR_PTR(ret);
}
- return &usb->clk;
+ return hw;
}
-static unsigned long at91rm9200_clk_usb_recalc_rate(struct clk *clk,
+static unsigned long at91rm9200_clk_usb_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(clk);
+ struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
unsigned int pllbr;
u8 usbdiv;
@@ -228,11 +237,11 @@ static unsigned long at91rm9200_clk_usb_recalc_rate(struct clk *clk,
return 0;
}
-static long at91rm9200_clk_usb_round_rate(struct clk *clk, unsigned long rate,
+static long at91rm9200_clk_usb_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
- struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(clk);
- struct clk *parent = clk_get_parent(clk);
+ struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
+ struct clk_hw *parent = clk_hw_get_parent(hw);
unsigned long bestrate = 0;
int bestdiff = -1;
unsigned long tmprate;
@@ -246,7 +255,7 @@ static long at91rm9200_clk_usb_round_rate(struct clk *clk, unsigned long rate,
continue;
tmp_parent_rate = rate * usb->divisors[i];
- tmp_parent_rate = clk_round_rate(parent, tmp_parent_rate);
+ tmp_parent_rate = clk_hw_round_rate(parent, tmp_parent_rate);
tmprate = DIV_ROUND_CLOSEST(tmp_parent_rate, usb->divisors[i]);
if (tmprate < rate)
tmpdiff = rate - tmprate;
@@ -266,11 +275,11 @@ static long at91rm9200_clk_usb_round_rate(struct clk *clk, unsigned long rate,
return bestrate;
}
-static int at91rm9200_clk_usb_set_rate(struct clk *clk, unsigned long rate,
+static int at91rm9200_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
int i;
- struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(clk);
+ struct at91rm9200_clk_usb *usb = to_at91rm9200_clk_usb(hw);
unsigned long div;
if (!rate)
@@ -280,9 +289,9 @@ static int at91rm9200_clk_usb_set_rate(struct clk *clk, unsigned long rate,
for (i = 0; i < RM9200_USB_DIV_TAB_SIZE; i++) {
if (usb->divisors[i] == div) {
- regmap_write_bits(usb->regmap, AT91_CKGR_PLLBR,
- AT91_PMC_USBDIV,
- i << RM9200_USB_DIV_SHIFT);
+ regmap_update_bits(usb->regmap, AT91_CKGR_PLLBR,
+ AT91_PMC_USBDIV,
+ i << RM9200_USB_DIV_SHIFT);
return 0;
}
@@ -297,29 +306,35 @@ static const struct clk_ops at91rm9200_usb_ops = {
.set_rate = at91rm9200_clk_usb_set_rate,
};
-struct clk * __init
+struct clk_hw * __init
at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
const char *parent_name, const u32 *divisors)
{
struct at91rm9200_clk_usb *usb;
+ struct clk_hw *hw;
+ struct clk_init_data init;
int ret;
- usb = xzalloc(sizeof(*usb));
- usb->clk.name = name;
- usb->clk.ops = &at91rm9200_usb_ops;
- usb->parent_name = parent_name;
- usb->clk.parent_names = &usb->parent_name;
- usb->clk.num_parents = 1;
- /* init.flags = CLK_SET_RATE_PARENT; */
+ usb = kzalloc(sizeof(*usb), GFP_KERNEL);
+ if (!usb)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &at91rm9200_usb_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = CLK_SET_RATE_PARENT;
+ usb->hw.init = &init;
usb->regmap = regmap;
memcpy(usb->divisors, divisors, sizeof(usb->divisors));
- ret = clk_register(&usb->clk);
+ hw = &usb->hw;
+ ret = clk_hw_register(NULL, &usb->hw);
if (ret) {
kfree(usb);
- return ERR_PTR(ret);
+ hw = ERR_PTR(ret);
}
- return &usb->clk;
+ return hw;
}
diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c
index 3d71cd615f..7d85e43024 100644
--- a/drivers/clk/at91/clk-utmi.c
+++ b/drivers/clk/at91/clk-utmi.c
@@ -3,15 +3,14 @@
* Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
*/
-#include <common.h>
-#include <clock.h>
-#include <linux/list.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/clk/at91_pmc.h>
+#include <of.h>
#include <mfd/syscon.h>
-#include <regmap.h>
-
+#include <linux/regmap.h>
#include <soc/at91/atmel-sfr.h>
+#include <linux/printk.h>
#include "pmc.h"
@@ -19,16 +18,16 @@
* The purpose of this clock is to generate a 480 MHz signal. A different
* rate can't be configured.
*/
-#define UTMI_RATE 480000000
+#define UTMI_RATE 480000000
struct clk_utmi {
- struct clk clk;
- const char *parent;
+ struct clk_hw hw;
struct regmap *regmap_pmc;
struct regmap *regmap_sfr;
+ struct at91_clk_pms pms;
};
-#define to_clk_utmi(clk) container_of(clk, struct clk_utmi, clk)
+#define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw)
static inline bool clk_utmi_ready(struct regmap *regmap)
{
@@ -39,10 +38,10 @@ static inline bool clk_utmi_ready(struct regmap *regmap)
return status & AT91_PMC_LOCKU;
}
-static int clk_utmi_enable(struct clk *clk)
+static int clk_utmi_prepare(struct clk_hw *hw)
{
- struct clk *hw_parent;
- struct clk_utmi *utmi = to_clk_utmi(clk);
+ struct clk_hw *hw_parent;
+ struct clk_utmi *utmi = to_clk_utmi(hw);
unsigned int uckr = AT91_PMC_UPLLEN | AT91_PMC_UPLLCOUNT |
AT91_PMC_BIASEN;
unsigned int utmi_ref_clk_freq;
@@ -53,8 +52,8 @@ static int clk_utmi_enable(struct clk *clk)
* FREQ field of the SFR_UTMICKTRIM register to generate properly
* the utmi clock.
*/
- hw_parent = clk_get_parent(clk);
- parent_rate = clk_get_rate(hw_parent);
+ hw_parent = clk_hw_get_parent(hw);
+ parent_rate = clk_hw_get_rate(hw_parent);
switch (parent_rate) {
case 12000000:
@@ -78,80 +77,173 @@ static int clk_utmi_enable(struct clk *clk)
return -EINVAL;
}
-
if (utmi->regmap_sfr) {
- regmap_write_bits(utmi->regmap_sfr, AT91_SFR_UTMICKTRIM,
- AT91_UTMICKTRIM_FREQ, utmi_ref_clk_freq);
+ regmap_update_bits(utmi->regmap_sfr, AT91_SFR_UTMICKTRIM,
+ AT91_UTMICKTRIM_FREQ, utmi_ref_clk_freq);
} else if (utmi_ref_clk_freq) {
pr_err("UTMICK: sfr node required\n");
return -EINVAL;
}
- regmap_write_bits(utmi->regmap_pmc, AT91_CKGR_UCKR, uckr, uckr);
+ regmap_update_bits(utmi->regmap_pmc, AT91_CKGR_UCKR, uckr, uckr);
while (!clk_utmi_ready(utmi->regmap_pmc))
- barrier();
+ cpu_relax();
return 0;
}
-static int clk_utmi_is_enabled(struct clk *clk)
+static int clk_utmi_is_prepared(struct clk_hw *hw)
{
- struct clk_utmi *utmi = to_clk_utmi(clk);
+ struct clk_utmi *utmi = to_clk_utmi(hw);
return clk_utmi_ready(utmi->regmap_pmc);
}
-static void clk_utmi_disable(struct clk *clk)
+static void clk_utmi_unprepare(struct clk_hw *hw)
{
- struct clk_utmi *utmi = to_clk_utmi(clk);
+ struct clk_utmi *utmi = to_clk_utmi(hw);
- regmap_write_bits(utmi->regmap_pmc, AT91_CKGR_UCKR,
- AT91_PMC_UPLLEN, 0);
+ regmap_update_bits(utmi->regmap_pmc, AT91_CKGR_UCKR,
+ AT91_PMC_UPLLEN, 0);
}
-static unsigned long clk_utmi_recalc_rate(struct clk *clk,
+static unsigned long clk_utmi_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- /* UTMI clk rate is fixed */
+ /* UTMI clk rate is fixed. */
return UTMI_RATE;
}
static const struct clk_ops utmi_ops = {
- .enable = clk_utmi_enable,
- .disable = clk_utmi_disable,
- .is_enabled = clk_utmi_is_enabled,
+ .enable = clk_utmi_prepare,
+ .disable = clk_utmi_unprepare,
+ .is_enabled = clk_utmi_is_prepared,
.recalc_rate = clk_utmi_recalc_rate,
};
-struct clk * __init
-at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
- const char *name, const char *parent_name)
+static struct clk_hw * __init
+at91_clk_register_utmi_internal(struct regmap *regmap_pmc,
+ struct regmap *regmap_sfr,
+ const char *name, const char *parent_name,
+ const struct clk_ops *ops, unsigned long flags)
{
- int ret;
struct clk_utmi *utmi;
+ struct clk_hw *hw;
+ struct clk_init_data init;
+ int ret;
- utmi = xzalloc(sizeof(*utmi));
-
- utmi->clk.name = name;
- utmi->clk.ops = &utmi_ops;
-
- if (parent_name) {
- utmi->parent = parent_name;
- utmi->clk.parent_names = &utmi->parent;
- utmi->clk.num_parents = 1;
- }
+ utmi = kzalloc(sizeof(*utmi), GFP_KERNEL);
+ if (!utmi)
+ return ERR_PTR(-ENOMEM);
- /* utmi->clk.flags = CLK_SET_RATE_GATE; */
+ init.name = name;
+ init.ops = ops;
+ init.parent_names = parent_name ? &parent_name : NULL;
+ init.num_parents = parent_name ? 1 : 0;
+ init.flags = flags;
+ utmi->hw.init = &init;
utmi->regmap_pmc = regmap_pmc;
utmi->regmap_sfr = regmap_sfr;
- ret = clk_register(&utmi->clk);
+ hw = &utmi->hw;
+ ret = clk_hw_register(NULL, &utmi->hw);
if (ret) {
kfree(utmi);
- return ERR_PTR(ret);
+ hw = ERR_PTR(ret);
}
- return &utmi->clk;
+ return hw;
+}
+
+struct clk_hw * __init
+at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
+ const char *name, const char *parent_name)
+{
+ return at91_clk_register_utmi_internal(regmap_pmc, regmap_sfr, name,
+ parent_name, &utmi_ops, CLK_SET_RATE_GATE);
+}
+
+static int clk_utmi_sama7g5_prepare(struct clk_hw *hw)
+{
+ struct clk_utmi *utmi = to_clk_utmi(hw);
+ struct clk_hw *hw_parent;
+ unsigned long parent_rate;
+ unsigned int val;
+
+ hw_parent = clk_hw_get_parent(hw);
+ parent_rate = clk_hw_get_rate(hw_parent);
+
+ switch (parent_rate) {
+ case 16000000:
+ val = 0;
+ break;
+ case 20000000:
+ val = 2;
+ break;
+ case 24000000:
+ val = 3;
+ break;
+ case 32000000:
+ val = 5;
+ break;
+ default:
+ pr_err("UTMICK: unsupported main_xtal rate\n");
+ return -EINVAL;
+ }
+
+ regmap_write(utmi->regmap_pmc, AT91_PMC_XTALF, val);
+
+ return 0;
+
+}
+
+static int clk_utmi_sama7g5_is_prepared(struct clk_hw *hw)
+{
+ struct clk_utmi *utmi = to_clk_utmi(hw);
+ struct clk_hw *hw_parent;
+ unsigned long parent_rate;
+ unsigned int val;
+
+ hw_parent = clk_hw_get_parent(hw);
+ parent_rate = clk_hw_get_rate(hw_parent);
+
+ regmap_read(utmi->regmap_pmc, AT91_PMC_XTALF, &val);
+ switch (val & 0x7) {
+ case 0:
+ if (parent_rate == 16000000)
+ return 1;
+ break;
+ case 2:
+ if (parent_rate == 20000000)
+ return 1;
+ break;
+ case 3:
+ if (parent_rate == 24000000)
+ return 1;
+ break;
+ case 5:
+ if (parent_rate == 32000000)
+ return 1;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static const struct clk_ops sama7g5_utmi_ops = {
+ .enable = clk_utmi_sama7g5_prepare,
+ .is_enabled = clk_utmi_sama7g5_is_prepared,
+ .recalc_rate = clk_utmi_recalc_rate,
+};
+
+struct clk_hw * __init
+at91_clk_sama7g5_register_utmi(struct regmap *regmap_pmc, const char *name,
+ const char *parent_name)
+{
+ return at91_clk_register_utmi_internal(regmap_pmc, NULL, name,
+ parent_name, &sama7g5_utmi_ops, 0);
}
diff --git a/drivers/clk/at91/dt-compat.c b/drivers/clk/at91/dt-compat.c
deleted file mode 100644
index b888249199..0000000000
--- a/drivers/clk/at91/dt-compat.c
+++ /dev/null
@@ -1,727 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <of.h>
-#include <driver.h>
-#include <regmap.h>
-#include <mfd/syscon.h>
-
-
-#include "pmc.h"
-
-#define MASTER_SOURCE_MAX 4
-
-#define PERIPHERAL_AT91RM9200 0
-#define PERIPHERAL_AT91SAM9X5 1
-
-#define PERIPHERAL_MAX 64
-
-#define PERIPHERAL_ID_MIN 2
-
-#define PROG_SOURCE_MAX 5
-#define PROG_ID_MAX 7
-
-#define SYSTEM_MAX_ID 31
-
-static const struct clk_pcr_layout dt_pcr_layout = {
- .offset = 0x10c,
- .cmd = BIT(12),
- .pid_mask = GENMASK(5, 0),
- .div_mask = GENMASK(17, 16),
- .gckcss_mask = GENMASK(10, 8),
-};
-
-static void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np)
-{
- struct clk *hw;
- const char *name = np->name;
- const char *parent_name;
- struct regmap *regmap;
- bool bypass;
-
- of_property_read_string(np, "clock-output-names", &name);
- bypass = of_property_read_bool(np, "atmel,osc-bypass");
- parent_name = of_clk_get_parent_name(np, 0);
-
- regmap = syscon_node_to_regmap(of_get_parent(np));
- if (IS_ERR(regmap))
- return;
-
- hw = at91_clk_register_main_osc(regmap, name, parent_name, bypass);
- if (IS_ERR(hw))
- return;
-
- of_clk_add_provider(np, of_clk_src_simple_get, hw);
-}
-CLK_OF_DECLARE(at91rm9200_clk_main_osc, "atmel,at91rm9200-clk-main-osc",
- of_at91rm9200_clk_main_osc_setup);
-
-static void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np)
-{
- struct clk *hw;
- u32 frequency = 0;
- u32 accuracy = 0;
- const char *name = np->name;
- struct regmap *regmap;
-
- of_property_read_string(np, "clock-output-names", &name);
- of_property_read_u32(np, "clock-frequency", &frequency);
- of_property_read_u32(np, "clock-accuracy", &accuracy);
-
- regmap = syscon_node_to_regmap(of_get_parent(np));
- if (IS_ERR(regmap))
- return;
-
- hw = at91_clk_register_main_rc_osc(regmap, name, frequency, accuracy);
- if (IS_ERR(hw))
- return;
-
- of_clk_add_provider(np, of_clk_src_simple_get, hw);
-}
-CLK_OF_DECLARE(at91sam9x5_clk_main_rc_osc, "atmel,at91sam9x5-clk-main-rc-osc",
- of_at91sam9x5_clk_main_rc_osc_setup);
-
-static void __init of_at91rm9200_clk_main_setup(struct device_node *np)
-{
- struct clk *hw;
- const char *parent_name;
- const char *name = np->name;
- struct regmap *regmap;
-
- parent_name = of_clk_get_parent_name(np, 0);
- of_property_read_string(np, "clock-output-names", &name);
-
- regmap = syscon_node_to_regmap(of_get_parent(np));
- if (IS_ERR(regmap))
- return;
-
- hw = at91_clk_register_rm9200_main(regmap, name, parent_name);
- if (IS_ERR(hw))
- return;
-
- of_clk_add_provider(np, of_clk_src_simple_get, hw);
-}
-CLK_OF_DECLARE(at91rm9200_clk_main, "atmel,at91rm9200-clk-main",
- of_at91rm9200_clk_main_setup);
-
-static void __init of_at91sam9x5_clk_main_setup(struct device_node *np)
-{
- struct clk *hw;
- const char *parent_names[2];
- unsigned int num_parents;
- const char *name = np->name;
- struct regmap *regmap;
-
- num_parents = of_clk_get_parent_count(np);
- if (num_parents == 0 || num_parents > 2)
- return;
-
- of_clk_parent_fill(np, parent_names, num_parents);
- regmap = syscon_node_to_regmap(of_get_parent(np));
- if (IS_ERR(regmap))
- return;
-
- of_property_read_string(np, "clock-output-names", &name);
-
- hw = at91_clk_register_sam9x5_main(regmap, name, parent_names,
- num_parents);
- if (IS_ERR(hw))
- return;
-
- of_clk_add_provider(np, of_clk_src_simple_get, hw);
-}
-CLK_OF_DECLARE(at91sam9x5_clk_main, "atmel,at91sam9x5-clk-main",
- of_at91sam9x5_clk_main_setup);
-
-static struct clk_master_characteristics * __init
-of_at91_clk_master_get_characteristics(struct device_node *np)
-{
- struct clk_master_characteristics *characteristics;
-
- characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
- if (!characteristics)
- return NULL;
-
- if (of_at91_get_clk_range(np, "atmel,clk-output-range", &characteristics->output))
- goto out_free_characteristics;
-
- of_property_read_u32_array(np, "atmel,clk-divisors",
- characteristics->divisors, 4);
-
- characteristics->have_div3_pres =
- of_property_read_bool(np, "atmel,master-clk-have-div3-pres");
-
- return characteristics;
-
-out_free_characteristics:
- kfree(characteristics);
- return NULL;
-}
-
-static void __init
-of_at91_clk_master_setup(struct device_node *np,
- const struct clk_master_layout *layout)
-{
- struct clk *hw;
- unsigned int num_parents;
- const char *parent_names[MASTER_SOURCE_MAX];
- const char *name = np->name;
- struct clk_master_characteristics *characteristics;
- struct regmap *regmap;
-
- num_parents = of_clk_get_parent_count(np);
- if (num_parents == 0 || num_parents > MASTER_SOURCE_MAX)
- return;
-
- of_clk_parent_fill(np, parent_names, num_parents);
-
- of_property_read_string(np, "clock-output-names", &name);
-
- characteristics = of_at91_clk_master_get_characteristics(np);
- if (!characteristics)
- return;
-
- regmap = syscon_node_to_regmap(of_get_parent(np));
- if (IS_ERR(regmap))
- return;
-
- hw = at91_clk_register_master(regmap, name, num_parents,
- parent_names, layout,
- characteristics);
- if (IS_ERR(hw))
- goto out_free_characteristics;
-
- of_clk_add_provider(np, of_clk_src_simple_get, hw);
- return;
-
-out_free_characteristics:
- kfree(characteristics);
-}
-
-static void __init of_at91rm9200_clk_master_setup(struct device_node *np)
-{
- of_at91_clk_master_setup(np, &at91rm9200_master_layout);
-}
-CLK_OF_DECLARE(at91rm9200_clk_master, "atmel,at91rm9200-clk-master",
- of_at91rm9200_clk_master_setup);
-
-static void __init of_at91sam9x5_clk_master_setup(struct device_node *np)
-{
- of_at91_clk_master_setup(np, &at91sam9x5_master_layout);
-}
-CLK_OF_DECLARE(at91sam9x5_clk_master, "atmel,at91sam9x5-clk-master",
- of_at91sam9x5_clk_master_setup);
-
-static void __init
-of_at91_clk_periph_setup(struct device_node *np, u8 type)
-{
- int num;
- u32 id;
- struct clk *hw;
- const char *parent_name;
- const char *name;
- struct device_node *periphclknp;
- struct regmap *regmap;
-
- parent_name = of_clk_get_parent_name(np, 0);
- if (!parent_name)
- return;
-
- num = of_get_child_count(np);
- if (!num || num > PERIPHERAL_MAX)
- return;
-
- regmap = syscon_node_to_regmap(of_get_parent(np));
- if (IS_ERR(regmap))
- return;
-
- for_each_child_of_node(np, periphclknp) {
- if (of_property_read_u32(periphclknp, "reg", &id))
- continue;
-
- if (id >= PERIPHERAL_MAX)
- continue;
-
- if (of_property_read_string(np, "clock-output-names", &name))
- name = periphclknp->name;
-
- if (type == PERIPHERAL_AT91RM9200) {
- hw = at91_clk_register_peripheral(regmap, name,
- parent_name, id);
- } else {
- struct clk_range range = CLK_RANGE(0, 0);
-
- of_at91_get_clk_range(periphclknp,
- "atmel,clk-output-range",
- &range);
-
- hw = at91_clk_register_sam9x5_peripheral(regmap,
- &dt_pcr_layout,
- name,
- parent_name,
- id, &range);
- }
-
- if (IS_ERR(hw))
- continue;
-
- of_clk_add_provider(periphclknp, of_clk_src_simple_get, hw);
- }
-}
-
-static void __init of_at91rm9200_clk_periph_setup(struct device_node *np)
-{
- of_at91_clk_periph_setup(np, PERIPHERAL_AT91RM9200);
-}
-CLK_OF_DECLARE(at91rm9200_clk_periph, "atmel,at91rm9200-clk-peripheral",
- of_at91rm9200_clk_periph_setup);
-
-static void __init of_at91sam9x5_clk_periph_setup(struct device_node *np)
-{
- of_at91_clk_periph_setup(np, PERIPHERAL_AT91SAM9X5);
-}
-CLK_OF_DECLARE(at91sam9x5_clk_periph, "atmel,at91sam9x5-clk-peripheral",
- of_at91sam9x5_clk_periph_setup);
-
-static struct clk_pll_characteristics * __init
-of_at91_clk_pll_get_characteristics(struct device_node *np)
-{
- int i;
- int offset;
- u32 tmp;
- int num_output;
- u32 num_cells;
- struct clk_range input;
- struct clk_range *output;
- u8 *out = NULL;
- u16 *icpll = NULL;
- struct clk_pll_characteristics *characteristics;
-
- if (of_at91_get_clk_range(np, "atmel,clk-input-range", &input))
- return NULL;
-
- if (of_property_read_u32(np, "#atmel,pll-clk-output-range-cells",
- &num_cells))
- return NULL;
-
- if (num_cells < 2 || num_cells > 4)
- return NULL;
-
- if (!of_get_property(np, "atmel,pll-clk-output-ranges", &tmp))
- return NULL;
- num_output = tmp / (sizeof(u32) * num_cells);
-
- characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
- if (!characteristics)
- return NULL;
-
- output = kcalloc(num_output, sizeof(*output), GFP_KERNEL);
- if (!output)
- goto out_free_characteristics;
-
- if (num_cells > 2) {
- out = kcalloc(num_output, sizeof(*out), GFP_KERNEL);
- if (!out)
- goto out_free_output;
- }
-
- if (num_cells > 3) {
- icpll = kcalloc(num_output, sizeof(*icpll), GFP_KERNEL);
- if (!icpll)
- goto out_free_output;
- }
-
- for (i = 0; i < num_output; i++) {
- offset = i * num_cells;
- if (of_property_read_u32_index(np,
- "atmel,pll-clk-output-ranges",
- offset, &tmp))
- goto out_free_output;
- output[i].min = tmp;
- if (of_property_read_u32_index(np,
- "atmel,pll-clk-output-ranges",
- offset + 1, &tmp))
- goto out_free_output;
- output[i].max = tmp;
-
- if (num_cells == 2)
- continue;
-
- if (of_property_read_u32_index(np,
- "atmel,pll-clk-output-ranges",
- offset + 2, &tmp))
- goto out_free_output;
- out[i] = tmp;
-
- if (num_cells == 3)
- continue;
-
- if (of_property_read_u32_index(np,
- "atmel,pll-clk-output-ranges",
- offset + 3, &tmp))
- goto out_free_output;
- icpll[i] = tmp;
- }
-
- characteristics->input = input;
- characteristics->num_output = num_output;
- characteristics->output = output;
- characteristics->out = out;
- characteristics->icpll = icpll;
- return characteristics;
-
-out_free_output:
- kfree(icpll);
- kfree(out);
- kfree(output);
-out_free_characteristics:
- kfree(characteristics);
- return NULL;
-}
-
-static void __init
-of_at91_clk_pll_setup(struct device_node *np,
- const struct clk_pll_layout *layout)
-{
- u32 id;
- struct clk *hw;
- struct regmap *regmap;
- const char *parent_name;
- const char *name = np->name;
- struct clk_pll_characteristics *characteristics;
-
- if (of_property_read_u32(np, "reg", &id))
- return;
-
- parent_name = of_clk_get_parent_name(np, 0);
-
- of_property_read_string(np, "clock-output-names", &name);
-
- regmap = syscon_node_to_regmap(of_get_parent(np));
- if (IS_ERR(regmap))
- return;
-
- characteristics = of_at91_clk_pll_get_characteristics(np);
- if (!characteristics)
- return;
-
- hw = at91_clk_register_pll(regmap, name, parent_name, id, layout,
- characteristics);
- if (IS_ERR(hw))
- goto out_free_characteristics;
-
- of_clk_add_provider(np, of_clk_src_simple_get, hw);
- return;
-
-out_free_characteristics:
- kfree(characteristics);
-}
-
-static void __init of_at91rm9200_clk_pll_setup(struct device_node *np)
-{
- of_at91_clk_pll_setup(np, &at91rm9200_pll_layout);
-}
-CLK_OF_DECLARE(at91rm9200_clk_pll, "atmel,at91rm9200-clk-pll",
- of_at91rm9200_clk_pll_setup);
-
-static void __init of_sama5d3_clk_pll_setup(struct device_node *np)
-{
- of_at91_clk_pll_setup(np, &sama5d3_pll_layout);
-}
-CLK_OF_DECLARE(sama5d3_clk_pll, "atmel,sama5d3-clk-pll",
- of_sama5d3_clk_pll_setup);
-
-static void __init
-of_at91sam9x5_clk_plldiv_setup(struct device_node *np)
-{
- struct clk *hw;
- const char *parent_name;
- const char *name = np->name;
- struct regmap *regmap;
-
- parent_name = of_clk_get_parent_name(np, 0);
-
- of_property_read_string(np, "clock-output-names", &name);
-
- regmap = syscon_node_to_regmap(of_get_parent(np));
- if (IS_ERR(regmap))
- return;
-
- hw = at91_clk_register_plldiv(regmap, name, parent_name);
- if (IS_ERR(hw))
- return;
-
- of_clk_add_provider(np, of_clk_src_simple_get, hw);
-}
-CLK_OF_DECLARE(at91sam9x5_clk_plldiv, "atmel,at91sam9x5-clk-plldiv",
- of_at91sam9x5_clk_plldiv_setup);
-
-static void __init
-of_at91_clk_prog_setup(struct device_node *np,
- const struct clk_programmable_layout *layout)
-{
- int num;
- u32 id;
- struct clk *hw;
- unsigned int num_parents;
- const char *parent_names[PROG_SOURCE_MAX];
- const char *name;
- struct device_node *progclknp;
- struct regmap *regmap;
-
- num_parents = of_clk_get_parent_count(np);
- if (num_parents == 0 || num_parents > PROG_SOURCE_MAX)
- return;
-
- of_clk_parent_fill(np, parent_names, num_parents);
-
- num = of_get_child_count(np);
- if (!num || num > (PROG_ID_MAX + 1))
- return;
-
- regmap = syscon_node_to_regmap(of_get_parent(np));
- if (IS_ERR(regmap))
- return;
-
- for_each_child_of_node(np, progclknp) {
- if (of_property_read_u32(progclknp, "reg", &id))
- continue;
-
- if (of_property_read_string(np, "clock-output-names", &name))
- name = progclknp->name;
-
- hw = at91_clk_register_programmable(regmap, name,
- parent_names, num_parents,
- id, layout);
- if (IS_ERR(hw))
- continue;
-
- of_clk_add_provider(progclknp, of_clk_src_simple_get, hw);
- }
-}
-
-static void __init of_at91rm9200_clk_prog_setup(struct device_node *np)
-{
- of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout);
-}
-CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable",
- of_at91rm9200_clk_prog_setup);
-
-static void __init of_at91sam9g45_clk_prog_setup(struct device_node *np)
-{
- of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout);
-}
-CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable",
- of_at91sam9g45_clk_prog_setup);
-
-static void __init of_at91sam9x5_clk_prog_setup(struct device_node *np)
-{
- of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout);
-}
-CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable",
- of_at91sam9x5_clk_prog_setup);
-
-#ifdef CONFIG_HAVE_AT91_SMD
-#define SMD_SOURCE_MAX 2
-
-static void __init of_at91sam9x5_clk_smd_setup(struct device_node *np)
-{
- struct clk *hw;
- unsigned int num_parents;
- const char *parent_names[SMD_SOURCE_MAX];
- const char *name = np->name;
- struct regmap *regmap;
-
- num_parents = of_clk_get_parent_count(np);
- if (num_parents == 0 || num_parents > SMD_SOURCE_MAX)
- return;
-
- of_clk_parent_fill(np, parent_names, num_parents);
-
- of_property_read_string(np, "clock-output-names", &name);
-
- regmap = syscon_node_to_regmap(of_get_parent(np));
- if (IS_ERR(regmap))
- return;
-
- hw = at91sam9x5_clk_register_smd(regmap, name, parent_names,
- num_parents);
- if (IS_ERR(hw))
- return;
-
- of_clk_add_provider(np, of_clk_src_simple_get, hw);
-}
-CLK_OF_DECLARE(at91sam9x5_clk_smd, "atmel,at91sam9x5-clk-smd",
- of_at91sam9x5_clk_smd_setup);
-#endif /* CONFIG_HAVE_AT91_SMD */
-
-static void __init of_at91rm9200_clk_sys_setup(struct device_node *np)
-{
- int num;
- u32 id;
- struct clk *hw;
- const char *name;
- struct device_node *sysclknp;
- const char *parent_name;
- struct regmap *regmap;
-
- num = of_get_child_count(np);
- if (num > (SYSTEM_MAX_ID + 1))
- return;
-
- regmap = syscon_node_to_regmap(of_get_parent(np));
- if (IS_ERR(regmap))
- return;
-
- for_each_child_of_node(np, sysclknp) {
- if (of_property_read_u32(sysclknp, "reg", &id))
- continue;
-
- if (of_property_read_string(np, "clock-output-names", &name))
- name = sysclknp->name;
-
- parent_name = of_clk_get_parent_name(sysclknp, 0);
-
- hw = at91_clk_register_system(regmap, name, parent_name, id);
- if (IS_ERR(hw))
- continue;
-
- of_clk_add_provider(sysclknp, of_clk_src_simple_get, hw);
- }
-}
-CLK_OF_DECLARE(at91rm9200_clk_sys, "atmel,at91rm9200-clk-system",
- of_at91rm9200_clk_sys_setup);
-
-#ifdef CONFIG_HAVE_AT91_USB_CLK
-#define USB_SOURCE_MAX 2
-
-static void __init of_at91sam9x5_clk_usb_setup(struct device_node *np)
-{
- struct clk *hw;
- unsigned int num_parents;
- const char *parent_names[USB_SOURCE_MAX];
- const char *name = np->name;
- struct regmap *regmap;
-
- num_parents = of_clk_get_parent_count(np);
- if (num_parents == 0 || num_parents > USB_SOURCE_MAX)
- return;
-
- of_clk_parent_fill(np, parent_names, num_parents);
-
- of_property_read_string(np, "clock-output-names", &name);
-
- regmap = syscon_node_to_regmap(of_get_parent(np));
- if (IS_ERR(regmap))
- return;
-
- hw = at91sam9x5_clk_register_usb(regmap, name, parent_names,
- num_parents);
- if (IS_ERR(hw))
- return;
-
- of_clk_add_provider(np, of_clk_src_simple_get, hw);
-}
-CLK_OF_DECLARE(at91sam9x5_clk_usb, "atmel,at91sam9x5-clk-usb",
- of_at91sam9x5_clk_usb_setup);
-
-static void __init of_at91sam9n12_clk_usb_setup(struct device_node *np)
-{
- struct clk *hw;
- const char *parent_name;
- const char *name = np->name;
- struct regmap *regmap;
-
- parent_name = of_clk_get_parent_name(np, 0);
- if (!parent_name)
- return;
-
- of_property_read_string(np, "clock-output-names", &name);
-
- regmap = syscon_node_to_regmap(of_get_parent(np));
- if (IS_ERR(regmap))
- return;
-
- hw = at91sam9n12_clk_register_usb(regmap, name, parent_name);
- if (IS_ERR(hw))
- return;
-
- of_clk_add_provider(np, of_clk_src_simple_get, hw);
-}
-CLK_OF_DECLARE(at91sam9n12_clk_usb, "atmel,at91sam9n12-clk-usb",
- of_at91sam9n12_clk_usb_setup);
-
-static void __init of_at91rm9200_clk_usb_setup(struct device_node *np)
-{
- struct clk *hw;
- const char *parent_name;
- const char *name = np->name;
- u32 divisors[4] = {0, 0, 0, 0};
- struct regmap *regmap;
-
- parent_name = of_clk_get_parent_name(np, 0);
- if (!parent_name)
- return;
-
- of_property_read_u32_array(np, "atmel,clk-divisors", divisors, 4);
- if (!divisors[0])
- return;
-
- of_property_read_string(np, "clock-output-names", &name);
-
- regmap = syscon_node_to_regmap(of_get_parent(np));
- if (IS_ERR(regmap))
- return;
- hw = at91rm9200_clk_register_usb(regmap, name, parent_name, divisors);
- if (IS_ERR(hw))
- return;
-
- of_clk_add_provider(np, of_clk_src_simple_get, hw);
-}
-CLK_OF_DECLARE(at91rm9200_clk_usb, "atmel,at91rm9200-clk-usb",
- of_at91rm9200_clk_usb_setup);
-#endif /* CONFIG_HAVE_AT91_USB_CLK */
-
-#ifdef CONFIG_HAVE_AT91_UTMI
-static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np)
-{
- struct clk *hw;
- const char *parent_name;
- const char *name = np->name;
- struct regmap *regmap_pmc, *regmap_sfr;
-
- parent_name = of_clk_get_parent_name(np, 0);
-
- of_property_read_string(np, "clock-output-names", &name);
-
- regmap_pmc = syscon_node_to_regmap(of_get_parent(np));
- if (IS_ERR(regmap_pmc))
- return;
-
- /*
- * If the device supports different mainck rates, this value has to be
- * set in the UTMI Clock Trimming register.
- * - 9x5: mainck supports several rates but it is indicated that a
- * 12 MHz is needed in case of USB.
- * - sama5d3 and sama5d2: mainck supports several rates. Configuring
- * the FREQ field of the UTMI Clock Trimming register is mandatory.
- * - sama5d4: mainck is at 12 MHz.
- *
- * We only need to retrieve sama5d3 or sama5d2 sfr regmap.
- */
- regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d3-sfr");
- if (IS_ERR(regmap_sfr)) {
- regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
- if (IS_ERR(regmap_sfr))
- regmap_sfr = NULL;
- }
-
- hw = at91_clk_register_utmi(regmap_pmc, regmap_sfr, name, parent_name);
- if (IS_ERR(hw))
- return;
-
- of_clk_add_provider(np, of_clk_src_simple_get, hw);
-}
-CLK_OF_DECLARE(at91sam9x5_clk_utmi, "atmel,at91sam9x5-clk-utmi",
- of_at91sam9x5_clk_utmi_setup);
-#endif /* CONFIG_HAVE_AT91_UTMI */
diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 171b62cbfd..4780b5790d 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -3,14 +3,14 @@
* Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
*/
-#include <module.h>
-#include <linux/list.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/clkdev.h>
+#include <linux/clk/at91_pmc.h>
#include <of.h>
+#include <of_address.h>
#include <mfd/syscon.h>
-#include <regmap.h>
-
-#include <dt-bindings/clock/at91.h>
+#include <linux/regmap.h>
#include "pmc.h"
@@ -40,7 +40,7 @@ int of_at91_get_clk_range(struct device_node *np, const char *propname,
}
EXPORT_SYMBOL_GPL(of_at91_get_clk_range);
-struct clk *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data)
+struct clk_hw *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data)
{
unsigned int type = clkspec->args[0];
unsigned int idx = clkspec->args[1];
@@ -63,6 +63,10 @@ struct clk *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data)
if (idx < pmc_data->ngck)
return pmc_data->ghws[idx];
break;
+ case PMC_TYPE_PROGRAMMABLE:
+ if (idx < pmc_data->npck)
+ return pmc_data->pchws[idx];
+ break;
default:
break;
}
@@ -72,213 +76,32 @@ struct clk *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data)
return ERR_PTR(-EINVAL);
}
-void pmc_data_free(struct pmc_data *pmc_data)
-{
- kfree(pmc_data->chws);
- kfree(pmc_data->shws);
- kfree(pmc_data->phws);
- kfree(pmc_data->ghws);
-}
-
struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
- unsigned int nperiph, unsigned int ngck)
+ unsigned int nperiph, unsigned int ngck,
+ unsigned int npck)
{
- struct pmc_data *pmc_data = kzalloc(sizeof(*pmc_data), GFP_KERNEL);
+ unsigned int num_clks = ncore + nsystem + nperiph + ngck + npck;
+ struct pmc_data *pmc_data;
+ pmc_data = kzalloc(struct_size(pmc_data, hwtable, num_clks),
+ GFP_KERNEL);
if (!pmc_data)
return NULL;
pmc_data->ncore = ncore;
- pmc_data->chws = kcalloc(ncore, sizeof(struct clk *), GFP_KERNEL);
- if (!pmc_data->chws)
- goto err;
+ pmc_data->chws = pmc_data->hwtable;
pmc_data->nsystem = nsystem;
- pmc_data->shws = kcalloc(nsystem, sizeof(struct clk *), GFP_KERNEL);
- if (!pmc_data->shws)
- goto err;
+ pmc_data->shws = pmc_data->chws + ncore;
pmc_data->nperiph = nperiph;
- pmc_data->phws = kcalloc(nperiph, sizeof(struct clk *), GFP_KERNEL);
- if (!pmc_data->phws)
- goto err;
+ pmc_data->phws = pmc_data->shws + nsystem;
pmc_data->ngck = ngck;
- pmc_data->ghws = kcalloc(ngck, sizeof(struct clk *), GFP_KERNEL);
- if (!pmc_data->ghws)
- goto err;
-
- return pmc_data;
-
-err:
- pmc_data_free(pmc_data);
-
- return NULL;
-}
-
-#ifdef CONFIG_PM
-static struct regmap *pmcreg;
-
-static u8 registered_ids[PMC_MAX_IDS];
-static u8 registered_pcks[PMC_MAX_PCKS];
-
-static struct
-{
- u32 scsr;
- u32 pcsr0;
- u32 uckr;
- u32 mor;
- u32 mcfr;
- u32 pllar;
- u32 mckr;
- u32 usb;
- u32 imr;
- u32 pcsr1;
- u32 pcr[PMC_MAX_IDS];
- u32 audio_pll0;
- u32 audio_pll1;
- u32 pckr[PMC_MAX_PCKS];
-} pmc_cache;
-
-/*
- * As Peripheral ID 0 is invalid on AT91 chips, the identifier is stored
- * without alteration in the table, and 0 is for unused clocks.
- */
-void pmc_register_id(u8 id)
-{
- int i;
-
- for (i = 0; i < PMC_MAX_IDS; i++) {
- if (registered_ids[i] == 0) {
- registered_ids[i] = id;
- break;
- }
- if (registered_ids[i] == id)
- break;
- }
-}
-
-/*
- * As Programmable Clock 0 is valid on AT91 chips, there is an offset
- * of 1 between the stored value and the real clock ID.
- */
-void pmc_register_pck(u8 pck)
-{
- int i;
-
- for (i = 0; i < PMC_MAX_PCKS; i++) {
- if (registered_pcks[i] == 0) {
- registered_pcks[i] = pck + 1;
- break;
- }
- if (registered_pcks[i] == (pck + 1))
- break;
- }
-}
-
-static int pmc_suspend(void)
-{
- int i;
- u8 num;
+ pmc_data->ghws = pmc_data->phws + nperiph;
- regmap_read(pmcreg, AT91_PMC_SCSR, &pmc_cache.scsr);
- regmap_read(pmcreg, AT91_PMC_PCSR, &pmc_cache.pcsr0);
- regmap_read(pmcreg, AT91_CKGR_UCKR, &pmc_cache.uckr);
- regmap_read(pmcreg, AT91_CKGR_MOR, &pmc_cache.mor);
- regmap_read(pmcreg, AT91_CKGR_MCFR, &pmc_cache.mcfr);
- regmap_read(pmcreg, AT91_CKGR_PLLAR, &pmc_cache.pllar);
- regmap_read(pmcreg, AT91_PMC_MCKR, &pmc_cache.mckr);
- regmap_read(pmcreg, AT91_PMC_USB, &pmc_cache.usb);
- regmap_read(pmcreg, AT91_PMC_IMR, &pmc_cache.imr);
- regmap_read(pmcreg, AT91_PMC_PCSR1, &pmc_cache.pcsr1);
+ pmc_data->npck = npck;
+ pmc_data->pchws = pmc_data->ghws + ngck;
- for (i = 0; registered_ids[i]; i++) {
- regmap_write(pmcreg, AT91_PMC_PCR,
- (registered_ids[i] & AT91_PMC_PCR_PID_MASK));
- regmap_read(pmcreg, AT91_PMC_PCR,
- &pmc_cache.pcr[registered_ids[i]]);
- }
- for (i = 0; registered_pcks[i]; i++) {
- num = registered_pcks[i] - 1;
- regmap_read(pmcreg, AT91_PMC_PCKR(num), &pmc_cache.pckr[num]);
- }
-
- return 0;
-}
-
-static bool pmc_ready(unsigned int mask)
-{
- unsigned int status;
-
- regmap_read(pmcreg, AT91_PMC_SR, &status);
-
- return ((status & mask) == mask) ? 1 : 0;
-}
-
-static void pmc_resume(void)
-{
- int i;
- u8 num;
- u32 tmp;
- u32 mask = AT91_PMC_MCKRDY | AT91_PMC_LOCKA;
-
- regmap_read(pmcreg, AT91_PMC_MCKR, &tmp);
- if (pmc_cache.mckr != tmp)
- pr_warn("MCKR was not configured properly by the firmware\n");
- regmap_read(pmcreg, AT91_CKGR_PLLAR, &tmp);
- if (pmc_cache.pllar != tmp)
- pr_warn("PLLAR was not configured properly by the firmware\n");
-
- regmap_write(pmcreg, AT91_PMC_SCER, pmc_cache.scsr);
- regmap_write(pmcreg, AT91_PMC_PCER, pmc_cache.pcsr0);
- regmap_write(pmcreg, AT91_CKGR_UCKR, pmc_cache.uckr);
- regmap_write(pmcreg, AT91_CKGR_MOR, pmc_cache.mor);
- regmap_write(pmcreg, AT91_CKGR_MCFR, pmc_cache.mcfr);
- regmap_write(pmcreg, AT91_PMC_USB, pmc_cache.usb);
- regmap_write(pmcreg, AT91_PMC_IMR, pmc_cache.imr);
- regmap_write(pmcreg, AT91_PMC_PCER1, pmc_cache.pcsr1);
-
- for (i = 0; registered_ids[i]; i++) {
- regmap_write(pmcreg, AT91_PMC_PCR,
- pmc_cache.pcr[registered_ids[i]] |
- AT91_PMC_PCR_CMD);
- }
- for (i = 0; registered_pcks[i]; i++) {
- num = registered_pcks[i] - 1;
- regmap_write(pmcreg, AT91_PMC_PCKR(num), pmc_cache.pckr[num]);
- }
-
- if (pmc_cache.uckr & AT91_PMC_UPLLEN)
- mask |= AT91_PMC_LOCKU;
-
- while (!pmc_ready(mask))
- cpu_relax();
-}
-
-static struct syscore_ops pmc_syscore_ops = {
- .suspend = pmc_suspend,
- .resume = pmc_resume,
-};
-
-static const struct of_device_id sama5d2_pmc_dt_ids[] = {
- { .compatible = "atmel,sama5d2-pmc" },
- { /* sentinel */ }
-};
-
-static int __init pmc_register_ops(void)
-{
- struct device_node *np;
-
- np = of_find_matching_node(NULL, sama5d2_pmc_dt_ids);
-
- pmcreg = device_node_to_regmap(np);
- if (IS_ERR(pmcreg))
- return PTR_ERR(pmcreg);
-
- register_syscore_ops(&pmc_syscore_ops);
-
- return 0;
+ return pmc_data;
}
-/* This has to happen before arch_initcall because of the tcb_clksrc driver */
-postcore_initcall(pmc_register_ops);
-#endif
diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
index d96a94e6e5..6c8801a0f9 100644
--- a/drivers/clk/at91/pmc.h
+++ b/drivers/clk/at91/pmc.h
@@ -8,19 +8,29 @@
#ifndef __PMC_H_
#define __PMC_H_
-#include <io.h>
-#include <linux/bitops.h>
-#include <printk.h>
+#include <linux/io.h>
+#include <linux/regmap.h>
+#include <of.h>
+#include <linux/barebox-wrapper.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/clock/at91.h>
+
+extern spinlock_t pmc_pcr_lock;
struct pmc_data {
unsigned int ncore;
- struct clk **chws;
+ struct clk_hw **chws;
unsigned int nsystem;
- struct clk **shws;
+ struct clk_hw **shws;
unsigned int nperiph;
- struct clk **phws;
+ struct clk_hw **phws;
unsigned int ngck;
- struct clk **ghws;
+ struct clk_hw **ghws;
+ unsigned int npck;
+ struct clk_hw **pchws;
+
+ struct clk_hw *hwtable[];
};
struct clk_range {
@@ -41,14 +51,20 @@ extern const struct clk_master_layout at91sam9x5_master_layout;
struct clk_master_characteristics {
struct clk_range output;
- u32 divisors[4];
+ u32 divisors[5];
u8 have_div3_pres;
};
struct clk_pll_layout {
u32 pllr_mask;
- u16 mul_mask;
+ u32 mul_mask;
+ u32 frac_mask;
+ u32 div_mask;
+ u32 endiv_mask;
u8 mul_shift;
+ u8 frac_shift;
+ u8 div_shift;
+ u8 endiv_shift;
};
extern const struct clk_pll_layout at91rm9200_pll_layout;
@@ -85,134 +101,168 @@ struct clk_pcr_layout {
u32 pid_mask;
};
+/**
+ * struct at91_clk_pms - Power management state for AT91 clock
+ * @rate: clock rate
+ * @parent_rate: clock parent rate
+ * @status: clock status (enabled or disabled)
+ * @parent: clock parent index
+ */
+struct at91_clk_pms {
+ unsigned long rate;
+ unsigned long parent_rate;
+ unsigned int status;
+ unsigned int parent;
+};
+
#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
#define ndck(a, s) (a[s - 1].id + 1)
#define nck(a) (a[ARRAY_SIZE(a) - 1].id + 1)
struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
- unsigned int nperiph, unsigned int ngck);
-void pmc_data_free(struct pmc_data *pmc_data);
+ unsigned int nperiph, unsigned int ngck,
+ unsigned int npck);
int of_at91_get_clk_range(struct device_node *np, const char *propname,
struct clk_range *range);
-struct clk *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data);
+struct clk_hw *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data);
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_audio_pll_frac(struct regmap *regmap, const char *name,
const char *parent_name);
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_audio_pll_pad(struct regmap *regmap, const char *name,
const char *parent_name);
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_audio_pll_pmc(struct regmap *regmap, const char *name,
const char *parent_name);
-struct clk * __init
-at91_clk_register_generated(struct regmap *regmap,
+struct clk_hw * __init
+at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
const struct clk_pcr_layout *layout,
const char *name, const char **parent_names,
- u8 num_parents, u8 id, bool pll_audio,
- const struct clk_range *range);
+ u32 *mux_table, u8 num_parents, u8 id,
+ const struct clk_range *range, int chg_pid);
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_h32mx(struct regmap *regmap, const char *name,
const char *parent_name);
-struct clk * __init
+struct clk_hw * __init
at91_clk_i2s_mux_register(struct regmap *regmap, const char *name,
const char * const *parent_names,
unsigned int num_parents, u8 bus_id);
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_main_rc_osc(struct regmap *regmap, const char *name,
u32 frequency, u32 accuracy);
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_main_osc(struct regmap *regmap, const char *name,
const char *parent_name, bool bypass);
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_rm9200_main(struct regmap *regmap,
const char *name,
const char *parent_name);
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_sam9x5_main(struct regmap *regmap, const char *name,
const char **parent_names, int num_parents);
-struct clk * __init
-at91_clk_register_master(struct regmap *regmap, const char *name,
- int num_parents, const char **parent_names,
- const struct clk_master_layout *layout,
- const struct clk_master_characteristics *characteristics);
-
-struct clk * __init
+struct clk_hw * __init
+at91_clk_register_master_pres(struct regmap *regmap, const char *name,
+ int num_parents, const char **parent_names,
+ const struct clk_master_layout *layout,
+ const struct clk_master_characteristics *characteristics,
+ spinlock_t *lock);
+
+struct clk_hw * __init
+at91_clk_register_master_div(struct regmap *regmap, const char *name,
+ const char *parent_names,
+ const struct clk_master_layout *layout,
+ const struct clk_master_characteristics *characteristics,
+ spinlock_t *lock, u32 flags);
+
+struct clk_hw * __init
+at91_clk_sama7g5_register_master(struct regmap *regmap,
+ const char *name, int num_parents,
+ const char **parent_names, u32 *mux_table,
+ spinlock_t *lock, u8 id, bool critical,
+ int chg_pid);
+
+struct clk_hw * __init
at91_clk_register_peripheral(struct regmap *regmap, const char *name,
const char *parent_name, u32 id);
-struct clk * __init
-at91_clk_register_sam9x5_peripheral(struct regmap *regmap,
+struct clk_hw * __init
+at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
const struct clk_pcr_layout *layout,
const char *name, const char *parent_name,
- u32 id, const struct clk_range *range);
+ u32 id, const struct clk_range *range,
+ int chg_pid, unsigned long flags);
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_pll(struct regmap *regmap, const char *name,
const char *parent_name, u8 id,
const struct clk_pll_layout *layout,
const struct clk_pll_characteristics *characteristics);
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_plldiv(struct regmap *regmap, const char *name,
const char *parent_name);
-struct clk * __init
-sam9x60_clk_register_pll(struct regmap *regmap,
- const char *name, const char *parent_name, u8 id,
- const struct clk_pll_characteristics *characteristics);
+struct clk_hw * __init
+sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
+ const char *name, const char *parent_name, u8 id,
+ const struct clk_pll_characteristics *characteristics,
+ const struct clk_pll_layout *layout, u32 flags);
-struct clk * __init
+struct clk_hw * __init
+sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
+ const char *name, const char *parent_name,
+ struct clk_hw *parent_hw, u8 id,
+ const struct clk_pll_characteristics *characteristics,
+ const struct clk_pll_layout *layout, u32 flags);
+
+struct clk_hw * __init
at91_clk_register_programmable(struct regmap *regmap, const char *name,
const char **parent_names, u8 num_parents, u8 id,
- const struct clk_programmable_layout *layout);
+ const struct clk_programmable_layout *layout,
+ u32 *mux_table);
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_sam9260_slow(struct regmap *regmap,
const char *name,
const char **parent_names,
int num_parents);
-struct clk * __init
+struct clk_hw * __init
at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name,
const char **parent_names, u8 num_parents);
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_system(struct regmap *regmap, const char *name,
- const char *parent_name, u8 id);
+ const char *parent_name, u8 id, unsigned long flags);
-struct clk * __init
+struct clk_hw * __init
at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
const char **parent_names, u8 num_parents);
-struct clk * __init
+struct clk_hw * __init
at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name,
const char *parent_name);
-struct clk * __init
+struct clk_hw * __init
sam9x60_clk_register_usb(struct regmap *regmap, const char *name,
const char **parent_names, u8 num_parents);
-
-struct clk * __init
+struct clk_hw * __init
at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
const char *parent_name, const u32 *divisors);
-struct clk * __init
+struct clk_hw * __init
at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
const char *name, const char *parent_name);
-#ifdef CONFIG_PM
-void pmc_register_id(u8 id);
-void pmc_register_pck(u8 pck);
-#else
-static inline void pmc_register_id(u8 id) {}
-static inline void pmc_register_pck(u8 pck) {}
-#endif
+struct clk_hw * __init
+at91_clk_sama7g5_register_utmi(struct regmap *regmap, const char *name,
+ const char *parent_name);
#endif /* __PMC_H_ */
diff --git a/drivers/clk/at91/sam9x60.c b/drivers/clk/at91/sam9x60.c
index 36a7a846ef..3a477ffc95 100644
--- a/drivers/clk/at91/sam9x60.c
+++ b/drivers/clk/at91/sam9x60.c
@@ -1,18 +1,16 @@
-// SPDX-License-Identifier: GPL-2.0
-
-#include <driver.h>
-#include <regmap.h>
-#include <stdio.h>
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/clk-provider.h>
#include <mfd/syscon.h>
-
-#include <linux/clk.h>
#include <linux/slab.h>
-#include <linux/types.h>
+#include <stdio.h>
#include <dt-bindings/clock/at91.h>
#include "pmc.h"
+static DEFINE_SPINLOCK(pmc_pll_lock);
+static DEFINE_SPINLOCK(mck_lock);
+
static const struct clk_master_characteristics mck_characteristics = {
.output = { .min = 140000000, .max = 200000000 },
.divisors = { 1, 2, 4, 3 },
@@ -26,7 +24,7 @@ static const struct clk_master_layout sam9x60_master_layout = {
};
static const struct clk_range plla_outputs[] = {
- { .min = 300000000, .max = 600000000 },
+ { .min = 2343750, .max = 1200000000 },
};
static const struct clk_pll_characteristics plla_characteristics = {
@@ -46,6 +44,20 @@ static const struct clk_pll_characteristics upll_characteristics = {
.upll = true,
};
+static const struct clk_pll_layout pll_frac_layout = {
+ .mul_mask = GENMASK(31, 24),
+ .frac_mask = GENMASK(21, 0),
+ .mul_shift = 24,
+ .frac_shift = 0,
+};
+
+static const struct clk_pll_layout pll_div_layout = {
+ .div_mask = GENMASK(7, 0),
+ .endiv_mask = BIT(29),
+ .div_shift = 0,
+ .endiv_shift = 29,
+};
+
static const struct clk_programmable_layout sam9x60_programmable_layout = {
.pres_mask = 0xff,
.pres_shift = 8,
@@ -64,17 +76,23 @@ static const struct clk_pcr_layout sam9x60_pcr_layout = {
static const struct {
char *n;
char *p;
+ unsigned long flags;
u8 id;
} sam9x60_systemck[] = {
- { .n = "ddrck", .p = "masterck", .id = 2 },
+ /*
+ * ddrck feeds DDR controller and is enabled by bootloader thus we need
+ * to keep it enabled in case there is no Linux consumer for it.
+ */
+ { .n = "ddrck", .p = "masterck_div", .id = 2, .flags = CLK_IS_CRITICAL },
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
- { .n = "qspick", .p = "masterck", .id = 19 },
+ { .n = "qspick", .p = "masterck_div", .id = 19 },
};
static const struct {
char *n;
+ unsigned long flags;
u8 id;
} sam9x60_periphck[] = {
{ .n = "pioA_clk", .id = 2, },
@@ -121,14 +139,17 @@ static const struct {
{ .n = "pioD_clk", .id = 44, },
{ .n = "tcb1_clk", .id = 45, },
{ .n = "dbgu_clk", .id = 47, },
- { .n = "mpddr_clk", .id = 49, },
+ /*
+ * mpddr_clk feeds DDR controller and is enabled by bootloader thus we
+ * need to keep it enabled in case there is no Linux consumer for it.
+ */
+ { .n = "mpddr_clk", .id = 49, .flags = CLK_IS_CRITICAL },
};
static const struct {
char *n;
u8 id;
struct clk_range r;
- bool pll;
} sam9x60_gck[] = {
{ .n = "flex0_gclk", .id = 5, },
{ .n = "flex1_gclk", .id = 6, },
@@ -148,11 +169,9 @@ static const struct {
{ .n = "sdmmc1_gclk", .id = 26, .r = { .min = 0, .max = 105000000 }, },
{ .n = "flex11_gclk", .id = 32, },
{ .n = "flex12_gclk", .id = 33, },
- { .n = "i2s_gclk", .id = 34, .r = { .min = 0, .max = 105000000 },
- .pll = true, },
+ { .n = "i2s_gclk", .id = 34, .r = { .min = 0, .max = 105000000 }, },
{ .n = "pit64b_gclk", .id = 37, },
- { .n = "classd_gclk", .id = 42, .r = { .min = 0, .max = 100000000 },
- .pll = true, },
+ { .n = "classd_gclk", .id = 42, .r = { .min = 0, .max = 100000000 }, },
{ .n = "tcb1_gclk", .id = 45, },
{ .n = "dbgu_gclk", .id = 47, },
};
@@ -163,10 +182,10 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
const char *td_slck_name, *md_slck_name, *mainxtal_name;
struct pmc_data *sam9x60_pmc;
const char *parent_names[6];
+ struct clk_hw *main_osc_hw;
struct regmap *regmap;
- struct clk *hw;
+ struct clk_hw *hw;
int i;
- bool bypass;
i = of_property_match_string(np, "clock-names", "td_slck");
if (i < 0)
@@ -185,28 +204,26 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
return;
mainxtal_name = of_clk_get_parent_name(np, i);
- regmap = syscon_node_to_regmap(np);
+ regmap = device_node_to_regmap(np);
if (IS_ERR(regmap))
return;
- sam9x60_pmc = pmc_data_allocate(PMC_MAIN + 1,
+ sam9x60_pmc = pmc_data_allocate(PMC_PLLACK + 1,
nck(sam9x60_systemck),
nck(sam9x60_periphck),
- nck(sam9x60_gck));
+ nck(sam9x60_gck), 8);
if (!sam9x60_pmc)
return;
- hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 24000000,
+ hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
50000000);
if (IS_ERR(hw))
goto err_free;
- bypass = of_property_read_bool(np, "atmel,osc-bypass");
-
- hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
- bypass);
+ hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, 0);
if (IS_ERR(hw))
goto err_free;
+ main_osc_hw = hw;
parent_names[0] = "main_rc_osc";
parent_names[1] = "main_osc";
@@ -216,13 +233,45 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
sam9x60_pmc->chws[PMC_MAIN] = hw;
- hw = sam9x60_clk_register_pll(regmap, "pllack",
- "mainck", 0, &plla_characteristics);
+ hw = sam9x60_clk_register_frac_pll(regmap, &pmc_pll_lock, "pllack_fracck",
+ "mainck", sam9x60_pmc->chws[PMC_MAIN],
+ 0, &plla_characteristics,
+ &pll_frac_layout,
+ /*
+ * This feeds pllack_divck which
+ * feeds CPU. It should not be
+ * disabled.
+ */
+ CLK_IS_CRITICAL | CLK_SET_RATE_GATE);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ hw = sam9x60_clk_register_div_pll(regmap, &pmc_pll_lock, "pllack_divck",
+ "pllack_fracck", 0, &plla_characteristics,
+ &pll_div_layout,
+ /*
+ * This feeds CPU. It should not
+ * be disabled.
+ */
+ CLK_IS_CRITICAL | CLK_SET_RATE_GATE);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ sam9x60_pmc->chws[PMC_PLLACK] = hw;
+
+ hw = sam9x60_clk_register_frac_pll(regmap, &pmc_pll_lock, "upllck_fracck",
+ "main_osc", main_osc_hw, 1,
+ &upll_characteristics,
+ &pll_frac_layout, CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
- hw = sam9x60_clk_register_pll(regmap, "upllck",
- "main_osc", 1, &upll_characteristics);
+ hw = sam9x60_clk_register_div_pll(regmap, &pmc_pll_lock, "upllck_divck",
+ "upllck_fracck", 1, &upll_characteristics,
+ &pll_div_layout,
+ CLK_SET_RATE_GATE |
+ CLK_SET_PARENT_GATE |
+ CLK_SET_RATE_PARENT);
if (IS_ERR(hw))
goto err_free;
@@ -230,45 +279,55 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
parent_names[0] = md_slck_name;
parent_names[1] = "mainck";
- parent_names[2] = "pllack";
- hw = at91_clk_register_master(regmap, "masterck", 3, parent_names,
- &sam9x60_master_layout,
- &mck_characteristics);
+ parent_names[2] = "pllack_divck";
+ hw = at91_clk_register_master_pres(regmap, "masterck_pres", 3,
+ parent_names, &sam9x60_master_layout,
+ &mck_characteristics, &mck_lock);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ hw = at91_clk_register_master_div(regmap, "masterck_div",
+ "masterck_pres", &sam9x60_master_layout,
+ &mck_characteristics, &mck_lock,
+ CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
sam9x60_pmc->chws[PMC_MCK] = hw;
- parent_names[0] = "pllack";
- parent_names[1] = "upllck";
- parent_names[2] = "mainck";
- parent_names[3] = "mainck";
- hw = sam9x60_clk_register_usb(regmap, "usbck", parent_names, 4);
+ parent_names[0] = "pllack_divck";
+ parent_names[1] = "upllck_divck";
+ parent_names[2] = "main_osc";
+ hw = sam9x60_clk_register_usb(regmap, "usbck", parent_names, 3);
if (IS_ERR(hw))
goto err_free;
parent_names[0] = md_slck_name;
parent_names[1] = td_slck_name;
parent_names[2] = "mainck";
- parent_names[3] = "masterck";
- parent_names[4] = "pllack";
- parent_names[5] = "upllck";
- for (i = 0; i < 8; i++) {
+ parent_names[3] = "masterck_div";
+ parent_names[4] = "pllack_divck";
+ parent_names[5] = "upllck_divck";
+ for (i = 0; i < 2; i++) {
char name[6];
snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
parent_names, 6, i,
- &sam9x60_programmable_layout);
+ &sam9x60_programmable_layout,
+ NULL);
if (IS_ERR(hw))
goto err_free;
+
+ sam9x60_pmc->pchws[i] = hw;
}
for (i = 0; i < ARRAY_SIZE(sam9x60_systemck); i++) {
hw = at91_clk_register_system(regmap, sam9x60_systemck[i].n,
sam9x60_systemck[i].p,
- sam9x60_systemck[i].id);
+ sam9x60_systemck[i].id,
+ sam9x60_systemck[i].flags);
if (IS_ERR(hw))
goto err_free;
@@ -276,12 +335,13 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
}
for (i = 0; i < ARRAY_SIZE(sam9x60_periphck); i++) {
- hw = at91_clk_register_sam9x5_peripheral(regmap,
+ hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&sam9x60_pcr_layout,
sam9x60_periphck[i].n,
- "masterck",
+ "masterck_div",
sam9x60_periphck[i].id,
- &range);
+ &range, INT_MIN,
+ sam9x60_periphck[i].flags);
if (IS_ERR(hw))
goto err_free;
@@ -289,25 +349,24 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
}
for (i = 0; i < ARRAY_SIZE(sam9x60_gck); i++) {
- hw = at91_clk_register_generated(regmap,
+ hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
&sam9x60_pcr_layout,
sam9x60_gck[i].n,
- parent_names, 6,
+ parent_names, NULL, 6,
sam9x60_gck[i].id,
- sam9x60_gck[i].pll,
- &sam9x60_gck[i].r);
+ &sam9x60_gck[i].r, INT_MIN);
if (IS_ERR(hw))
goto err_free;
sam9x60_pmc->ghws[sam9x60_gck[i].id] = hw;
}
- of_clk_add_provider(np, of_clk_hw_pmc_get, sam9x60_pmc);
+ of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sam9x60_pmc);
return;
err_free:
- pmc_data_free(sam9x60_pmc);
+ kfree(sam9x60_pmc);
}
/* Some clks are used for a clocksource */
CLK_OF_DECLARE(sam9x60_pmc, "microchip,sam9x60-pmc", sam9x60_pmc_setup);
diff --git a/drivers/clk/at91/sama5d2.c b/drivers/clk/at91/sama5d2.c
index 731637e4ab..96c0d1f6a4 100644
--- a/drivers/clk/at91/sama5d2.c
+++ b/drivers/clk/at91/sama5d2.c
@@ -1,18 +1,15 @@
-// SPDX-License-Identifier: GPL-2.0
-
-#include <driver.h>
-#include <regmap.h>
-#include <stdio.h>
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/clk-provider.h>
#include <mfd/syscon.h>
-
-#include <linux/clk.h>
#include <linux/slab.h>
-#include <linux/types.h>
+#include <stdio.h>
#include <dt-bindings/clock/at91.h>
#include "pmc.h"
+static DEFINE_SPINLOCK(mck_lock);
+
static const struct clk_master_characteristics mck_characteristics = {
.output = { .min = 124000000, .max = 166000000 },
.divisors = { 1, 2, 4, 3 },
@@ -44,16 +41,21 @@ static const struct clk_pcr_layout sama5d2_pcr_layout = {
static const struct {
char *n;
char *p;
+ unsigned long flags;
u8 id;
} sama5d2_systemck[] = {
- { .n = "ddrck", .p = "masterck", .id = 2 },
- { .n = "lcdck", .p = "masterck", .id = 3 },
- { .n = "uhpck", .p = "usbck", .id = 6 },
- { .n = "udpck", .p = "usbck", .id = 7 },
- { .n = "pck0", .p = "prog0", .id = 8 },
- { .n = "pck1", .p = "prog1", .id = 9 },
- { .n = "pck2", .p = "prog2", .id = 10 },
- { .n = "iscck", .p = "masterck", .id = 18 },
+ /*
+ * ddrck feeds DDR controller and is enabled by bootloader thus we need
+ * to keep it enabled in case there is no Linux consumer for it.
+ */
+ { .n = "ddrck", .p = "masterck_div", .id = 2, .flags = CLK_IS_CRITICAL },
+ { .n = "lcdck", .p = "masterck_div", .id = 3 },
+ { .n = "uhpck", .p = "usbck", .id = 6 },
+ { .n = "udpck", .p = "usbck", .id = 7 },
+ { .n = "pck0", .p = "prog0", .id = 8 },
+ { .n = "pck1", .p = "prog1", .id = 9 },
+ { .n = "pck2", .p = "prog2", .id = 10 },
+ { .n = "iscck", .p = "masterck_div", .id = 18 },
};
static const struct {
@@ -95,11 +97,13 @@ static const struct {
{ .n = "i2s1_clk", .id = 55, .r = { .min = 0, .max = 83000000 }, },
{ .n = "can0_clk", .id = 56, .r = { .min = 0, .max = 83000000 }, },
{ .n = "can1_clk", .id = 57, .r = { .min = 0, .max = 83000000 }, },
+ { .n = "ptc_clk", .id = 58, .r = { .min = 0, .max = 83000000 }, },
{ .n = "classd_clk", .id = 59, .r = { .min = 0, .max = 83000000 }, },
};
static const struct {
char *n;
+ unsigned long flags;
u8 id;
} sama5d2_periphck[] = {
{ .n = "dma0_clk", .id = 6, },
@@ -107,7 +111,11 @@ static const struct {
{ .n = "aes_clk", .id = 9, },
{ .n = "aesb_clk", .id = 10, },
{ .n = "sha_clk", .id = 12, },
- { .n = "mpddr_clk", .id = 13, },
+ /*
+ * mpddr_clk feeds DDR controller and is enabled by bootloader thus we
+ * need to keep it enabled in case there is no Linux consumer for it.
+ */
+ { .n = "mpddr_clk", .id = 13, .flags = CLK_IS_CRITICAL },
{ .n = "matrix0_clk", .id = 15, },
{ .n = "sdmmc0_hclk", .id = 31, },
{ .n = "sdmmc1_hclk", .id = 32, },
@@ -121,21 +129,30 @@ static const struct {
char *n;
u8 id;
struct clk_range r;
- bool pll;
+ int chg_pid;
} sama5d2_gck[] = {
- { .n = "sdmmc0_gclk", .id = 31, },
- { .n = "sdmmc1_gclk", .id = 32, },
- { .n = "tcb0_gclk", .id = 35, .r = { .min = 0, .max = 83000000 }, },
- { .n = "tcb1_gclk", .id = 36, .r = { .min = 0, .max = 83000000 }, },
- { .n = "pwm_gclk", .id = 38, .r = { .min = 0, .max = 83000000 }, },
- { .n = "isc_gclk", .id = 46, },
- { .n = "pdmic_gclk", .id = 48, },
- { .n = "i2s0_gclk", .id = 54, .pll = true },
- { .n = "i2s1_gclk", .id = 55, .pll = true },
- { .n = "can0_gclk", .id = 56, .r = { .min = 0, .max = 80000000 }, },
- { .n = "can1_gclk", .id = 57, .r = { .min = 0, .max = 80000000 }, },
- { .n = "classd_gclk", .id = 59, .r = { .min = 0, .max = 100000000 },
- .pll = true },
+ { .n = "flx0_gclk", .id = 19, .chg_pid = INT_MIN, .r = { .min = 0, .max = 27666666 }, },
+ { .n = "flx1_gclk", .id = 20, .chg_pid = INT_MIN, .r = { .min = 0, .max = 27666666 }, },
+ { .n = "flx2_gclk", .id = 21, .chg_pid = INT_MIN, .r = { .min = 0, .max = 27666666 }, },
+ { .n = "flx3_gclk", .id = 22, .chg_pid = INT_MIN, .r = { .min = 0, .max = 27666666 }, },
+ { .n = "flx4_gclk", .id = 23, .chg_pid = INT_MIN, .r = { .min = 0, .max = 27666666 }, },
+ { .n = "uart0_gclk", .id = 24, .chg_pid = INT_MIN, .r = { .min = 0, .max = 27666666 }, },
+ { .n = "uart1_gclk", .id = 25, .chg_pid = INT_MIN, .r = { .min = 0, .max = 27666666 }, },
+ { .n = "uart2_gclk", .id = 26, .chg_pid = INT_MIN, .r = { .min = 0, .max = 27666666 }, },
+ { .n = "uart3_gclk", .id = 27, .chg_pid = INT_MIN, .r = { .min = 0, .max = 27666666 }, },
+ { .n = "uart4_gclk", .id = 28, .chg_pid = INT_MIN, .r = { .min = 0, .max = 27666666 }, },
+ { .n = "sdmmc0_gclk", .id = 31, .chg_pid = INT_MIN, },
+ { .n = "sdmmc1_gclk", .id = 32, .chg_pid = INT_MIN, },
+ { .n = "tcb0_gclk", .id = 35, .chg_pid = INT_MIN, .r = { .min = 0, .max = 83000000 }, },
+ { .n = "tcb1_gclk", .id = 36, .chg_pid = INT_MIN, .r = { .min = 0, .max = 83000000 }, },
+ { .n = "pwm_gclk", .id = 38, .chg_pid = INT_MIN, .r = { .min = 0, .max = 83000000 }, },
+ { .n = "isc_gclk", .id = 46, .chg_pid = INT_MIN, },
+ { .n = "pdmic_gclk", .id = 48, .chg_pid = INT_MIN, },
+ { .n = "i2s0_gclk", .id = 54, .chg_pid = 5, },
+ { .n = "i2s1_gclk", .id = 55, .chg_pid = 5, },
+ { .n = "can0_gclk", .id = 56, .chg_pid = INT_MIN, .r = { .min = 0, .max = 80000000 }, },
+ { .n = "can1_gclk", .id = 57, .chg_pid = INT_MIN, .r = { .min = 0, .max = 80000000 }, },
+ { .n = "classd_gclk", .id = 59, .chg_pid = 5, .r = { .min = 0, .max = 100000000 }, },
};
static const struct clk_programmable_layout sama5d2_programmable_layout = {
@@ -153,7 +170,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
struct pmc_data *sama5d2_pmc;
const char *parent_names[6];
struct regmap *regmap, *regmap_sfr;
- struct clk *hw;
+ struct clk_hw *hw;
int i;
bool bypass;
@@ -172,10 +189,10 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
if (IS_ERR(regmap))
return;
- sama5d2_pmc = pmc_data_allocate(PMC_I2S1_MUX + 1,
+ sama5d2_pmc = pmc_data_allocate(PMC_AUDIOPINCK + 1,
nck(sama5d2_systemck),
nck(sama5d2_periph32ck),
- nck(sama5d2_gck));
+ nck(sama5d2_gck), 3);
if (!sama5d2_pmc)
return;
@@ -208,6 +225,8 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
if (IS_ERR(hw))
goto err_free;
+ sama5d2_pmc->chws[PMC_PLLACK] = hw;
+
hw = at91_clk_register_audio_pll_frac(regmap, "audiopll_fracck",
"mainck");
if (IS_ERR(hw))
@@ -218,11 +237,15 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
if (IS_ERR(hw))
goto err_free;
+ sama5d2_pmc->chws[PMC_AUDIOPINCK] = hw;
+
hw = at91_clk_register_audio_pll_pmc(regmap, "audiopll_pmcck",
"audiopll_fracck");
if (IS_ERR(hw))
goto err_free;
+ sama5d2_pmc->chws[PMC_AUDIOPLLCK] = hw;
+
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
if (IS_ERR(regmap_sfr))
regmap_sfr = NULL;
@@ -237,15 +260,24 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
- hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
- &at91sam9x5_master_layout,
- &mck_characteristics);
+ hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
+ parent_names,
+ &at91sam9x5_master_layout,
+ &mck_characteristics, &mck_lock);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ hw = at91_clk_register_master_div(regmap, "masterck_div",
+ "masterck_pres",
+ &at91sam9x5_master_layout,
+ &mck_characteristics, &mck_lock,
+ CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
sama5d2_pmc->chws[PMC_MCK] = hw;
- hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck");
+ hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck_div");
if (IS_ERR(hw))
goto err_free;
@@ -261,24 +293,28 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
- parent_names[4] = "masterck";
+ parent_names[4] = "masterck_div";
parent_names[5] = "audiopll_pmcck";
for (i = 0; i < 3; i++) {
- char *name;
+ char name[6];
- name = xasprintf("prog%d", i);
+ snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
parent_names, 6, i,
- &sama5d2_programmable_layout);
+ &sama5d2_programmable_layout,
+ NULL);
if (IS_ERR(hw))
goto err_free;
+
+ sama5d2_pmc->pchws[i] = hw;
}
for (i = 0; i < ARRAY_SIZE(sama5d2_systemck); i++) {
hw = at91_clk_register_system(regmap, sama5d2_systemck[i].n,
sama5d2_systemck[i].p,
- sama5d2_systemck[i].id);
+ sama5d2_systemck[i].id,
+ sama5d2_systemck[i].flags);
if (IS_ERR(hw))
goto err_free;
@@ -286,12 +322,13 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
}
for (i = 0; i < ARRAY_SIZE(sama5d2_periphck); i++) {
- hw = at91_clk_register_sam9x5_peripheral(regmap,
+ hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&sama5d2_pcr_layout,
sama5d2_periphck[i].n,
- "masterck",
+ "masterck_div",
sama5d2_periphck[i].id,
- &range);
+ &range, INT_MIN,
+ sama5d2_periphck[i].flags);
if (IS_ERR(hw))
goto err_free;
@@ -299,12 +336,13 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
}
for (i = 0; i < ARRAY_SIZE(sama5d2_periph32ck); i++) {
- hw = at91_clk_register_sam9x5_peripheral(regmap,
+ hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&sama5d2_pcr_layout,
sama5d2_periph32ck[i].n,
"h32mxck",
sama5d2_periph32ck[i].id,
- &sama5d2_periph32ck[i].r);
+ &sama5d2_periph32ck[i].r,
+ INT_MIN, 0);
if (IS_ERR(hw))
goto err_free;
@@ -315,16 +353,16 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
- parent_names[4] = "masterck";
+ parent_names[4] = "masterck_div";
parent_names[5] = "audiopll_pmcck";
for (i = 0; i < ARRAY_SIZE(sama5d2_gck); i++) {
- hw = at91_clk_register_generated(regmap,
+ hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
&sama5d2_pcr_layout,
sama5d2_gck[i].n,
- parent_names, 6,
+ parent_names, NULL, 6,
sama5d2_gck[i].id,
- sama5d2_gck[i].pll,
- &sama5d2_gck[i].r);
+ &sama5d2_gck[i].r,
+ sama5d2_gck[i].chg_pid);
if (IS_ERR(hw))
goto err_free;
@@ -351,11 +389,12 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
sama5d2_pmc->chws[PMC_I2S1_MUX] = hw;
}
- of_clk_add_provider(np, of_clk_hw_pmc_get, sama5d2_pmc);
+ of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sama5d2_pmc);
return;
err_free:
- pmc_data_free(sama5d2_pmc);
+ kfree(sama5d2_pmc);
}
-CLK_OF_DECLARE_DRIVER(sama5d2_pmc, "atmel,sama5d2-pmc", sama5d2_pmc_setup);
+
+CLK_OF_DECLARE(sama5d2_pmc, "atmel,sama5d2-pmc", sama5d2_pmc_setup);
diff --git a/drivers/clk/at91/sama5d3.c b/drivers/clk/at91/sama5d3.c
new file mode 100644
index 0000000000..53a1a7413a
--- /dev/null
+++ b/drivers/clk/at91/sama5d3.c
@@ -0,0 +1,270 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/clk-provider.h>
+#include <mfd/syscon.h>
+#include <linux/slab.h>
+#include <stdio.h>
+
+#include <dt-bindings/clock/at91.h>
+
+#include "pmc.h"
+
+static DEFINE_SPINLOCK(mck_lock);
+
+static const struct clk_master_characteristics mck_characteristics = {
+ .output = { .min = 0, .max = 166000000 },
+ .divisors = { 1, 2, 4, 3 },
+};
+
+static u8 plla_out[] = { 0 };
+
+static u16 plla_icpll[] = { 0 };
+
+static const struct clk_range plla_outputs[] = {
+ { .min = 400000000, .max = 1000000000 },
+};
+
+static const struct clk_pll_characteristics plla_characteristics = {
+ .input = { .min = 8000000, .max = 50000000 },
+ .num_output = ARRAY_SIZE(plla_outputs),
+ .output = plla_outputs,
+ .icpll = plla_icpll,
+ .out = plla_out,
+};
+
+static const struct clk_pcr_layout sama5d3_pcr_layout = {
+ .offset = 0x10c,
+ .cmd = BIT(12),
+ .pid_mask = GENMASK(6, 0),
+ .div_mask = GENMASK(17, 16),
+};
+
+static const struct {
+ char *n;
+ char *p;
+ unsigned long flags;
+ u8 id;
+} sama5d3_systemck[] = {
+ /*
+ * ddrck feeds DDR controller and is enabled by bootloader thus we need
+ * to keep it enabled in case there is no Linux consumer for it.
+ */
+ { .n = "ddrck", .p = "masterck_div", .id = 2, .flags = CLK_IS_CRITICAL },
+ { .n = "lcdck", .p = "masterck_div", .id = 3 },
+ { .n = "smdck", .p = "smdclk", .id = 4 },
+ { .n = "uhpck", .p = "usbck", .id = 6 },
+ { .n = "udpck", .p = "usbck", .id = 7 },
+ { .n = "pck0", .p = "prog0", .id = 8 },
+ { .n = "pck1", .p = "prog1", .id = 9 },
+ { .n = "pck2", .p = "prog2", .id = 10 },
+};
+
+static const struct {
+ char *n;
+ u8 id;
+ struct clk_range r;
+ unsigned long flags;
+} sama5d3_periphck[] = {
+ { .n = "dbgu_clk", .id = 2, },
+ { .n = "hsmc_clk", .id = 5, },
+ { .n = "pioA_clk", .id = 6, },
+ { .n = "pioB_clk", .id = 7, },
+ { .n = "pioC_clk", .id = 8, },
+ { .n = "pioD_clk", .id = 9, },
+ { .n = "pioE_clk", .id = 10, },
+ { .n = "usart0_clk", .id = 12, .r = { .min = 0, .max = 83000000 }, },
+ { .n = "usart1_clk", .id = 13, .r = { .min = 0, .max = 83000000 }, },
+ { .n = "usart2_clk", .id = 14, .r = { .min = 0, .max = 83000000 }, },
+ { .n = "usart3_clk", .id = 15, .r = { .min = 0, .max = 83000000 }, },
+ { .n = "uart0_clk", .id = 16, .r = { .min = 0, .max = 83000000 }, },
+ { .n = "uart1_clk", .id = 17, .r = { .min = 0, .max = 83000000 }, },
+ { .n = "twi0_clk", .id = 18, .r = { .min = 0, .max = 41500000 }, },
+ { .n = "twi1_clk", .id = 19, .r = { .min = 0, .max = 41500000 }, },
+ { .n = "twi2_clk", .id = 20, .r = { .min = 0, .max = 41500000 }, },
+ { .n = "mci0_clk", .id = 21, },
+ { .n = "mci1_clk", .id = 22, },
+ { .n = "mci2_clk", .id = 23, },
+ { .n = "spi0_clk", .id = 24, .r = { .min = 0, .max = 166000000 }, },
+ { .n = "spi1_clk", .id = 25, .r = { .min = 0, .max = 166000000 }, },
+ { .n = "tcb0_clk", .id = 26, .r = { .min = 0, .max = 166000000 }, },
+ { .n = "tcb1_clk", .id = 27, .r = { .min = 0, .max = 166000000 }, },
+ { .n = "pwm_clk", .id = 28, },
+ { .n = "adc_clk", .id = 29, .r = { .min = 0, .max = 83000000 }, },
+ { .n = "dma0_clk", .id = 30, },
+ { .n = "dma1_clk", .id = 31, },
+ { .n = "uhphs_clk", .id = 32, },
+ { .n = "udphs_clk", .id = 33, },
+ { .n = "macb0_clk", .id = 34, },
+ { .n = "macb1_clk", .id = 35, },
+ { .n = "lcdc_clk", .id = 36, },
+ { .n = "isi_clk", .id = 37, },
+ { .n = "ssc0_clk", .id = 38, .r = { .min = 0, .max = 83000000 }, },
+ { .n = "ssc1_clk", .id = 39, .r = { .min = 0, .max = 83000000 }, },
+ { .n = "can0_clk", .id = 40, .r = { .min = 0, .max = 83000000 }, },
+ { .n = "can1_clk", .id = 41, .r = { .min = 0, .max = 83000000 }, },
+ { .n = "sha_clk", .id = 42, },
+ { .n = "aes_clk", .id = 43, },
+ { .n = "tdes_clk", .id = 44, },
+ { .n = "trng_clk", .id = 45, },
+ { .n = "fuse_clk", .id = 48, },
+ /*
+ * mpddr_clk feeds DDR controller and is enabled by bootloader thus we
+ * need to keep it enabled in case there is no Linux consumer for it.
+ */
+ { .n = "mpddr_clk", .id = 49, .flags = CLK_IS_CRITICAL },
+};
+
+static void __init sama5d3_pmc_setup(struct device_node *np)
+{
+ const char *slck_name, *mainxtal_name;
+ struct pmc_data *sama5d3_pmc;
+ const char *parent_names[5];
+ struct regmap *regmap;
+ struct clk_hw *hw;
+ int i;
+ bool bypass;
+
+ i = of_property_match_string(np, "clock-names", "slow_clk");
+ if (i < 0)
+ return;
+
+ slck_name = of_clk_get_parent_name(np, i);
+
+ i = of_property_match_string(np, "clock-names", "main_xtal");
+ if (i < 0)
+ return;
+ mainxtal_name = of_clk_get_parent_name(np, i);
+
+ regmap = device_node_to_regmap(np);
+ if (IS_ERR(regmap))
+ return;
+
+ sama5d3_pmc = pmc_data_allocate(PMC_PLLACK + 1,
+ nck(sama5d3_systemck),
+ nck(sama5d3_periphck), 0, 3);
+ if (!sama5d3_pmc)
+ return;
+
+ hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
+ 50000000);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ bypass = of_property_read_bool(np, "atmel,osc-bypass");
+
+ hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
+ bypass);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ parent_names[0] = "main_rc_osc";
+ parent_names[1] = "main_osc";
+ hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
+ &sama5d3_pll_layout, &plla_characteristics);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ hw = at91_clk_register_plldiv(regmap, "plladivck", "pllack");
+ if (IS_ERR(hw))
+ goto err_free;
+
+ sama5d3_pmc->chws[PMC_PLLACK] = hw;
+
+ hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
+ if (IS_ERR(hw))
+ goto err_free;
+
+ sama5d3_pmc->chws[PMC_UTMI] = hw;
+
+ parent_names[0] = slck_name;
+ parent_names[1] = "mainck";
+ parent_names[2] = "plladivck";
+ parent_names[3] = "utmick";
+ hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
+ parent_names,
+ &at91sam9x5_master_layout,
+ &mck_characteristics, &mck_lock);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ hw = at91_clk_register_master_div(regmap, "masterck_div",
+ "masterck_pres",
+ &at91sam9x5_master_layout,
+ &mck_characteristics, &mck_lock,
+ CLK_SET_RATE_GATE);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ sama5d3_pmc->chws[PMC_MCK] = hw;
+
+ parent_names[0] = "plladivck";
+ parent_names[1] = "utmick";
+ hw = at91sam9x5_clk_register_usb(regmap, "usbck", parent_names, 2);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ hw = at91sam9x5_clk_register_smd(regmap, "smdclk", parent_names, 2);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ parent_names[0] = slck_name;
+ parent_names[1] = "mainck";
+ parent_names[2] = "plladivck";
+ parent_names[3] = "utmick";
+ parent_names[4] = "masterck_div";
+ for (i = 0; i < 3; i++) {
+ char name[6];
+
+ snprintf(name, sizeof(name), "prog%d", i);
+
+ hw = at91_clk_register_programmable(regmap, name,
+ parent_names, 5, i,
+ &at91sam9x5_programmable_layout,
+ NULL);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ sama5d3_pmc->pchws[i] = hw;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(sama5d3_systemck); i++) {
+ hw = at91_clk_register_system(regmap, sama5d3_systemck[i].n,
+ sama5d3_systemck[i].p,
+ sama5d3_systemck[i].id,
+ sama5d3_systemck[i].flags);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ sama5d3_pmc->shws[sama5d3_systemck[i].id] = hw;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(sama5d3_periphck); i++) {
+ hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
+ &sama5d3_pcr_layout,
+ sama5d3_periphck[i].n,
+ "masterck_div",
+ sama5d3_periphck[i].id,
+ &sama5d3_periphck[i].r,
+ INT_MIN,
+ sama5d3_periphck[i].flags);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ sama5d3_pmc->phws[sama5d3_periphck[i].id] = hw;
+ }
+
+ of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sama5d3_pmc);
+
+ return;
+
+err_free:
+ kfree(sama5d3_pmc);
+}
+/*
+ * The TCB is used as the clocksource so its clock is needed early. This means
+ * this can't be a platform driver.
+ */
+CLK_OF_DECLARE(sama5d3_pmc, "atmel,sama5d3-pmc", sama5d3_pmc_setup);
diff --git a/drivers/clk/at91/sama5d4.c b/drivers/clk/at91/sama5d4.c
index 77ccd77404..8fbd810883 100644
--- a/drivers/clk/at91/sama5d4.c
+++ b/drivers/clk/at91/sama5d4.c
@@ -1,18 +1,15 @@
-// SPDX-License-Identifier: GPL-2.0
-
-#include <driver.h>
-#include <regmap.h>
-#include <stdio.h>
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/clk-provider.h>
#include <mfd/syscon.h>
-
-#include <linux/clk.h>
#include <linux/slab.h>
-#include <linux/types.h>
+#include <stdio.h>
#include <dt-bindings/clock/at91.h>
#include "pmc.h"
+static DEFINE_SPINLOCK(mck_lock);
+
static const struct clk_master_characteristics mck_characteristics = {
.output = { .min = 125000000, .max = 200000000 },
.divisors = { 1, 2, 4, 3 },
@@ -43,16 +40,21 @@ static const struct clk_pcr_layout sama5d4_pcr_layout = {
static const struct {
char *n;
char *p;
+ unsigned long flags;
u8 id;
} sama5d4_systemck[] = {
- { .n = "ddrck", .p = "masterck", .id = 2 },
- { .n = "lcdck", .p = "masterck", .id = 3 },
- { .n = "smdck", .p = "smdclk", .id = 4 },
- { .n = "uhpck", .p = "usbck", .id = 6 },
- { .n = "udpck", .p = "usbck", .id = 7 },
- { .n = "pck0", .p = "prog0", .id = 8 },
- { .n = "pck1", .p = "prog1", .id = 9 },
- { .n = "pck2", .p = "prog2", .id = 10 },
+ /*
+ * ddrck feeds DDR controller and is enabled by bootloader thus we need
+ * to keep it enabled in case there is no Linux consumer for it.
+ */
+ { .n = "ddrck", .p = "masterck_div", .id = 2, .flags = CLK_IS_CRITICAL },
+ { .n = "lcdck", .p = "masterck_div", .id = 3 },
+ { .n = "smdck", .p = "smdclk", .id = 4 },
+ { .n = "uhpck", .p = "usbck", .id = 6 },
+ { .n = "udpck", .p = "usbck", .id = 7 },
+ { .n = "pck0", .p = "prog0", .id = 8 },
+ { .n = "pck1", .p = "prog1", .id = 9 },
+ { .n = "pck2", .p = "prog2", .id = 10 },
};
static const struct {
@@ -107,12 +109,17 @@ static const struct {
static const struct {
char *n;
+ unsigned long flags;
u8 id;
} sama5d4_periphck[] = {
{ .n = "dma0_clk", .id = 8 },
{ .n = "cpkcc_clk", .id = 10 },
{ .n = "aesb_clk", .id = 13 },
- { .n = "mpddr_clk", .id = 16 },
+ /*
+ * mpddr_clk feeds DDR controller and is enabled by bootloader thus we
+ * need to keep it enabled in case there is no Linux consumer for it.
+ */
+ { .n = "mpddr_clk", .id = 16, .flags = CLK_IS_CRITICAL },
{ .n = "matrix0_clk", .id = 18 },
{ .n = "vdec_clk", .id = 19 },
{ .n = "dma1_clk", .id = 50 },
@@ -127,7 +134,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
struct pmc_data *sama5d4_pmc;
const char *parent_names[5];
struct regmap *regmap;
- struct clk *hw;
+ struct clk_hw *hw;
int i;
bool bypass;
@@ -146,9 +153,9 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
if (IS_ERR(regmap))
return;
- sama5d4_pmc = pmc_data_allocate(PMC_MCK2 + 1,
+ sama5d4_pmc = pmc_data_allocate(PMC_PLLACK + 1,
nck(sama5d4_systemck),
- nck(sama5d4_periph32ck), 0);
+ nck(sama5d4_periph32ck), 0, 3);
if (!sama5d4_pmc)
return;
@@ -179,6 +186,8 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
if (IS_ERR(hw))
goto err_free;
+ sama5d4_pmc->chws[PMC_PLLACK] = hw;
+
hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
if (IS_ERR(hw))
goto err_free;
@@ -189,15 +198,24 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
- hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
- &at91sam9x5_master_layout,
- &mck_characteristics);
+ hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4,
+ parent_names,
+ &at91sam9x5_master_layout,
+ &mck_characteristics, &mck_lock);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ hw = at91_clk_register_master_div(regmap, "masterck_div",
+ "masterck_pres",
+ &at91sam9x5_master_layout,
+ &mck_characteristics, &mck_lock,
+ CLK_SET_RATE_GATE);
if (IS_ERR(hw))
goto err_free;
sama5d4_pmc->chws[PMC_MCK] = hw;
- hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck");
+ hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck_div");
if (IS_ERR(hw))
goto err_free;
@@ -219,23 +237,27 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
- parent_names[4] = "masterck";
+ parent_names[4] = "masterck_div";
for (i = 0; i < 3; i++) {
- char *name;
+ char name[6];
- name = xasprintf("prog%d", i);
+ snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
parent_names, 5, i,
- &at91sam9x5_programmable_layout);
+ &at91sam9x5_programmable_layout,
+ NULL);
if (IS_ERR(hw))
goto err_free;
+
+ sama5d4_pmc->pchws[i] = hw;
}
for (i = 0; i < ARRAY_SIZE(sama5d4_systemck); i++) {
hw = at91_clk_register_system(regmap, sama5d4_systemck[i].n,
sama5d4_systemck[i].p,
- sama5d4_systemck[i].id);
+ sama5d4_systemck[i].id,
+ sama5d4_systemck[i].flags);
if (IS_ERR(hw))
goto err_free;
@@ -243,12 +265,13 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
}
for (i = 0; i < ARRAY_SIZE(sama5d4_periphck); i++) {
- hw = at91_clk_register_sam9x5_peripheral(regmap,
+ hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&sama5d4_pcr_layout,
sama5d4_periphck[i].n,
- "masterck",
+ "masterck_div",
sama5d4_periphck[i].id,
- &range);
+ &range, INT_MIN,
+ sama5d4_periphck[i].flags);
if (IS_ERR(hw))
goto err_free;
@@ -256,23 +279,24 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
}
for (i = 0; i < ARRAY_SIZE(sama5d4_periph32ck); i++) {
- hw = at91_clk_register_sam9x5_peripheral(regmap,
+ hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
&sama5d4_pcr_layout,
sama5d4_periph32ck[i].n,
"h32mxck",
sama5d4_periph32ck[i].id,
- &range);
+ &range, INT_MIN, 0);
if (IS_ERR(hw))
goto err_free;
sama5d4_pmc->phws[sama5d4_periph32ck[i].id] = hw;
}
- of_clk_add_provider(np, of_clk_hw_pmc_get, sama5d4_pmc);
+ of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sama5d4_pmc);
return;
err_free:
- pmc_data_free(sama5d4_pmc);
+ kfree(sama5d4_pmc);
}
-CLK_OF_DECLARE_DRIVER(sama5d4_pmc, "atmel,sama5d4-pmc", sama5d4_pmc_setup);
+
+CLK_OF_DECLARE(sama5d4_pmc, "atmel,sama5d4-pmc", sama5d4_pmc_setup);
diff --git a/drivers/clk/at91/sama7g5.c b/drivers/clk/at91/sama7g5.c
new file mode 100644
index 0000000000..7d33367176
--- /dev/null
+++ b/drivers/clk/at91/sama7g5.c
@@ -0,0 +1,1133 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SAMA7G5 PMC code.
+ *
+ * Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Claudiu Beznea <claudiu.beznea@microchip.com>
+ *
+ */
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <mfd/syscon.h>
+#include <linux/slab.h>
+#include <stdio.h>
+
+#include <dt-bindings/clock/at91.h>
+
+#include "pmc.h"
+
+#define SAMA7G5_INIT_TABLE(_table, _count) \
+ do { \
+ u8 _i; \
+ for (_i = 0; _i < (_count); _i++) \
+ (_table)[_i] = _i; \
+ } while (0)
+
+#define SAMA7G5_FILL_TABLE(_to, _from, _count) \
+ do { \
+ u8 _i; \
+ for (_i = 0; _i < (_count); _i++) { \
+ (_to)[_i] = (_from)[_i]; \
+ } \
+ } while (0)
+
+static DEFINE_SPINLOCK(pmc_pll_lock);
+static DEFINE_SPINLOCK(pmc_mck0_lock);
+static DEFINE_SPINLOCK(pmc_mckX_lock);
+
+/*
+ * PLL clocks identifiers
+ * @PLL_ID_CPU: CPU PLL identifier
+ * @PLL_ID_SYS: System PLL identifier
+ * @PLL_ID_DDR: DDR PLL identifier
+ * @PLL_ID_IMG: Image subsystem PLL identifier
+ * @PLL_ID_BAUD: Baud PLL identifier
+ * @PLL_ID_AUDIO: Audio PLL identifier
+ * @PLL_ID_ETH: Ethernet PLL identifier
+ */
+enum pll_ids {
+ PLL_ID_CPU,
+ PLL_ID_SYS,
+ PLL_ID_DDR,
+ PLL_ID_IMG,
+ PLL_ID_BAUD,
+ PLL_ID_AUDIO,
+ PLL_ID_ETH,
+ PLL_ID_MAX,
+};
+
+/*
+ * PLL type identifiers
+ * @PLL_TYPE_FRAC: fractional PLL identifier
+ * @PLL_TYPE_DIV: divider PLL identifier
+ */
+enum pll_type {
+ PLL_TYPE_FRAC,
+ PLL_TYPE_DIV,
+};
+
+/* Layout for fractional PLLs. */
+static const struct clk_pll_layout pll_layout_frac = {
+ .mul_mask = GENMASK(31, 24),
+ .frac_mask = GENMASK(21, 0),
+ .mul_shift = 24,
+ .frac_shift = 0,
+};
+
+/* Layout for DIVPMC dividers. */
+static const struct clk_pll_layout pll_layout_divpmc = {
+ .div_mask = GENMASK(7, 0),
+ .endiv_mask = BIT(29),
+ .div_shift = 0,
+ .endiv_shift = 29,
+};
+
+/* Layout for DIVIO dividers. */
+static const struct clk_pll_layout pll_layout_divio = {
+ .div_mask = GENMASK(19, 12),
+ .endiv_mask = BIT(30),
+ .div_shift = 12,
+ .endiv_shift = 30,
+};
+
+/*
+ * CPU PLL output range.
+ * Notice: The upper limit has been setup to 1000000002 due to hardware
+ * block which cannot output exactly 1GHz.
+ */
+static const struct clk_range cpu_pll_outputs[] = {
+ { .min = 2343750, .max = 1000000002 },
+};
+
+/* PLL output range. */
+static const struct clk_range pll_outputs[] = {
+ { .min = 2343750, .max = 1200000000 },
+};
+
+/* CPU PLL characteristics. */
+static const struct clk_pll_characteristics cpu_pll_characteristics = {
+ .input = { .min = 12000000, .max = 50000000 },
+ .num_output = ARRAY_SIZE(cpu_pll_outputs),
+ .output = cpu_pll_outputs,
+};
+
+/* PLL characteristics. */
+static const struct clk_pll_characteristics pll_characteristics = {
+ .input = { .min = 12000000, .max = 50000000 },
+ .num_output = ARRAY_SIZE(pll_outputs),
+ .output = pll_outputs,
+};
+
+/*
+ * PLL clocks description
+ * @n: clock name
+ * @p: clock parent
+ * @l: clock layout
+ * @c: clock characteristics
+ * @t: clock type
+ * @f: clock flags
+ * @eid: export index in sama7g5->chws[] array
+ */
+static const struct {
+ const char *n;
+ const char *p;
+ const struct clk_pll_layout *l;
+ const struct clk_pll_characteristics *c;
+ unsigned long f;
+ u8 t;
+ u8 eid;
+} sama7g5_plls[][PLL_ID_MAX] = {
+ [PLL_ID_CPU] = {
+ { .n = "cpupll_fracck",
+ .p = "mainck",
+ .l = &pll_layout_frac,
+ .c = &cpu_pll_characteristics,
+ .t = PLL_TYPE_FRAC,
+ /*
+ * This feeds cpupll_divpmcck which feeds CPU. It should
+ * not be disabled.
+ */
+ .f = CLK_IS_CRITICAL, },
+
+ { .n = "cpupll_divpmcck",
+ .p = "cpupll_fracck",
+ .l = &pll_layout_divpmc,
+ .c = &cpu_pll_characteristics,
+ .t = PLL_TYPE_DIV,
+ /* This feeds CPU. It should not be disabled. */
+ .f = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT,
+ .eid = PMC_CPUPLL, },
+ },
+
+ [PLL_ID_SYS] = {
+ { .n = "syspll_fracck",
+ .p = "mainck",
+ .l = &pll_layout_frac,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_FRAC,
+ /*
+ * This feeds syspll_divpmcck which may feed critical parts
+ * of the systems like timers. Therefore it should not be
+ * disabled.
+ */
+ .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, },
+
+ { .n = "syspll_divpmcck",
+ .p = "syspll_fracck",
+ .l = &pll_layout_divpmc,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_DIV,
+ /*
+ * This may feed critical parts of the systems like timers.
+ * Therefore it should not be disabled.
+ */
+ .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
+ .eid = PMC_SYSPLL, },
+ },
+
+ [PLL_ID_DDR] = {
+ { .n = "ddrpll_fracck",
+ .p = "mainck",
+ .l = &pll_layout_frac,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_FRAC,
+ /*
+ * This feeds ddrpll_divpmcck which feeds DDR. It should not
+ * be disabled.
+ */
+ .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, },
+
+ { .n = "ddrpll_divpmcck",
+ .p = "ddrpll_fracck",
+ .l = &pll_layout_divpmc,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_DIV,
+ /* This feeds DDR. It should not be disabled. */
+ .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, },
+ },
+
+ [PLL_ID_IMG] = {
+ { .n = "imgpll_fracck",
+ .p = "mainck",
+ .l = &pll_layout_frac,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_FRAC,
+ .f = CLK_SET_RATE_GATE, },
+
+ { .n = "imgpll_divpmcck",
+ .p = "imgpll_fracck",
+ .l = &pll_layout_divpmc,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_DIV,
+ .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
+ CLK_SET_RATE_PARENT, },
+ },
+
+ [PLL_ID_BAUD] = {
+ { .n = "baudpll_fracck",
+ .p = "mainck",
+ .l = &pll_layout_frac,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_FRAC,
+ .f = CLK_SET_RATE_GATE, },
+
+ { .n = "baudpll_divpmcck",
+ .p = "baudpll_fracck",
+ .l = &pll_layout_divpmc,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_DIV,
+ .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
+ CLK_SET_RATE_PARENT, },
+ },
+
+ [PLL_ID_AUDIO] = {
+ { .n = "audiopll_fracck",
+ .p = "main_xtal",
+ .l = &pll_layout_frac,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_FRAC,
+ .f = CLK_SET_RATE_GATE, },
+
+ { .n = "audiopll_divpmcck",
+ .p = "audiopll_fracck",
+ .l = &pll_layout_divpmc,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_DIV,
+ .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
+ CLK_SET_RATE_PARENT,
+ .eid = PMC_AUDIOPMCPLL, },
+
+ { .n = "audiopll_diviock",
+ .p = "audiopll_fracck",
+ .l = &pll_layout_divio,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_DIV,
+ .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
+ CLK_SET_RATE_PARENT,
+ .eid = PMC_AUDIOIOPLL, },
+ },
+
+ [PLL_ID_ETH] = {
+ { .n = "ethpll_fracck",
+ .p = "main_xtal",
+ .l = &pll_layout_frac,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_FRAC,
+ .f = CLK_SET_RATE_GATE, },
+
+ { .n = "ethpll_divpmcck",
+ .p = "ethpll_fracck",
+ .l = &pll_layout_divpmc,
+ .c = &pll_characteristics,
+ .t = PLL_TYPE_DIV,
+ .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
+ CLK_SET_RATE_PARENT, },
+ },
+};
+
+/*
+ * Master clock (MCK[1..4]) description
+ * @n: clock name
+ * @ep: extra parents names array
+ * @ep_chg_chg_id: index in parents array that specifies the changeable
+ * parent
+ * @ep_count: extra parents count
+ * @ep_mux_table: mux table for extra parents
+ * @id: clock id
+ * @eid: export index in sama7g5->chws[] array
+ * @c: true if clock is critical and cannot be disabled
+ */
+static const struct {
+ const char *n;
+ const char *ep[4];
+ int ep_chg_id;
+ u8 ep_count;
+ u8 ep_mux_table[4];
+ u8 id;
+ u8 eid;
+ u8 c;
+} sama7g5_mckx[] = {
+ { .n = "mck1",
+ .id = 1,
+ .ep = { "syspll_divpmcck", },
+ .ep_mux_table = { 5, },
+ .ep_count = 1,
+ .ep_chg_id = INT_MIN,
+ .eid = PMC_MCK1,
+ .c = 1, },
+
+ { .n = "mck2",
+ .id = 2,
+ .ep = { "ddrpll_divpmcck", },
+ .ep_mux_table = { 6, },
+ .ep_count = 1,
+ .ep_chg_id = INT_MIN,
+ .c = 1, },
+
+ { .n = "mck3",
+ .id = 3,
+ .ep = { "syspll_divpmcck", "ddrpll_divpmcck", "imgpll_divpmcck", },
+ .ep_mux_table = { 5, 6, 7, },
+ .ep_count = 3,
+ .ep_chg_id = 5, },
+
+ { .n = "mck4",
+ .id = 4,
+ .ep = { "syspll_divpmcck", },
+ .ep_mux_table = { 5, },
+ .ep_count = 1,
+ .ep_chg_id = INT_MIN,
+ .c = 1, },
+};
+
+/*
+ * System clock description
+ * @n: clock name
+ * @p: clock parent name
+ * @id: clock id
+ */
+static const struct {
+ const char *n;
+ const char *p;
+ u8 id;
+} sama7g5_systemck[] = {
+ { .n = "pck0", .p = "prog0", .id = 8, },
+ { .n = "pck1", .p = "prog1", .id = 9, },
+ { .n = "pck2", .p = "prog2", .id = 10, },
+ { .n = "pck3", .p = "prog3", .id = 11, },
+ { .n = "pck4", .p = "prog4", .id = 12, },
+ { .n = "pck5", .p = "prog5", .id = 13, },
+ { .n = "pck6", .p = "prog6", .id = 14, },
+ { .n = "pck7", .p = "prog7", .id = 15, },
+};
+
+/* Mux table for programmable clocks. */
+static u32 sama7g5_prog_mux_table[] = { 0, 1, 2, 5, 6, 7, 8, 9, 10, };
+
+/*
+ * Peripheral clock description
+ * @n: clock name
+ * @p: clock parent name
+ * @r: clock range values
+ * @id: clock id
+ * @chgp: index in parent array of the changeable parent
+ */
+static const struct {
+ const char *n;
+ const char *p;
+ struct clk_range r;
+ u8 chgp;
+ u8 id;
+} sama7g5_periphck[] = {
+ { .n = "pioA_clk", .p = "mck0", .id = 11, },
+ { .n = "securam_clk", .p = "mck0", .id = 18, },
+ { .n = "sfr_clk", .p = "mck1", .id = 19, },
+ { .n = "hsmc_clk", .p = "mck1", .id = 21, },
+ { .n = "xdmac0_clk", .p = "mck1", .id = 22, },
+ { .n = "xdmac1_clk", .p = "mck1", .id = 23, },
+ { .n = "xdmac2_clk", .p = "mck1", .id = 24, },
+ { .n = "acc_clk", .p = "mck1", .id = 25, },
+ { .n = "aes_clk", .p = "mck1", .id = 27, },
+ { .n = "tzaesbasc_clk", .p = "mck1", .id = 28, },
+ { .n = "asrc_clk", .p = "mck1", .id = 30, .r = { .max = 200000000, }, },
+ { .n = "cpkcc_clk", .p = "mck0", .id = 32, },
+ { .n = "csi_clk", .p = "mck3", .id = 33, .r = { .max = 266000000, }, .chgp = 1, },
+ { .n = "csi2dc_clk", .p = "mck3", .id = 34, .r = { .max = 266000000, }, .chgp = 1, },
+ { .n = "eic_clk", .p = "mck1", .id = 37, },
+ { .n = "flex0_clk", .p = "mck1", .id = 38, },
+ { .n = "flex1_clk", .p = "mck1", .id = 39, },
+ { .n = "flex2_clk", .p = "mck1", .id = 40, },
+ { .n = "flex3_clk", .p = "mck1", .id = 41, },
+ { .n = "flex4_clk", .p = "mck1", .id = 42, },
+ { .n = "flex5_clk", .p = "mck1", .id = 43, },
+ { .n = "flex6_clk", .p = "mck1", .id = 44, },
+ { .n = "flex7_clk", .p = "mck1", .id = 45, },
+ { .n = "flex8_clk", .p = "mck1", .id = 46, },
+ { .n = "flex9_clk", .p = "mck1", .id = 47, },
+ { .n = "flex10_clk", .p = "mck1", .id = 48, },
+ { .n = "flex11_clk", .p = "mck1", .id = 49, },
+ { .n = "gmac0_clk", .p = "mck1", .id = 51, },
+ { .n = "gmac1_clk", .p = "mck1", .id = 52, },
+ { .n = "icm_clk", .p = "mck1", .id = 55, },
+ { .n = "isc_clk", .p = "mck3", .id = 56, .r = { .max = 266000000, }, .chgp = 1, },
+ { .n = "i2smcc0_clk", .p = "mck1", .id = 57, .r = { .max = 200000000, }, },
+ { .n = "i2smcc1_clk", .p = "mck1", .id = 58, .r = { .max = 200000000, }, },
+ { .n = "matrix_clk", .p = "mck1", .id = 60, },
+ { .n = "mcan0_clk", .p = "mck1", .id = 61, .r = { .max = 200000000, }, },
+ { .n = "mcan1_clk", .p = "mck1", .id = 62, .r = { .max = 200000000, }, },
+ { .n = "mcan2_clk", .p = "mck1", .id = 63, .r = { .max = 200000000, }, },
+ { .n = "mcan3_clk", .p = "mck1", .id = 64, .r = { .max = 200000000, }, },
+ { .n = "mcan4_clk", .p = "mck1", .id = 65, .r = { .max = 200000000, }, },
+ { .n = "mcan5_clk", .p = "mck1", .id = 66, .r = { .max = 200000000, }, },
+ { .n = "pdmc0_clk", .p = "mck1", .id = 68, .r = { .max = 200000000, }, },
+ { .n = "pdmc1_clk", .p = "mck1", .id = 69, .r = { .max = 200000000, }, },
+ { .n = "pit64b0_clk", .p = "mck1", .id = 70, },
+ { .n = "pit64b1_clk", .p = "mck1", .id = 71, },
+ { .n = "pit64b2_clk", .p = "mck1", .id = 72, },
+ { .n = "pit64b3_clk", .p = "mck1", .id = 73, },
+ { .n = "pit64b4_clk", .p = "mck1", .id = 74, },
+ { .n = "pit64b5_clk", .p = "mck1", .id = 75, },
+ { .n = "pwm_clk", .p = "mck1", .id = 77, },
+ { .n = "qspi0_clk", .p = "mck1", .id = 78, },
+ { .n = "qspi1_clk", .p = "mck1", .id = 79, },
+ { .n = "sdmmc0_clk", .p = "mck1", .id = 80, },
+ { .n = "sdmmc1_clk", .p = "mck1", .id = 81, },
+ { .n = "sdmmc2_clk", .p = "mck1", .id = 82, },
+ { .n = "sha_clk", .p = "mck1", .id = 83, },
+ { .n = "spdifrx_clk", .p = "mck1", .id = 84, .r = { .max = 200000000, }, },
+ { .n = "spdiftx_clk", .p = "mck1", .id = 85, .r = { .max = 200000000, }, },
+ { .n = "ssc0_clk", .p = "mck1", .id = 86, .r = { .max = 200000000, }, },
+ { .n = "ssc1_clk", .p = "mck1", .id = 87, .r = { .max = 200000000, }, },
+ { .n = "tcb0_ch0_clk", .p = "mck1", .id = 88, .r = { .max = 200000000, }, },
+ { .n = "tcb0_ch1_clk", .p = "mck1", .id = 89, .r = { .max = 200000000, }, },
+ { .n = "tcb0_ch2_clk", .p = "mck1", .id = 90, .r = { .max = 200000000, }, },
+ { .n = "tcb1_ch0_clk", .p = "mck1", .id = 91, .r = { .max = 200000000, }, },
+ { .n = "tcb1_ch1_clk", .p = "mck1", .id = 92, .r = { .max = 200000000, }, },
+ { .n = "tcb1_ch2_clk", .p = "mck1", .id = 93, .r = { .max = 200000000, }, },
+ { .n = "tcpca_clk", .p = "mck1", .id = 94, },
+ { .n = "tcpcb_clk", .p = "mck1", .id = 95, },
+ { .n = "tdes_clk", .p = "mck1", .id = 96, },
+ { .n = "trng_clk", .p = "mck1", .id = 97, },
+ { .n = "udphsa_clk", .p = "mck1", .id = 104, },
+ { .n = "udphsb_clk", .p = "mck1", .id = 105, },
+ { .n = "uhphs_clk", .p = "mck1", .id = 106, },
+};
+
+/*
+ * Generic clock description
+ * @n: clock name
+ * @pp: PLL parents
+ * @pp_mux_table: PLL parents mux table
+ * @r: clock output range
+ * @pp_chg_id: id in parent array of changeable PLL parent
+ * @pp_count: PLL parents count
+ * @id: clock id
+ */
+static const struct {
+ const char *n;
+ const char *pp[8];
+ const char pp_mux_table[8];
+ struct clk_range r;
+ int pp_chg_id;
+ u8 pp_count;
+ u8 id;
+} sama7g5_gck[] = {
+ { .n = "adc_gclk",
+ .id = 26,
+ .r = { .max = 100000000, },
+ .pp = { "syspll_divpmcck", "imgpll_divpmcck", "audiopll_divpmcck", },
+ .pp_mux_table = { 5, 7, 9, },
+ .pp_count = 3,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "asrc_gclk",
+ .id = 30,
+ .r = { .max = 200000000 },
+ .pp = { "audiopll_divpmcck", },
+ .pp_mux_table = { 9, },
+ .pp_count = 1,
+ .pp_chg_id = 3, },
+
+ { .n = "csi_gclk",
+ .id = 33,
+ .r = { .max = 27000000 },
+ .pp = { "ddrpll_divpmcck", "imgpll_divpmcck", },
+ .pp_mux_table = { 6, 7, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "flex0_gclk",
+ .id = 38,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "flex1_gclk",
+ .id = 39,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "flex2_gclk",
+ .id = 40,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "flex3_gclk",
+ .id = 41,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "flex4_gclk",
+ .id = 42,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "flex5_gclk",
+ .id = 43,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "flex6_gclk",
+ .id = 44,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "flex7_gclk",
+ .id = 45,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "flex8_gclk",
+ .id = 46,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "flex9_gclk",
+ .id = 47,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "flex10_gclk",
+ .id = 48,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "flex11_gclk",
+ .id = 49,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "gmac0_gclk",
+ .id = 51,
+ .r = { .max = 125000000 },
+ .pp = { "ethpll_divpmcck", },
+ .pp_mux_table = { 10, },
+ .pp_count = 1,
+ .pp_chg_id = 3, },
+
+ { .n = "gmac1_gclk",
+ .id = 52,
+ .r = { .max = 50000000 },
+ .pp = { "ethpll_divpmcck", },
+ .pp_mux_table = { 10, },
+ .pp_count = 1,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "gmac0_tsu_gclk",
+ .id = 53,
+ .r = { .max = 300000000 },
+ .pp = { "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp_mux_table = { 9, 10, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "gmac1_tsu_gclk",
+ .id = 54,
+ .r = { .max = 300000000 },
+ .pp = { "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp_mux_table = { 9, 10, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "i2smcc0_gclk",
+ .id = 57,
+ .r = { .max = 100000000 },
+ .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
+ .pp_mux_table = { 5, 9, },
+ .pp_count = 2,
+ .pp_chg_id = 4, },
+
+ { .n = "i2smcc1_gclk",
+ .id = 58,
+ .r = { .max = 100000000 },
+ .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
+ .pp_mux_table = { 5, 9, },
+ .pp_count = 2,
+ .pp_chg_id = 4, },
+
+ { .n = "mcan0_gclk",
+ .id = 61,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "mcan1_gclk",
+ .id = 62,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "mcan2_gclk",
+ .id = 63,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "mcan3_gclk",
+ .id = 64,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "mcan4_gclk",
+ .id = 65,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "mcan5_gclk",
+ .id = 66,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "pdmc0_gclk",
+ .id = 68,
+ .r = { .max = 50000000 },
+ .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
+ .pp_mux_table = { 5, 9, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "pdmc1_gclk",
+ .id = 69,
+ .r = { .max = 50000000, },
+ .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
+ .pp_mux_table = { 5, 9, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "pit64b0_gclk",
+ .id = 70,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
+ "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp_mux_table = { 5, 7, 8, 9, 10, },
+ .pp_count = 5,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "pit64b1_gclk",
+ .id = 71,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
+ "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp_mux_table = { 5, 7, 8, 9, 10, },
+ .pp_count = 5,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "pit64b2_gclk",
+ .id = 72,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
+ "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp_mux_table = { 5, 7, 8, 9, 10, },
+ .pp_count = 5,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "pit64b3_gclk",
+ .id = 73,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
+ "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp_mux_table = { 5, 7, 8, 9, 10, },
+ .pp_count = 5,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "pit64b4_gclk",
+ .id = 74,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
+ "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp_mux_table = { 5, 7, 8, 9, 10, },
+ .pp_count = 5,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "pit64b5_gclk",
+ .id = 75,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
+ "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp_mux_table = { 5, 7, 8, 9, 10, },
+ .pp_count = 5,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "qspi0_gclk",
+ .id = 78,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "qspi1_gclk",
+ .id = 79,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "sdmmc0_gclk",
+ .id = 80,
+ .r = { .max = 208000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = 4, },
+
+ { .n = "sdmmc1_gclk",
+ .id = 81,
+ .r = { .max = 208000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = 4, },
+
+ { .n = "sdmmc2_gclk",
+ .id = 82,
+ .r = { .max = 208000000 },
+ .pp = { "syspll_divpmcck", "baudpll_divpmcck", },
+ .pp_mux_table = { 5, 8, },
+ .pp_count = 2,
+ .pp_chg_id = 4, },
+
+ { .n = "spdifrx_gclk",
+ .id = 84,
+ .r = { .max = 150000000 },
+ .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
+ .pp_mux_table = { 5, 9, },
+ .pp_count = 2,
+ .pp_chg_id = 4, },
+
+ { .n = "spdiftx_gclk",
+ .id = 85,
+ .r = { .max = 25000000 },
+ .pp = { "syspll_divpmcck", "audiopll_divpmcck", },
+ .pp_mux_table = { 5, 9, },
+ .pp_count = 2,
+ .pp_chg_id = 4, },
+
+ { .n = "tcb0_ch0_gclk",
+ .id = 88,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
+ "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp_mux_table = { 5, 7, 8, 9, 10, },
+ .pp_count = 5,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "tcb1_ch0_gclk",
+ .id = 91,
+ .r = { .max = 200000000 },
+ .pp = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck",
+ "audiopll_divpmcck", "ethpll_divpmcck", },
+ .pp_mux_table = { 5, 7, 8, 9, 10, },
+ .pp_count = 5,
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "tcpca_gclk",
+ .id = 94,
+ .r = { .max = 32768, },
+ .pp_chg_id = INT_MIN, },
+
+ { .n = "tcpcb_gclk",
+ .id = 95,
+ .r = { .max = 32768, },
+ .pp_chg_id = INT_MIN, },
+};
+
+/* MCK0 characteristics. */
+static const struct clk_master_characteristics mck0_characteristics = {
+ .output = { .min = 32768, .max = 200000000 },
+ .divisors = { 1, 2, 4, 3, 5 },
+ .have_div3_pres = 1,
+};
+
+/* MCK0 layout. */
+static const struct clk_master_layout mck0_layout = {
+ .mask = 0x773,
+ .pres_shift = 4,
+ .offset = 0x28,
+};
+
+/* Programmable clock layout. */
+static const struct clk_programmable_layout programmable_layout = {
+ .pres_mask = 0xff,
+ .pres_shift = 8,
+ .css_mask = 0x1f,
+ .have_slck_mck = 0,
+ .is_pres_direct = 1,
+};
+
+/* Peripheral clock layout. */
+static const struct clk_pcr_layout sama7g5_pcr_layout = {
+ .offset = 0x88,
+ .cmd = BIT(31),
+ .gckcss_mask = GENMASK(12, 8),
+ .pid_mask = GENMASK(6, 0),
+};
+
+static void __init sama7g5_pmc_setup(struct device_node *np)
+{
+ const char *td_slck_name, *md_slck_name, *mainxtal_name;
+ struct pmc_data *sama7g5_pmc;
+ const char *parent_names[10];
+ void **alloc_mem = NULL;
+ int alloc_mem_size = 0;
+ struct regmap *regmap;
+ struct clk_hw *hw;
+ bool bypass;
+ int i, j;
+
+ i = of_property_match_string(np, "clock-names", "td_slck");
+ if (i < 0)
+ return;
+
+ td_slck_name = of_clk_get_parent_name(np, i);
+
+ i = of_property_match_string(np, "clock-names", "md_slck");
+ if (i < 0)
+ return;
+
+ md_slck_name = of_clk_get_parent_name(np, i);
+
+ i = of_property_match_string(np, "clock-names", "main_xtal");
+ if (i < 0)
+ return;
+
+ mainxtal_name = of_clk_get_parent_name(np, i);
+
+ regmap = device_node_to_regmap(np);
+ if (IS_ERR(regmap))
+ return;
+
+ sama7g5_pmc = pmc_data_allocate(PMC_MCK1 + 1,
+ nck(sama7g5_systemck),
+ nck(sama7g5_periphck),
+ nck(sama7g5_gck), 8);
+ if (!sama7g5_pmc)
+ return;
+
+ alloc_mem = kmalloc(sizeof(void *) *
+ (ARRAY_SIZE(sama7g5_mckx) + ARRAY_SIZE(sama7g5_gck)),
+ GFP_KERNEL);
+ if (!alloc_mem)
+ goto err_free;
+
+ hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
+ 50000000);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ bypass = of_property_read_bool(np, "atmel,osc-bypass");
+
+ hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
+ bypass);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ parent_names[0] = "main_rc_osc";
+ parent_names[1] = "main_osc";
+ hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ sama7g5_pmc->chws[PMC_MAIN] = hw;
+
+ for (i = 0; i < PLL_ID_MAX; i++) {
+ for (j = 0; j < 3; j++) {
+ struct clk_hw *parent_hw;
+
+ if (!sama7g5_plls[i][j].n)
+ continue;
+
+ switch (sama7g5_plls[i][j].t) {
+ case PLL_TYPE_FRAC:
+ if (!strcmp(sama7g5_plls[i][j].p, "mainck"))
+ parent_hw = sama7g5_pmc->chws[PMC_MAIN];
+ else
+ parent_hw = __clk_get_hw(of_clk_get_by_name(np,
+ sama7g5_plls[i][j].p));
+
+ hw = sam9x60_clk_register_frac_pll(regmap,
+ &pmc_pll_lock, sama7g5_plls[i][j].n,
+ sama7g5_plls[i][j].p, parent_hw, i,
+ sama7g5_plls[i][j].c,
+ sama7g5_plls[i][j].l,
+ sama7g5_plls[i][j].f);
+ break;
+
+ case PLL_TYPE_DIV:
+ hw = sam9x60_clk_register_div_pll(regmap,
+ &pmc_pll_lock, sama7g5_plls[i][j].n,
+ sama7g5_plls[i][j].p, i,
+ sama7g5_plls[i][j].c,
+ sama7g5_plls[i][j].l,
+ sama7g5_plls[i][j].f);
+ break;
+
+ default:
+ continue;
+ }
+
+ if (IS_ERR(hw))
+ goto err_free;
+
+ if (sama7g5_plls[i][j].eid)
+ sama7g5_pmc->chws[sama7g5_plls[i][j].eid] = hw;
+ }
+ }
+
+ parent_names[0] = "cpupll_divpmcck";
+ hw = at91_clk_register_master_div(regmap, "mck0", "cpupll_divpmcck",
+ &mck0_layout, &mck0_characteristics,
+ &pmc_mck0_lock, CLK_GET_RATE_NOCACHE);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ sama7g5_pmc->chws[PMC_MCK] = hw;
+
+ parent_names[0] = md_slck_name;
+ parent_names[1] = td_slck_name;
+ parent_names[2] = "mainck";
+ for (i = 0; i < ARRAY_SIZE(sama7g5_mckx); i++) {
+ u8 num_parents = 3 + sama7g5_mckx[i].ep_count;
+ u32 *mux_table;
+
+ mux_table = kmalloc_array(num_parents, sizeof(*mux_table),
+ GFP_KERNEL);
+ if (!mux_table)
+ goto err_free;
+
+ SAMA7G5_INIT_TABLE(mux_table, 3);
+ SAMA7G5_FILL_TABLE(&mux_table[3], sama7g5_mckx[i].ep_mux_table,
+ sama7g5_mckx[i].ep_count);
+ SAMA7G5_FILL_TABLE(&parent_names[3], sama7g5_mckx[i].ep,
+ sama7g5_mckx[i].ep_count);
+
+ hw = at91_clk_sama7g5_register_master(regmap, sama7g5_mckx[i].n,
+ num_parents, parent_names, mux_table,
+ &pmc_mckX_lock, sama7g5_mckx[i].id,
+ sama7g5_mckx[i].c,
+ sama7g5_mckx[i].ep_chg_id);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ alloc_mem[alloc_mem_size++] = mux_table;
+
+ if (sama7g5_mckx[i].eid)
+ sama7g5_pmc->chws[sama7g5_mckx[i].eid] = hw;
+ }
+
+ hw = at91_clk_sama7g5_register_utmi(regmap, "utmick", "main_xtal");
+ if (IS_ERR(hw))
+ goto err_free;
+
+ sama7g5_pmc->chws[PMC_UTMI] = hw;
+
+ parent_names[0] = md_slck_name;
+ parent_names[1] = td_slck_name;
+ parent_names[2] = "mainck";
+ parent_names[3] = "syspll_divpmcck";
+ parent_names[4] = "ddrpll_divpmcck";
+ parent_names[5] = "imgpll_divpmcck";
+ parent_names[6] = "baudpll_divpmcck";
+ parent_names[7] = "audiopll_divpmcck";
+ parent_names[8] = "ethpll_divpmcck";
+ for (i = 0; i < 8; i++) {
+ char name[6];
+
+ snprintf(name, sizeof(name), "prog%d", i);
+
+ hw = at91_clk_register_programmable(regmap, name, parent_names,
+ 9, i,
+ &programmable_layout,
+ sama7g5_prog_mux_table);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ sama7g5_pmc->pchws[i] = hw;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(sama7g5_systemck); i++) {
+ hw = at91_clk_register_system(regmap, sama7g5_systemck[i].n,
+ sama7g5_systemck[i].p,
+ sama7g5_systemck[i].id, 0);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ sama7g5_pmc->shws[sama7g5_systemck[i].id] = hw;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(sama7g5_periphck); i++) {
+ hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
+ &sama7g5_pcr_layout,
+ sama7g5_periphck[i].n,
+ sama7g5_periphck[i].p,
+ sama7g5_periphck[i].id,
+ &sama7g5_periphck[i].r,
+ sama7g5_periphck[i].chgp ? 0 :
+ INT_MIN, 0);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ sama7g5_pmc->phws[sama7g5_periphck[i].id] = hw;
+ }
+
+ parent_names[0] = md_slck_name;
+ parent_names[1] = td_slck_name;
+ parent_names[2] = "mainck";
+ for (i = 0; i < ARRAY_SIZE(sama7g5_gck); i++) {
+ u8 num_parents = 3 + sama7g5_gck[i].pp_count;
+ u32 *mux_table;
+
+ mux_table = kmalloc_array(num_parents, sizeof(*mux_table),
+ GFP_KERNEL);
+ if (!mux_table)
+ goto err_free;
+
+ SAMA7G5_INIT_TABLE(mux_table, 3);
+ SAMA7G5_FILL_TABLE(&mux_table[3], sama7g5_gck[i].pp_mux_table,
+ sama7g5_gck[i].pp_count);
+ SAMA7G5_FILL_TABLE(&parent_names[3], sama7g5_gck[i].pp,
+ sama7g5_gck[i].pp_count);
+
+ hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
+ &sama7g5_pcr_layout,
+ sama7g5_gck[i].n,
+ parent_names, mux_table,
+ num_parents,
+ sama7g5_gck[i].id,
+ &sama7g5_gck[i].r,
+ sama7g5_gck[i].pp_chg_id);
+ if (IS_ERR(hw))
+ goto err_free;
+
+ sama7g5_pmc->ghws[sama7g5_gck[i].id] = hw;
+ alloc_mem[alloc_mem_size++] = mux_table;
+ }
+
+ of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sama7g5_pmc);
+
+ return;
+
+err_free:
+ if (alloc_mem) {
+ for (i = 0; i < alloc_mem_size; i++)
+ kfree(alloc_mem[i]);
+ kfree(alloc_mem);
+ }
+
+ kfree(sama7g5_pmc);
+}
+
+/* Some clks are used for a clocksource */
+CLK_OF_DECLARE(sama7g5_pmc, "microchip,sama7g5-pmc", sama7g5_pmc_setup);
diff --git a/drivers/clk/at91/sckc.c b/drivers/clk/at91/sckc.c
index 1a33a64421..1e03537cf1 100644
--- a/drivers/clk/at91/sckc.c
+++ b/drivers/clk/at91/sckc.c
@@ -5,18 +5,12 @@
* Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
*/
-#include <common.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <clock.h>
#include <of.h>
#include <of_address.h>
-#include <io.h>
-#include <linux/list.h>
-#include <linux/clk.h>
-#include <linux/clk/at91_pmc.h>
-#include <mfd/syscon.h>
-#include <regmap.h>
-
-
+#include <linux/io.h>
#define SLOW_CLOCK_FREQ 32768
#define SLOWCK_SW_CYCLES 5
@@ -33,50 +27,47 @@ struct clk_slow_bits {
};
struct clk_slow_osc {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *sckcr;
const struct clk_slow_bits *bits;
unsigned long startup_usec;
- const char *parent_name;
};
-#define to_clk_slow_osc(clk) container_of(clk, struct clk_slow_osc, clk)
+#define to_clk_slow_osc(hw) container_of(hw, struct clk_slow_osc, hw)
struct clk_sama5d4_slow_osc {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *sckcr;
const struct clk_slow_bits *bits;
unsigned long startup_usec;
bool prepared;
- const char *parent_name;
};
-#define to_clk_sama5d4_slow_osc(clk) container_of(clk, struct clk_sama5d4_slow_osc, clk)
+#define to_clk_sama5d4_slow_osc(hw) container_of(hw, struct clk_sama5d4_slow_osc, hw)
struct clk_slow_rc_osc {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *sckcr;
const struct clk_slow_bits *bits;
unsigned long frequency;
+ unsigned long accuracy;
unsigned long startup_usec;
- const char *parent_name;
};
-#define to_clk_slow_rc_osc(clk) container_of(clk, struct clk_slow_rc_osc, clk)
+#define to_clk_slow_rc_osc(hw) container_of(hw, struct clk_slow_rc_osc, hw)
struct clk_sam9x5_slow {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *sckcr;
const struct clk_slow_bits *bits;
u8 parent;
- const char *parent_names[2];
};
-#define to_clk_sam9x5_slow(clk) container_of(clk, struct clk_sam9x5_slow, clk)
+#define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw)
-static int clk_slow_osc_enable(struct clk *clk)
+static int clk_slow_osc_prepare(struct clk_hw *hw)
{
- struct clk_slow_osc *osc = to_clk_slow_osc(clk);
+ struct clk_slow_osc *osc = to_clk_slow_osc(hw);
void __iomem *sckcr = osc->sckcr;
u32 tmp = readl(sckcr);
@@ -90,9 +81,9 @@ static int clk_slow_osc_enable(struct clk *clk)
return 0;
}
-static void clk_slow_osc_disable(struct clk *clk)
+static void clk_slow_osc_unprepare(struct clk_hw *hw)
{
- struct clk_slow_osc *osc = to_clk_slow_osc(clk);
+ struct clk_slow_osc *osc = to_clk_slow_osc(hw);
void __iomem *sckcr = osc->sckcr;
u32 tmp = readl(sckcr);
@@ -102,9 +93,9 @@ static void clk_slow_osc_disable(struct clk *clk)
writel(tmp & ~osc->bits->cr_osc32en, sckcr);
}
-static int clk_slow_osc_is_enabled(struct clk *clk)
+static int clk_slow_osc_is_prepared(struct clk_hw *hw)
{
- struct clk_slow_osc *osc = to_clk_slow_osc(clk);
+ struct clk_slow_osc *osc = to_clk_slow_osc(hw);
void __iomem *sckcr = osc->sckcr;
u32 tmp = readl(sckcr);
@@ -115,12 +106,12 @@ static int clk_slow_osc_is_enabled(struct clk *clk)
}
static const struct clk_ops slow_osc_ops = {
- .enable = clk_slow_osc_enable,
- .disable = clk_slow_osc_disable,
- .is_enabled = clk_slow_osc_is_enabled,
+ .enable = clk_slow_osc_prepare,
+ .disable = clk_slow_osc_unprepare,
+ .is_enabled = clk_slow_osc_is_prepared,
};
-static struct clk * __init
+static struct clk_hw * __init
at91_clk_register_slow_osc(void __iomem *sckcr,
const char *name,
const char *parent_name,
@@ -128,21 +119,25 @@ at91_clk_register_slow_osc(void __iomem *sckcr,
bool bypass,
const struct clk_slow_bits *bits)
{
- int ret;
struct clk_slow_osc *osc;
+ struct clk_hw *hw;
+ struct clk_init_data init;
+ int ret;
if (!sckcr || !name || !parent_name)
return ERR_PTR(-EINVAL);
- osc = xzalloc(sizeof(*osc));
+ osc = kzalloc(sizeof(*osc), GFP_KERNEL);
+ if (!osc)
+ return ERR_PTR(-ENOMEM);
- osc->clk.name = name;
- osc->clk.ops = &slow_osc_ops;
- osc->parent_name = parent_name;
- osc->clk.parent_names = &osc->parent_name;
- osc->clk.num_parents = 1;
- /* osc->clk.flags = CLK_IGNORE_UNUSED; */
+ init.name = name;
+ init.ops = &slow_osc_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = CLK_IGNORE_UNUSED;
+ osc->hw.init = &init;
osc->sckcr = sckcr;
osc->startup_usec = startup;
osc->bits = bits;
@@ -151,34 +146,35 @@ at91_clk_register_slow_osc(void __iomem *sckcr,
writel((readl(sckcr) & ~osc->bits->cr_osc32en) |
osc->bits->cr_osc32byp, sckcr);
- ret = clk_register(&osc->clk);
+ hw = &osc->hw;
+ ret = clk_hw_register(NULL, &osc->hw);
if (ret) {
kfree(osc);
- return ERR_PTR(ret);
+ hw = ERR_PTR(ret);
}
- return &osc->clk;
+ return hw;
}
-static void at91_clk_unregister_slow_osc(struct clk *clk)
+static void at91_clk_unregister_slow_osc(struct clk_hw *hw)
{
- struct clk_slow_osc *osc = to_clk_slow_osc(clk);
+ struct clk_slow_osc *osc = to_clk_slow_osc(hw);
- clk_unregister(clk);
+ clk_hw_unregister(hw);
kfree(osc);
}
-static unsigned long clk_slow_rc_osc_recalc_rate(struct clk *clk,
+static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(clk);
+ struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
return osc->frequency;
}
-static int clk_slow_rc_osc_enable(struct clk *clk)
+static int clk_slow_rc_osc_prepare(struct clk_hw *hw)
{
- struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(clk);
+ struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
void __iomem *sckcr = osc->sckcr;
writel(readl(sckcr) | osc->bits->cr_rcen, sckcr);
@@ -188,29 +184,29 @@ static int clk_slow_rc_osc_enable(struct clk *clk)
return 0;
}
-static void clk_slow_rc_osc_disable(struct clk *clk)
+static void clk_slow_rc_osc_unprepare(struct clk_hw *hw)
{
- struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(clk);
+ struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
void __iomem *sckcr = osc->sckcr;
writel(readl(sckcr) & ~osc->bits->cr_rcen, sckcr);
}
-static int clk_slow_rc_osc_is_enabled(struct clk *clk)
+static int clk_slow_rc_osc_is_prepared(struct clk_hw *hw)
{
- struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(clk);
+ struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
return !!(readl(osc->sckcr) & osc->bits->cr_rcen);
}
static const struct clk_ops slow_rc_osc_ops = {
- .enable = clk_slow_rc_osc_enable,
- .disable = clk_slow_rc_osc_disable,
- .is_enabled = clk_slow_rc_osc_is_enabled,
+ .enable = clk_slow_rc_osc_prepare,
+ .disable = clk_slow_rc_osc_unprepare,
+ .is_enabled = clk_slow_rc_osc_is_prepared,
.recalc_rate = clk_slow_rc_osc_recalc_rate,
};
-static struct clk * __init
+static struct clk_hw * __init
at91_clk_register_slow_rc_osc(void __iomem *sckcr,
const char *name,
unsigned long frequency,
@@ -219,43 +215,51 @@ at91_clk_register_slow_rc_osc(void __iomem *sckcr,
const struct clk_slow_bits *bits)
{
struct clk_slow_rc_osc *osc;
+ struct clk_hw *hw;
+ struct clk_init_data init;
int ret;
if (!sckcr || !name)
return ERR_PTR(-EINVAL);
- osc = xzalloc(sizeof(*osc));
- osc->clk.name = name;
- osc->clk.ops = &slow_rc_osc_ops;
- osc->clk.parent_names = NULL;
- osc->clk.num_parents = 0;
- /* init.flags = CLK_IGNORE_UNUSED; */
+ osc = kzalloc(sizeof(*osc), GFP_KERNEL);
+ if (!osc)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &slow_rc_osc_ops;
+ init.parent_names = NULL;
+ init.num_parents = 0;
+ init.flags = CLK_IGNORE_UNUSED;
+ osc->hw.init = &init;
osc->sckcr = sckcr;
osc->bits = bits;
osc->frequency = frequency;
+ osc->accuracy = accuracy;
osc->startup_usec = startup;
- ret = clk_register(&osc->clk);
+ hw = &osc->hw;
+ ret = clk_hw_register(NULL, &osc->hw);
if (ret) {
kfree(osc);
- return ERR_PTR(ret);
+ hw = ERR_PTR(ret);
}
- return &osc->clk;
+ return hw;
}
-static void at91_clk_unregister_slow_rc_osc(struct clk *clk)
+static void at91_clk_unregister_slow_rc_osc(struct clk_hw *hw)
{
- struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(clk);
+ struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
- clk_unregister(clk);
+ clk_hw_unregister(hw);
kfree(osc);
}
-static int clk_sam9x5_slow_set_parent(struct clk *clk, u8 index)
+static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index)
{
- struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(clk);
+ struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
void __iomem *sckcr = slowck->sckcr;
u32 tmp;
@@ -280,9 +284,9 @@ static int clk_sam9x5_slow_set_parent(struct clk *clk, u8 index)
return 0;
}
-static int clk_sam9x5_slow_get_parent(struct clk *clk)
+static int clk_sam9x5_slow_get_parent(struct clk_hw *hw)
{
- struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(clk);
+ struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
return !!(readl(slowck->sckcr) & slowck->bits->cr_oscsel);
}
@@ -292,7 +296,7 @@ static const struct clk_ops sam9x5_slow_ops = {
.get_parent = clk_sam9x5_slow_get_parent,
};
-static struct clk * __init
+static struct clk_hw * __init
at91_clk_register_sam9x5_slow(void __iomem *sckcr,
const char *name,
const char **parent_names,
@@ -300,37 +304,43 @@ at91_clk_register_sam9x5_slow(void __iomem *sckcr,
const struct clk_slow_bits *bits)
{
struct clk_sam9x5_slow *slowck;
+ struct clk_hw *hw;
+ struct clk_init_data init;
int ret;
if (!sckcr || !name || !parent_names || !num_parents)
return ERR_PTR(-EINVAL);
- slowck = xzalloc(sizeof(*slowck));
- slowck->clk.name = name;
- slowck->clk.ops = &sam9x5_slow_ops;
+ slowck = kzalloc(sizeof(*slowck), GFP_KERNEL);
+ if (!slowck)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &sam9x5_slow_ops;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+ init.flags = 0;
- memcpy(slowck->parent_names, parent_names,
- num_parents * sizeof(slowck->parent_names[0]));
- slowck->clk.parent_names = slowck->parent_names;
- slowck->clk.num_parents = num_parents;
+ slowck->hw.init = &init;
slowck->sckcr = sckcr;
slowck->bits = bits;
slowck->parent = !!(readl(sckcr) & slowck->bits->cr_oscsel);
- ret = clk_register(&slowck->clk);
+ hw = &slowck->hw;
+ ret = clk_hw_register(NULL, &slowck->hw);
if (ret) {
kfree(slowck);
- return ERR_PTR(ret);
+ hw = ERR_PTR(ret);
}
- return &slowck->clk;
+ return hw;
}
-static void at91_clk_unregister_sam9x5_slow(struct clk *clk)
+static void at91_clk_unregister_sam9x5_slow(struct clk_hw *hw)
{
- struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(clk);
+ struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
- clk_unregister(clk);
+ clk_hw_unregister(hw);
kfree(slowck);
}
@@ -342,7 +352,7 @@ static void __init at91sam9x5_sckc_register(struct device_node *np,
void __iomem *regbase = of_iomap(np, 0);
struct device_node *child = NULL;
const char *xtal_name;
- struct clk *slow_rc, *slow_osc, *slowck;
+ struct clk_hw *slow_rc, *slow_osc, *slowck;
bool bypass;
int ret;
@@ -385,10 +395,10 @@ static void __init at91sam9x5_sckc_register(struct device_node *np,
/* DT backward compatibility */
if (child)
- ret = of_clk_add_provider(child, of_clk_src_simple_get,
+ ret = of_clk_add_hw_provider(child, of_clk_hw_simple_get,
slowck);
else
- ret = of_clk_add_provider(np, of_clk_src_simple_get, slowck);
+ ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, slowck);
if (WARN_ON(ret))
goto unregister_slowck;
@@ -433,8 +443,8 @@ static const struct clk_slow_bits at91sam9x60_bits = {
static void __init of_sam9x60_sckc_setup(struct device_node *np)
{
void __iomem *regbase = of_iomap(np, 0);
- struct clk_onecell_data *clk_data;
- struct clk *slow_rc, *slow_osc;
+ struct clk_hw_onecell_data *clk_data;
+ struct clk_hw *slow_rc, *slow_osc;
const char *xtal_name;
const char *parent_names[2] = { "slow_rc_osc", "slow_osc" };
bool bypass;
@@ -443,8 +453,9 @@ static void __init of_sam9x60_sckc_setup(struct device_node *np)
if (!regbase)
return;
- slow_rc = clk_register_fixed_rate(parent_names[0], NULL, 0,
- 32768);
+ slow_rc = clk_hw_register_fixed_rate_with_accuracy(NULL, parent_names[0],
+ NULL, 0, 32768,
+ 93750000);
if (IS_ERR(slow_rc))
return;
@@ -459,61 +470,54 @@ static void __init of_sam9x60_sckc_setup(struct device_node *np)
if (IS_ERR(slow_osc))
goto unregister_slow_rc;
- clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+ clk_data = kzalloc(struct_size(clk_data, hws, 2), GFP_KERNEL);
if (!clk_data)
goto unregister_slow_osc;
/* MD_SLCK and TD_SLCK. */
- clk_data->clk_num = 2;
- clk_data->clks = kcalloc(clk_data->clk_num,
- sizeof(*clk_data->clks), GFP_KERNEL);
- if (!clk_data->clks)
+ clk_data->num = 2;
+ clk_data->hws[0] = clk_hw_register_fixed_rate(NULL, "md_slck",
+ parent_names[0],
+ 0, 32768);
+ if (IS_ERR(clk_data->hws[0]))
goto clk_data_free;
- clk_data->clks[0] = clk_register_fixed_rate("md_slck",
- parent_names[0],
- 0, 32768);
- if (IS_ERR(clk_data->clks[0]))
- goto clks_free;
-
- clk_data->clks[1] = at91_clk_register_sam9x5_slow(regbase, "td_slck",
+ clk_data->hws[1] = at91_clk_register_sam9x5_slow(regbase, "td_slck",
parent_names, 2,
&at91sam9x60_bits);
- if (IS_ERR(clk_data->clks[1]))
+ if (IS_ERR(clk_data->hws[1]))
goto unregister_md_slck;
- ret = of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+ ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
if (WARN_ON(ret))
goto unregister_td_slck;
return;
unregister_td_slck:
- at91_clk_unregister_sam9x5_slow(clk_data->clks[1]);
+ at91_clk_unregister_sam9x5_slow(clk_data->hws[1]);
unregister_md_slck:
- clk_unregister(clk_data->clks[0]);
-clks_free:
- kfree(clk_data->clks);
+ clk_hw_unregister(clk_data->hws[0]);
clk_data_free:
kfree(clk_data);
unregister_slow_osc:
at91_clk_unregister_slow_osc(slow_osc);
unregister_slow_rc:
- clk_unregister(slow_rc);
+ clk_hw_unregister(slow_rc);
}
CLK_OF_DECLARE(sam9x60_clk_sckc, "microchip,sam9x60-sckc",
of_sam9x60_sckc_setup);
-static int clk_sama5d4_slow_osc_enable(struct clk *clk)
+static int clk_sama5d4_slow_osc_prepare(struct clk_hw *hw)
{
- struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(clk);
+ struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(hw);
if (osc->prepared)
return 0;
/*
* Assume that if it has already been selected (for example by the
- * bootloader), enough time has aready passed.
+ * bootloader), enough time has already passed.
*/
if ((readl(osc->sckcr) & osc->bits->cr_oscsel)) {
osc->prepared = true;
@@ -526,16 +530,16 @@ static int clk_sama5d4_slow_osc_enable(struct clk *clk)
return 0;
}
-static int clk_sama5d4_slow_osc_is_enabled(struct clk *clk)
+static int clk_sama5d4_slow_osc_is_prepared(struct clk_hw *hw)
{
- struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(clk);
+ struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(hw);
return osc->prepared;
}
static const struct clk_ops sama5d4_slow_osc_ops = {
- .enable = clk_sama5d4_slow_osc_enable,
- .is_enabled = clk_sama5d4_slow_osc_is_enabled,
+ .enable = clk_sama5d4_slow_osc_prepare,
+ .is_enabled = clk_sama5d4_slow_osc_is_prepared,
};
static const struct clk_slow_bits at91sama5d4_bits = {
@@ -545,32 +549,41 @@ static const struct clk_slow_bits at91sama5d4_bits = {
static void __init of_sama5d4_sckc_setup(struct device_node *np)
{
void __iomem *regbase = of_iomap(np, 0);
- struct clk *slow_rc, *slowck;
+ struct clk_hw *slow_rc, *slowck;
struct clk_sama5d4_slow_osc *osc;
+ struct clk_init_data init;
+ const char *xtal_name;
const char *parent_names[2] = { "slow_rc_osc", "slow_osc" };
int ret;
if (!regbase)
return;
- slow_rc = clk_fixed(parent_names[0], 32768);
+ slow_rc = clk_hw_register_fixed_rate_with_accuracy(NULL,
+ parent_names[0],
+ NULL, 0, 32768,
+ 250000000);
if (IS_ERR(slow_rc))
return;
- osc = xzalloc(sizeof(*osc));
- osc->parent_name = of_clk_get_parent_name(np, 0);
- osc->clk.name = parent_names[1];
- osc->clk.ops = &sama5d4_slow_osc_ops;
- osc->clk.parent_names = &osc->parent_name;
- osc->clk.num_parents = 1;
+ xtal_name = of_clk_get_parent_name(np, 0);
+
+ osc = kzalloc(sizeof(*osc), GFP_KERNEL);
+ if (!osc)
+ goto unregister_slow_rc;
- /* osc->clk.flags = CLK_IGNORE_UNUSED; */
+ init.name = parent_names[1];
+ init.ops = &sama5d4_slow_osc_ops;
+ init.parent_names = &xtal_name;
+ init.num_parents = 1;
+ init.flags = CLK_IGNORE_UNUSED;
+ osc->hw.init = &init;
osc->sckcr = regbase;
osc->startup_usec = 1200000;
osc->bits = &at91sama5d4_bits;
- ret = clk_register(&osc->clk);
+ ret = clk_hw_register(NULL, &osc->hw);
if (ret)
goto free_slow_osc_data;
@@ -580,7 +593,7 @@ static void __init of_sama5d4_sckc_setup(struct device_node *np)
if (IS_ERR(slowck))
goto unregister_slow_osc;
- ret = of_clk_add_provider(np, of_clk_src_simple_get, slowck);
+ ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, slowck);
if (WARN_ON(ret))
goto unregister_slowck;
@@ -589,10 +602,11 @@ static void __init of_sama5d4_sckc_setup(struct device_node *np)
unregister_slowck:
at91_clk_unregister_sam9x5_slow(slowck);
unregister_slow_osc:
- clk_unregister(&osc->clk);
+ clk_hw_unregister(&osc->hw);
free_slow_osc_data:
kfree(osc);
- clk_unregister(slow_rc);
+unregister_slow_rc:
+ clk_hw_unregister(slow_rc);
}
CLK_OF_DECLARE(sama5d4_clk_sckc, "atmel,sama5d4-sckc",
of_sama5d4_sckc_setup);
diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile
new file mode 100644
index 0000000000..1539e9f592
--- /dev/null
+++ b/drivers/clk/bcm/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_ARCH_BCM283X) += clk-bcm2835-aux.o
diff --git a/drivers/clk/bcm/clk-bcm2835-aux.c b/drivers/clk/bcm/clk-bcm2835-aux.c
new file mode 100644
index 0000000000..aabeb88f59
--- /dev/null
+++ b/drivers/clk/bcm/clk-bcm2835-aux.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Broadcom
+ */
+
+#include <linux/clk.h>
+#include <io.h>
+#include <of_address.h>
+#include <driver.h>
+#include <init.h>
+#include <dt-bindings/clock/bcm2835-aux.h>
+
+#define BCM2835_AUXIRQ 0x00
+#define BCM2835_AUXENB 0x04
+
+static int bcm2835_aux_clk_probe(struct device *dev)
+{
+ struct clk_hw_onecell_data *onecell;
+ const char *parent;
+ struct clk *parent_clk;
+ void __iomem *reg, *gate;
+
+ parent_clk = clk_get(dev, NULL);
+ if (IS_ERR(parent_clk))
+ return PTR_ERR(parent_clk);
+ parent = __clk_get_name(parent_clk);
+
+ reg = of_iomap(dev->of_node, 0);
+ if (!reg)
+ return -ENOMEM;
+
+ onecell = kmalloc(struct_size(onecell, hws, BCM2835_AUX_CLOCK_COUNT),
+ GFP_KERNEL);
+ if (!onecell)
+ return -ENOMEM;
+ onecell->num = BCM2835_AUX_CLOCK_COUNT;
+
+ gate = reg + BCM2835_AUXENB;
+ onecell->hws[BCM2835_AUX_CLOCK_UART] =
+ clk_hw_register_gate(dev, "aux_uart", parent, 0, gate, 0, 0, NULL);
+
+ onecell->hws[BCM2835_AUX_CLOCK_SPI1] =
+ clk_hw_register_gate(dev, "aux_spi1", parent, 0, gate, 1, 0, NULL);
+
+ onecell->hws[BCM2835_AUX_CLOCK_SPI2] =
+ clk_hw_register_gate(dev, "aux_spi2", parent, 0, gate, 2, 0, NULL);
+
+ return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
+ onecell);
+}
+
+static const struct of_device_id bcm2835_aux_clk_of_match[] = {
+ { .compatible = "brcm,bcm2835-aux", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, bcm2835_aux_clk_of_match);
+
+static struct driver bcm2835_aux_clk_driver = {
+ .name = "bcm2835-aux-clk",
+ .of_compatible = bcm2835_aux_clk_of_match,
+ .probe = bcm2835_aux_clk_probe,
+};
+core_platform_driver(bcm2835_aux_clk_driver);
+
+MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
+MODULE_DESCRIPTION("BCM2835 auxiliary peripheral clock driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/clk-ar933x.c b/drivers/clk/clk-ar933x.c
index 875e9f506f..c97caaa37e 100644
--- a/drivers/clk/clk-ar933x.c
+++ b/drivers/clk/clk-ar933x.c
@@ -19,17 +19,17 @@ static struct clk *clks[ATH79_CLK_END];
static struct clk_onecell_data clk_data;
struct clk_ar933x {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *base;
u32 div_shift;
u32 div_mask;
const char *parent;
};
-static unsigned long clk_ar933x_recalc_rate(struct clk *clk,
+static unsigned long clk_ar933x_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_ar933x *f = container_of(clk, struct clk_ar933x, clk);
+ struct clk_ar933x *f = container_of(hw, struct clk_ar933x, hw);
unsigned long rate;
unsigned long freq;
u32 clock_ctrl;
@@ -79,14 +79,14 @@ static struct clk *clk_ar933x(const char *name, const char *parent,
f->div_shift = div_shift;
f->div_mask = div_mask;
- f->clk.ops = &clk_ar933x_ops;
- f->clk.name = name;
- f->clk.parent_names = &f->parent;
- f->clk.num_parents = 1;
+ f->hw.clk.ops = &clk_ar933x_ops;
+ f->hw.clk.name = name;
+ f->hw.clk.parent_names = &f->parent;
+ f->hw.clk.num_parents = 1;
- clk_register(&f->clk);
+ bclk_register(&f->hw.clk);
- return &f->clk;
+ return &f->hw.clk;
}
static void ar933x_pll_init(void __iomem *base)
@@ -104,7 +104,7 @@ static void ar933x_pll_init(void __iomem *base)
AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK);
}
-static int ar933x_clk_probe(struct device_d *dev)
+static int ar933x_clk_probe(struct device *dev)
{
struct resource *iores;
void __iomem *base;
@@ -118,7 +118,7 @@ static int ar933x_clk_probe(struct device_d *dev)
clk_data.clks = clks;
clk_data.clk_num = ARRAY_SIZE(clks);
- of_clk_add_provider(dev->device_node, of_clk_src_onecell_get,
+ of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
&clk_data);
return 0;
@@ -131,15 +131,12 @@ static __maybe_unused struct of_device_id ar933x_clk_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, ar933x_clk_dt_ids);
-static struct driver_d ar933x_clk_driver = {
+static struct driver ar933x_clk_driver = {
.probe = ar933x_clk_probe,
.name = "ar933x_clk",
.of_compatible = DRV_OF_COMPAT(ar933x_clk_dt_ids),
};
-static int ar933x_clk_init(void)
-{
- return platform_driver_register(&ar933x_clk_driver);
-}
-postcore_initcall(ar933x_clk_init);
+postcore_platform_driver(ar933x_clk_driver);
diff --git a/drivers/clk/clk-ar9344.c b/drivers/clk/clk-ar9344.c
index ad0e5c10e9..43a9da2857 100644
--- a/drivers/clk/clk-ar9344.c
+++ b/drivers/clk/clk-ar9344.c
@@ -35,17 +35,17 @@ static struct clk *clks[ATH79_CLK_END];
static struct clk_onecell_data clk_data;
struct clk_ar9344 {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *base;
u32 div_shift;
u32 div_mask;
const char *parent;
};
-static unsigned long clk_ar9344_recalc_rate(struct clk *clk,
+static unsigned long clk_ar9344_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_ar9344 *f = container_of(clk, struct clk_ar9344, clk);
+ struct clk_ar9344 *f = container_of(hw, struct clk_ar9344, hw);
int outdiv, refdiv, nint, nfrac;
int cpu_post_div;
u32 clock_ctrl;
@@ -84,14 +84,14 @@ static struct clk *clk_ar9344(const char *name, const char *parent,
f->div_shift = 0;
f->div_mask = 0;
- f->clk.ops = &clk_ar9344_ops;
- f->clk.name = name;
- f->clk.parent_names = &f->parent;
- f->clk.num_parents = 1;
+ f->hw.clk.ops = &clk_ar9344_ops;
+ f->hw.clk.name = name;
+ f->hw.clk.parent_names = &f->parent;
+ f->hw.clk.num_parents = 1;
- clk_register(&f->clk);
+ bclk_register(&f->hw.clk);
- return &f->clk;
+ return &f->hw.clk;
}
static void ar9344_pll_init(void __iomem *base)
@@ -99,7 +99,7 @@ static void ar9344_pll_init(void __iomem *base)
clks[ATH79_CLK_CPU] = clk_ar9344("cpu", "ref", base);
}
-static int ar9344_clk_probe(struct device_d *dev)
+static int ar9344_clk_probe(struct device *dev)
{
struct resource *iores;
void __iomem *base;
@@ -113,7 +113,7 @@ static int ar9344_clk_probe(struct device_d *dev)
clk_data.clks = clks;
clk_data.clk_num = ARRAY_SIZE(clks);
- of_clk_add_provider(dev->device_node, of_clk_src_onecell_get,
+ of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
&clk_data);
return 0;
@@ -126,15 +126,12 @@ static __maybe_unused struct of_device_id ar9344_clk_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, ar9344_clk_dt_ids);
-static struct driver_d ar9344_clk_driver = {
+static struct driver ar9344_clk_driver = {
.probe = ar9344_clk_probe,
.name = "ar9344_clk",
.of_compatible = DRV_OF_COMPAT(ar9344_clk_dt_ids),
};
-static int ar9344_clk_init(void)
-{
- return platform_driver_register(&ar9344_clk_driver);
-}
-postcore_initcall(ar9344_clk_init);
+postcore_platform_driver(ar9344_clk_driver);
diff --git a/drivers/clk/clk-bulk.c b/drivers/clk/clk-bulk.c
index ddbe32f9c2..db775dc40b 100644
--- a/drivers/clk/clk-bulk.c
+++ b/drivers/clk/clk-bulk.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2017 NXP
*
@@ -23,8 +23,9 @@ void clk_bulk_put(int num_clks, struct clk_bulk_data *clks)
}
EXPORT_SYMBOL_GPL(clk_bulk_put);
-int __must_check clk_bulk_get(struct device_d *dev, int num_clks,
- struct clk_bulk_data *clks)
+static int __clk_bulk_get(struct device *dev, int num_clks,
+ struct clk_bulk_data *clks,
+ bool optional)
{
int ret;
int i;
@@ -36,10 +37,15 @@ int __must_check clk_bulk_get(struct device_d *dev, int num_clks,
clks[i].clk = clk_get(dev, clks[i].id);
if (IS_ERR(clks[i].clk)) {
ret = PTR_ERR(clks[i].clk);
+ clks[i].clk = NULL;
+
+ if (ret == -ENOENT && optional)
+ continue;
+
if (ret != -EPROBE_DEFER)
dev_err(dev, "Failed to get clk '%s': %d\n",
clks[i].id, ret);
- clks[i].clk = NULL;
+
goto err;
}
}
@@ -51,8 +57,102 @@ err:
return ret;
}
+
+int __must_check clk_bulk_get(struct device *dev, int num_clks,
+ struct clk_bulk_data *clks)
+{
+ return __clk_bulk_get(dev, num_clks, clks, false);
+}
EXPORT_SYMBOL(clk_bulk_get);
+int __must_check clk_bulk_get_optional(struct device *dev, int num_clks,
+ struct clk_bulk_data *clks)
+{
+ return __clk_bulk_get(dev, num_clks, clks, true);
+}
+EXPORT_SYMBOL(clk_bulk_get_optional);
+
+static int __must_check of_clk_bulk_get(struct device_node *np, int num_clks,
+ struct clk_bulk_data *clks)
+{
+ int ret;
+ int i;
+
+ for (i = 0; i < num_clks; i++) {
+ clks[i].id = NULL;
+ clks[i].clk = NULL;
+ }
+
+ for (i = 0; i < num_clks; i++) {
+ of_property_read_string_index(np, "clock-names", i, &clks[i].id);
+ clks[i].clk = of_clk_get(np, i);
+ if (IS_ERR(clks[i].clk)) {
+ ret = PTR_ERR(clks[i].clk);
+ if (ret != -EPROBE_DEFER)
+ pr_err("%s: Failed to get clk index: %d ret: %pe\n",
+ np->name, i, clks[i].clk);
+ clks[i].clk = NULL;
+ goto err;
+ }
+ }
+
+ return 0;
+
+err:
+ clk_bulk_put(i, clks);
+
+ return ret;
+}
+
+static int __must_check of_clk_bulk_get_all(struct device_node *np,
+ struct clk_bulk_data **clks)
+{
+ struct clk_bulk_data *clk_bulk;
+ int num_clks;
+ int ret;
+
+ num_clks = of_clk_get_parent_count(np);
+ if (!num_clks)
+ return 0;
+
+ clk_bulk = kmalloc_array(num_clks, sizeof(*clk_bulk), GFP_KERNEL);
+ if (!clk_bulk)
+ return -ENOMEM;
+
+ ret = of_clk_bulk_get(np, num_clks, clk_bulk);
+ if (ret) {
+ kfree(clk_bulk);
+ return ret;
+ }
+
+ *clks = clk_bulk;
+
+ return num_clks;
+}
+
+void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks)
+{
+ if (IS_ERR_OR_NULL(clks))
+ return;
+
+ clk_bulk_put(num_clks, clks);
+
+ kfree(clks);
+}
+EXPORT_SYMBOL(clk_bulk_put_all);
+
+int __must_check clk_bulk_get_all(struct device *dev,
+ struct clk_bulk_data **clks)
+{
+ struct device_node *np = dev->of_node;
+
+ if (!np)
+ return 0;
+
+ return of_clk_bulk_get_all(np, clks);
+}
+EXPORT_SYMBOL(clk_bulk_get_all);
+
/**
* clk_bulk_disable - gate a set of clocks
* @num_clks: the number of clk_bulk_data
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index e0f543bc1c..454bfaeb0c 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -12,85 +12,123 @@
#include <linux/err.h>
struct clk_composite {
- struct clk clk;
+ struct clk_hw hw;
struct clk *mux_clk;
struct clk *rate_clk;
struct clk *gate_clk;
};
-#define to_clk_composite(_clk) container_of(_clk, struct clk_composite, clk)
+#define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw)
-static int clk_composite_get_parent(struct clk *clk)
+static int clk_composite_get_parent(struct clk_hw *hw)
{
- struct clk_composite *composite = to_clk_composite(clk);
+ struct clk_composite *composite = to_clk_composite(hw);
struct clk *mux_clk = composite->mux_clk;
+ struct clk_hw *mux_hw = clk_to_clk_hw(mux_clk);
- return mux_clk ? mux_clk->ops->get_parent(mux_clk) : 0;
+ return mux_clk ? mux_clk->ops->get_parent(mux_hw) : 0;
}
-static int clk_composite_set_parent(struct clk *clk, u8 index)
+static int clk_composite_set_parent(struct clk_hw *hw, u8 index)
{
- struct clk_composite *composite = to_clk_composite(clk);
+ struct clk_composite *composite = to_clk_composite(hw);
struct clk *mux_clk = composite->mux_clk;
+ struct clk_hw *mux_hw = clk_to_clk_hw(mux_clk);
- return mux_clk ? mux_clk->ops->set_parent(mux_clk, index) : 0;
+ return mux_clk ? mux_clk->ops->set_parent(mux_hw, index) : 0;
}
-static unsigned long clk_composite_recalc_rate(struct clk *clk,
+static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_composite *composite = to_clk_composite(clk);
+ struct clk_composite *composite = to_clk_composite(hw);
struct clk *rate_clk = composite->rate_clk;
+ struct clk_hw *rate_hw = clk_to_clk_hw(rate_clk);
if (rate_clk)
- return rate_clk->ops->recalc_rate(rate_clk, parent_rate);
+ return rate_clk->ops->recalc_rate(rate_hw, parent_rate);
return parent_rate;
}
-static long clk_composite_round_rate(struct clk *clk, unsigned long rate,
+static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
- struct clk_composite *composite = to_clk_composite(clk);
+ struct clk_composite *composite = to_clk_composite(hw);
struct clk *rate_clk = composite->rate_clk;
+ struct clk *mux_clk = composite->mux_clk;
+ struct clk_hw *rate_hw = clk_to_clk_hw(rate_clk);
+
+ if (rate_clk)
+ return rate_clk->ops->round_rate(rate_hw, rate, prate);
- return rate_clk ? rate_clk->ops->round_rate(rate_clk, rate, prate) : 0;
+ if (!(hw->clk.flags & CLK_SET_RATE_NO_REPARENT) &&
+ mux_clk &&
+ mux_clk->ops->set_rate)
+ return mux_clk->ops->round_rate(clk_to_clk_hw(mux_clk), rate, prate);
+
+ return *prate;
}
-static int clk_composite_set_rate(struct clk *clk, unsigned long rate,
+static int clk_composite_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_composite *composite = to_clk_composite(clk);
+ struct clk_composite *composite = to_clk_composite(hw);
struct clk *rate_clk = composite->rate_clk;
+ struct clk *mux_clk = composite->mux_clk;
+ struct clk_hw *rate_hw = clk_to_clk_hw(rate_clk);
+
+ /*
+ * When the rate clock is present use that to set the rate,
+ * otherwise try the mux clock. We currently do not support
+ * to find the best rate using a combination of both.
+ */
+ if (rate_clk)
+ return rate_clk->ops->set_rate(rate_hw, rate, parent_rate);
+
+ if (!(hw->clk.flags & CLK_SET_RATE_NO_REPARENT) &&
+ mux_clk &&
+ mux_clk->ops->set_rate) {
+ /*
+ * We'll call set_rate on the mux clk which in turn results
+ * in reparenting the mux clk. Make sure the enable count
+ * (which is stored in the composite clk, not the mux clk)
+ * is transferred correctly.
+ */
+ mux_clk->enable_count = hw->clk.enable_count;
+ return mux_clk->ops->set_rate(clk_to_clk_hw(mux_clk), rate, parent_rate);
+ }
- return rate_clk ?
- rate_clk->ops->set_rate(rate_clk, rate, parent_rate) : 0;
+ return 0;
}
-static int clk_composite_is_enabled(struct clk *clk)
+static int clk_composite_is_enabled(struct clk_hw *hw)
{
- struct clk_composite *composite = to_clk_composite(clk);
+ struct clk_composite *composite = to_clk_composite(hw);
struct clk *gate_clk = composite->gate_clk;
+ struct clk_hw *gate_hw = clk_to_clk_hw(gate_clk);
- return gate_clk ? gate_clk->ops->is_enabled(gate_clk) : 0;
+ return gate_clk ? gate_clk->ops->is_enabled(gate_hw) : 0;
}
-static int clk_composite_enable(struct clk *clk)
+static int clk_composite_enable(struct clk_hw *hw)
{
- struct clk_composite *composite = to_clk_composite(clk);
+ struct clk_composite *composite = to_clk_composite(hw);
struct clk *gate_clk = composite->gate_clk;
+ struct clk_hw *gate_hw = clk_to_clk_hw(gate_clk);
- return gate_clk ? gate_clk->ops->enable(gate_clk) : 0;
+ return gate_clk ? gate_clk->ops->enable(gate_hw) : 0;
}
-static void clk_composite_disable(struct clk *clk)
+static void clk_composite_disable(struct clk_hw *hw)
{
- struct clk_composite *composite = to_clk_composite(clk);
+ struct clk_composite *composite = to_clk_composite(hw);
struct clk *gate_clk = composite->gate_clk;
+ struct clk_hw *gate_hw = clk_to_clk_hw(gate_clk);
if (gate_clk)
- gate_clk->ops->disable(gate_clk);
+ gate_clk->ops->disable(gate_hw);
}
static struct clk_ops clk_composite_ops = {
@@ -116,22 +154,61 @@ struct clk *clk_register_composite(const char *name,
composite = xzalloc(sizeof(*composite));
- composite->clk.name = name;
- composite->clk.ops = &clk_composite_ops;
- composite->clk.flags = flags;
- composite->clk.parent_names = parent_names;
- composite->clk.num_parents = num_parents;
+ composite->hw.clk.name = name;
+ composite->hw.clk.ops = &clk_composite_ops;
+ composite->hw.clk.flags = flags;
+ composite->hw.clk.parent_names = parent_names;
+ composite->hw.clk.num_parents = num_parents;
composite->mux_clk = mux_clk;
composite->rate_clk = rate_clk;
composite->gate_clk = gate_clk;
- ret = clk_register(&composite->clk);
+ ret = bclk_register(&composite->hw.clk);
if (ret)
goto err;
- return &composite->clk;
+ if (composite->mux_clk) {
+ composite->mux_clk->parents = composite->hw.clk.parents;
+ composite->mux_clk->parent_names = composite->hw.clk.parent_names;
+ composite->mux_clk->num_parents = composite->hw.clk.num_parents;
+ }
+
+ return &composite->hw.clk;
err:
kfree(composite);
return 0;
}
+
+struct clk_hw *clk_hw_register_composite(struct device *dev,
+ const char *name,
+ const char * const *parent_names,
+ int num_parents,
+ struct clk_hw *mux_hw,
+ const struct clk_ops *mux_ops,
+ struct clk_hw *rate_hw,
+ const struct clk_ops *rate_ops,
+ struct clk_hw *gate_hw,
+ const struct clk_ops *gate_ops,
+ unsigned long flags)
+{
+ struct clk *clk;
+
+ if (mux_hw)
+ mux_hw->clk.ops = mux_ops;
+ if (rate_hw)
+ rate_hw->clk.ops = rate_ops;
+ if (gate_hw)
+ gate_hw->clk.ops = gate_ops;
+
+ parent_names = memdup_array(parent_names, num_parents);
+ if (!parent_names)
+ return ERR_PTR(-ENOMEM);
+
+ clk = clk_register_composite(xstrdup(name), parent_names, num_parents,
+ mux_hw ? &mux_hw->clk : NULL,
+ rate_hw ? &rate_hw->clk : NULL,
+ gate_hw ? &gate_hw->clk : NULL,
+ flags);
+ return clk_to_clk_hw(clk);
+}
diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
index 0bd99993cc..ca596f2cf3 100644
--- a/drivers/clk/clk-conf.c
+++ b/drivers/clk/clk-conf.c
@@ -22,8 +22,8 @@ static int __set_clk_parents(struct device_node *node, bool clk_supplier)
num_parents = of_count_phandle_with_args(node, "assigned-clock-parents",
"#clock-cells");
if (num_parents == -EINVAL)
- pr_err("clk: invalid value of clock-parents property at %s\n",
- node->full_name);
+ pr_err("clk: invalid value of clock-parents property at %pOF\n",
+ node);
for (index = 0; index < num_parents; index++) {
rc = of_parse_phandle_with_args(node, "assigned-clock-parents",
@@ -39,8 +39,8 @@ static int __set_clk_parents(struct device_node *node, bool clk_supplier)
return 0;
pclk = of_clk_get_from_provider(&clkspec);
if (IS_ERR(pclk)) {
- pr_warn("clk: couldn't get parent clock %d for %s\n",
- index, node->full_name);
+ pr_warn("clk: couldn't get parent clock %d for %pOF\n",
+ index, node);
return PTR_ERR(pclk);
}
@@ -54,8 +54,8 @@ static int __set_clk_parents(struct device_node *node, bool clk_supplier)
}
clk = of_clk_get_from_provider(&clkspec);
if (IS_ERR(clk)) {
- pr_warn("clk: couldn't get parent clock %d for %s\n",
- index, node->full_name);
+ pr_warn("clk: couldn't get parent clock %d for %pOF\n",
+ index, node);
rc = PTR_ERR(clk);
goto err;
}
@@ -98,8 +98,8 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
clk = of_clk_get_from_provider(&clkspec);
if (IS_ERR(clk)) {
- pr_warn("clk: couldn't get clock %d for %s\n",
- index, node->full_name);
+ pr_warn("clk: couldn't get clock %d for %pOF\n",
+ index, node);
return PTR_ERR(clk);
}
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index cad902fd32..ccab70aecc 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -7,10 +7,10 @@
#include <common.h>
#include <io.h>
#include <malloc.h>
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/log2.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
{
@@ -88,14 +88,21 @@ unsigned long divider_recalc_rate(struct clk *clk, unsigned long parent_rate,
unsigned int div;
div = _get_div(table, val, flags, width);
+ if (!div) {
+ WARN(!(flags & CLK_DIVIDER_ALLOW_ZERO),
+ "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
+ clk->name);
+ return parent_rate;
+ }
return DIV_ROUND_UP_ULL((u64)parent_rate, div);
}
-static unsigned long clk_divider_recalc_rate(struct clk *clk,
+static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_divider *divider = container_of(clk, struct clk_divider, clk);
+ struct clk *clk = clk_hw_to_clk(hw);
+ struct clk_divider *divider = container_of(hw, struct clk_divider, hw);
unsigned int val;
val = readl(divider->reg) >> divider->shift;
@@ -233,13 +240,47 @@ long divider_round_rate(struct clk *clk, unsigned long rate,
return DIV_ROUND_UP(*prate, div);
}
-static long clk_divider_round_rate(struct clk *clk, unsigned long rate,
+long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
+ unsigned long rate, unsigned long *prate,
+ const struct clk_div_table *table,
+ u8 width, unsigned long flags)
+{
+ int div;
+
+ div = clk_divider_bestdiv(&hw->clk, rate, prate, table, width, flags);
+
+ return DIV_ROUND_UP_ULL((u64)*prate, div);
+}
+EXPORT_SYMBOL_GPL(divider_round_rate_parent);
+
+long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
+ unsigned long rate, unsigned long *prate,
+ const struct clk_div_table *table, u8 width,
+ unsigned long flags, unsigned int val)
+{
+ int div;
+
+ div = _get_div(table, val, flags, width);
+
+ /* Even a read-only clock can propagate a rate change */
+ if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
+ if (!*prate)
+ return -EINVAL;
+
+ *prate = clk_hw_round_rate(clk_hw_get_parent(hw), rate * div);
+ }
+
+ return DIV_ROUND_UP_ULL((u64)*prate, div);
+}
+
+static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
- struct clk_divider *divider = container_of(clk, struct clk_divider, clk);
+ struct clk *clk = clk_hw_to_clk(hw);
+ struct clk_divider *divider = to_clk_divider(hw);
if (divider->flags & CLK_DIVIDER_READ_ONLY)
- return clk_divider_recalc_rate(clk, *prate);
+ return clk_divider_recalc_rate(hw, *prate);
return divider_round_rate(clk, rate, prate, divider->table,
divider->width, divider->flags);
@@ -261,23 +302,22 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate,
return min_t(unsigned int, value, clk_div_mask(width));
}
-static int clk_divider_set_rate(struct clk *clk, unsigned long rate,
+static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_divider *divider = container_of(clk, struct clk_divider, clk);
- unsigned int div, value;
+ struct clk *clk = clk_hw_to_clk(hw);
+ struct clk_divider *divider = to_clk_divider(hw);
+ unsigned int value;
u32 val;
if (divider->flags & CLK_DIVIDER_READ_ONLY)
return 0;
if (clk->flags & CLK_SET_RATE_PARENT) {
- unsigned long best_parent_rate = parent_rate;
- div = clk_divider_bestdiv(clk, rate, &best_parent_rate,
- divider->table, divider->width, divider->flags);
- clk_set_rate(clk_get_parent(clk), best_parent_rate);
- } else {
- div = DIV_ROUND_UP(parent_rate, rate);
+ clk_divider_bestdiv(clk, rate, &parent_rate,
+ divider->table, divider->width,
+ divider->flags);
+ clk_set_rate(clk_get_parent(clk), parent_rate);
}
value = divider_get_val(rate, parent_rate, divider->table,
@@ -287,7 +327,7 @@ static int clk_divider_set_rate(struct clk *clk, unsigned long rate,
val &= ~(clk_div_mask(divider->width) << divider->shift);
val |= value << divider->shift;
- if (clk->flags & CLK_DIVIDER_HIWORD_MASK)
+ if (divider->flags & CLK_DIVIDER_HIWORD_MASK)
val |= clk_div_mask(divider->width) << (divider->shift + 16);
writel(val, divider->reg);
@@ -295,12 +335,16 @@ static int clk_divider_set_rate(struct clk *clk, unsigned long rate,
return 0;
}
-struct clk_ops clk_divider_ops = {
+const struct clk_ops clk_divider_ops = {
.set_rate = clk_divider_set_rate,
.recalc_rate = clk_divider_recalc_rate,
.round_rate = clk_divider_round_rate,
};
+const struct clk_ops clk_divider_ro_ops = {
+ .recalc_rate = clk_divider_recalc_rate,
+};
+
struct clk *clk_divider_alloc(const char *name, const char *parent,
unsigned clk_flags, void __iomem *reg, u8 shift,
u8 width, unsigned div_flags)
@@ -312,18 +356,19 @@ struct clk *clk_divider_alloc(const char *name, const char *parent,
div->width = width;
div->parent = parent;
div->flags = div_flags;
- div->clk.ops = &clk_divider_ops;
- div->clk.name = name;
- div->clk.flags = clk_flags;
- div->clk.parent_names = &div->parent;
- div->clk.num_parents = 1;
+ div->hw.clk.ops = &clk_divider_ops;
+ div->hw.clk.name = name;
+ div->hw.clk.flags = clk_flags;
+ div->hw.clk.parent_names = &div->parent;
+ div->hw.clk.num_parents = 1;
- return &div->clk;
+ return &div->hw.clk;
}
void clk_divider_free(struct clk *clk)
{
- struct clk_divider *d = container_of(clk, struct clk_divider, clk);
+ struct clk_hw *hw = clk_to_clk_hw(clk);
+ struct clk_divider *d = to_clk_divider(hw);
free(d);
}
@@ -337,7 +382,7 @@ struct clk *clk_divider(const char *name, const char *parent, unsigned clk_flags
d = clk_divider_alloc(name , parent, clk_flags, reg, shift, width,
div_flags);
- ret = clk_register(d);
+ ret = bclk_register(d);
if (ret) {
clk_divider_free(d);
return ERR_PTR(ret);
@@ -352,12 +397,15 @@ struct clk *clk_divider_one_based(const char *name, const char *parent,
{
struct clk_divider *div;
struct clk *clk;
+ struct clk_hw *hw;
clk = clk_divider(name, parent, clk_flags, reg, shift, width, div_flags);
if (IS_ERR(clk))
return clk;
- div = container_of(clk, struct clk_divider, clk);
+ hw = clk_to_clk_hw(clk);
+ div = to_clk_divider(hw);
+
div->flags |= CLK_DIVIDER_ONE_BASED;
return clk;
@@ -377,11 +425,11 @@ struct clk *clk_divider_table(const char *name, const char *parent,
div->width = width;
div->parent = parent;
div->flags = div_flags;
- div->clk.ops = &clk_divider_ops;
- div->clk.name = name;
- div->clk.flags = clk_flags;
- div->clk.parent_names = &div->parent;
- div->clk.num_parents = 1;
+ div->hw.clk.ops = &clk_divider_ops;
+ div->hw.clk.name = name;
+ div->hw.clk.flags = clk_flags;
+ div->hw.clk.parent_names = &div->parent;
+ div->hw.clk.num_parents = 1;
div->table = table;
for (clkt = div->table; clkt->div; clkt++) {
@@ -392,11 +440,59 @@ struct clk *clk_divider_table(const char *name, const char *parent,
div->table_size++;
}
- ret = clk_register(&div->clk);
+ ret = bclk_register(&div->hw.clk);
if (ret) {
free(div);
return ERR_PTR(ret);
}
- return &div->clk;
+ return &div->hw.clk;
+}
+
+struct clk *clk_register_divider_table(struct device *dev, const char *name,
+ const char *parent_name,
+ unsigned long flags,
+ void __iomem *reg, u8 shift, u8 width,
+ u8 clk_divider_flags,
+ const struct clk_div_table *table,
+ spinlock_t *lock)
+{
+ return clk_divider_table(name, parent_name, flags, reg, shift, width,
+ table, clk_divider_flags);
+}
+
+struct clk *clk_register_divider(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+ void __iomem *reg, u8 shift, u8 width,
+ u8 clk_divider_flags, spinlock_t *lock)
+{
+ return clk_divider(name, parent_name, flags, reg, shift, width,
+ clk_divider_flags);
+}
+
+struct clk_hw *clk_hw_register_divider_table(struct device *dev,
+ const char *name,
+ const char *parent_name,
+ unsigned long flags,
+ void __iomem *reg, u8 shift,
+ u8 width,
+ u8 clk_divider_flags,
+ const struct clk_div_table *table,
+ spinlock_t *lock)
+{
+ return clk_to_clk_hw(clk_register_divider_table(dev, xstrdup(name),
+ xstrdup(parent_name), flags, reg, shift, width,
+ clk_divider_flags, table, lock));
+}
+
+struct clk_hw *clk_hw_register_divider(struct device *dev,
+ const char *name,
+ const char *parent_name,
+ unsigned long flags,
+ void __iomem *reg, u8 shift, u8 width,
+ u8 clk_divider_flags, spinlock_t *lock)
+{
+ return clk_to_clk_hw(clk_register_divider(dev, xstrdup(name),
+ xstrdup(parent_name), flags, reg, shift, width,
+ clk_divider_flags, lock));
}
diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index e7738775f8..d2c808d40c 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -10,25 +10,19 @@
#include <linux/clk.h>
#include <linux/err.h>
-struct clk_fixed_factor {
- struct clk clk;
- int mult;
- int div;
- const char *parent;
-};
-
-static unsigned long clk_fixed_factor_recalc_rate(struct clk *clk,
+static unsigned long clk_fixed_factor_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_fixed_factor *f = container_of(clk, struct clk_fixed_factor, clk);
+ struct clk_fixed_factor *f = to_clk_fixed_factor(hw);
return (parent_rate / f->div) * f->mult;
}
-static long clk_factor_round_rate(struct clk *clk, unsigned long rate,
+static long clk_factor_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
- struct clk_fixed_factor *fix = container_of(clk, struct clk_fixed_factor, clk);
+ struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
+ struct clk *clk = clk_hw_to_clk(hw);
if (clk->flags & CLK_SET_RATE_PARENT) {
unsigned long best_parent;
@@ -40,10 +34,11 @@ static long clk_factor_round_rate(struct clk *clk, unsigned long rate,
return (*prate / fix->div) * fix->mult;
}
-static int clk_factor_set_rate(struct clk *clk, unsigned long rate,
+static int clk_factor_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_fixed_factor *fix = container_of(clk, struct clk_fixed_factor, clk);
+ struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
+ struct clk *clk = clk_hw_to_clk(hw);
if (clk->flags & CLK_SET_RATE_PARENT) {
return clk_set_rate(clk_get_parent(clk), rate * fix->div / fix->mult);
@@ -52,7 +47,7 @@ static int clk_factor_set_rate(struct clk *clk, unsigned long rate,
return 0;
}
-static struct clk_ops clk_fixed_factor_ops = {
+struct clk_ops clk_fixed_factor_ops = {
.set_rate = clk_factor_set_rate,
.round_rate = clk_factor_round_rate,
.recalc_rate = clk_fixed_factor_recalc_rate,
@@ -67,19 +62,39 @@ struct clk *clk_fixed_factor(const char *name,
f->mult = mult;
f->div = div;
f->parent = parent;
- f->clk.ops = &clk_fixed_factor_ops;
- f->clk.name = name;
- f->clk.flags = flags;
- f->clk.parent_names = &f->parent;
- f->clk.num_parents = 1;
+ f->hw.clk.ops = &clk_fixed_factor_ops;
+ f->hw.clk.name = name;
+ f->hw.clk.flags = flags;
+ f->hw.clk.parent_names = &f->parent;
+ f->hw.clk.num_parents = 1;
- ret = clk_register(&f->clk);
+ ret = bclk_register(&f->hw.clk);
if (ret) {
free(f);
return ERR_PTR(ret);
}
- return &f->clk;
+ return &f->hw.clk;
+}
+
+struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
+ const char *parent_name,
+ unsigned long flags,
+ unsigned int mult, unsigned int div)
+{
+ return clk_fixed_factor(name, parent_name, mult, div, flags);
+}
+
+struct clk_hw *clk_hw_register_fixed_factor(struct device *dev,
+ const char *name,
+ const char *parent_name,
+ unsigned long flags,
+ unsigned int mult,
+ unsigned int div)
+{
+ return clk_to_clk_hw(clk_register_fixed_factor(dev, xstrdup(name),
+ xstrdup(parent_name),
+ flags, mult, div));
}
/**
diff --git a/drivers/clk/clk-fixed.c b/drivers/clk/clk-fixed.c
index d7ac59c4d4..6ec2feb84f 100644
--- a/drivers/clk/clk-fixed.c
+++ b/drivers/clk/clk-fixed.c
@@ -10,14 +10,14 @@
#include <linux/err.h>
struct clk_fixed {
- struct clk clk;
+ struct clk_hw hw;
unsigned long rate;
};
-static unsigned long clk_fixed_recalc_rate(struct clk *clk,
+static unsigned long clk_fixed_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_fixed *fix = container_of(clk, struct clk_fixed, clk);
+ struct clk_fixed *fix = container_of(hw, struct clk_fixed, hw);
return fix->rate;
}
@@ -36,27 +36,39 @@ struct clk *clk_register_fixed_rate(const char *name,
int ret;
fix->rate = rate;
- fix->clk.ops = &clk_fixed_ops;
- fix->clk.name = name;
- fix->clk.flags = flags;
+ fix->hw.clk.ops = &clk_fixed_ops;
+ fix->hw.clk.name = name;
+ fix->hw.clk.flags = flags;
if (parent_name) {
parent_names = kzalloc(sizeof(const char *), GFP_KERNEL);
if (!parent_names)
return ERR_PTR(-ENOMEM);
- fix->clk.parent_names = parent_names;
- fix->clk.num_parents = 1;
+ parent_names[0] = strdup(parent_name);
+ if (!parent_names[0])
+ return ERR_PTR(-ENOMEM);
+
+ fix->hw.clk.parent_names = parent_names;
+ fix->hw.clk.num_parents = 1;
}
- ret = clk_register(&fix->clk);
+ ret = bclk_register(&fix->hw.clk);
if (ret) {
free(parent_names);
free(fix);
return ERR_PTR(ret);
}
- return &fix->clk;
+ return &fix->hw.clk;
+}
+
+struct clk_hw *clk_hw_register_fixed_rate(struct device *dev,
+ const char *name, const char *parent_name,
+ unsigned long flags, unsigned long rate)
+{
+ return clk_to_clk_hw(clk_register_fixed_rate(xstrdup(name), parent_name,
+ flags, rate));
}
/**
diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c
index 6f0763b05f..d175921f64 100644
--- a/drivers/clk/clk-fractional-divider.c
+++ b/drivers/clk/clk-fractional-divider.c
@@ -4,83 +4,126 @@
*
* Adjustable fractional divider clock implementation.
* Output rate = (m / n) * parent_rate.
+ * Uses rational best approximation algorithm.
*/
#include <common.h>
#include <io.h>
#include <malloc.h>
#include <linux/clk.h>
+#include <linux/spinlock.h>
#include <linux/err.h>
#include <linux/gcd.h>
#include <linux/math64.h>
+#include <linux/rational.h>
#include <linux/barebox-wrapper.h>
-#define to_clk_fd(_hw) container_of(_hw, struct clk_fractional_divider, clk)
+static inline u32 clk_fd_readl(struct clk_fractional_divider *fd)
+{
+ if (fd->flags & CLK_FRAC_DIVIDER_BIG_ENDIAN)
+ return ioread32be(fd->reg);
-struct clk_fractional_divider {
- struct clk clk;
- void __iomem *reg;
- u8 mshift;
- u32 mmask;
- u8 nshift;
- u32 nmask;
- u8 flags;
-};
+ return readl(fd->reg);
+}
+
+static inline void clk_fd_writel(struct clk_fractional_divider *fd, u32 val)
+{
+ if (fd->flags & CLK_FRAC_DIVIDER_BIG_ENDIAN)
+ iowrite32be(val, fd->reg);
+ else
+ writel(val, fd->reg);
+}
-static unsigned long clk_fd_recalc_rate(struct clk *hw,
+static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_fractional_divider *fd = to_clk_fd(hw);
- u32 val, m, n;
+ unsigned long m, n;
+ u32 val;
u64 ret;
- val = readl(fd->reg);
+ val = clk_fd_readl(fd);
m = (val & fd->mmask) >> fd->mshift;
n = (val & fd->nmask) >> fd->nshift;
+ if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) {
+ m++;
+ n++;
+ }
+
+ if (!n || !m)
+ return parent_rate;
+
ret = (u64)parent_rate * m;
do_div(ret, n);
return ret;
}
-static long clk_fd_round_rate(struct clk *hw, unsigned long rate,
- unsigned long *prate)
+static void clk_fd_general_approximation(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate,
+ unsigned long *m, unsigned long *n)
{
struct clk_fractional_divider *fd = to_clk_fd(hw);
- unsigned maxn = (fd->nmask >> fd->nshift) + 1;
- unsigned div;
+ unsigned long scale;
+
+ /*
+ * Get rate closer to *parent_rate to guarantee there is no overflow
+ * for m and n. In the result it will be the nearest rate left shifted
+ * by (scale - fd->nwidth) bits.
+ */
+ scale = fls_long(*parent_rate / rate - 1);
+ if (scale > fd->nwidth)
+ rate <<= scale - fd->nwidth;
+
+ rational_best_approximation(rate, *parent_rate,
+ GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
+ m, n);
+}
- if (!rate || rate >= *prate)
- return *prate;
+static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct clk *clk = clk_hw_to_clk(hw);
+ struct clk_fractional_divider *fd = to_clk_fd(hw);
+ unsigned long m, n;
+ u64 ret;
- div = gcd(*prate, rate);
+ if (!rate || (!(clk->flags & CLK_SET_RATE_PARENT) && rate >= *parent_rate))
+ return *parent_rate;
- while ((*prate / div) > maxn) {
- div <<= 1;
- rate <<= 1;
- }
+ if (fd->approximation)
+ fd->approximation(hw, rate, parent_rate, &m, &n);
+ else
+ clk_fd_general_approximation(hw, rate, parent_rate, &m, &n);
- return rate;
+ ret = (u64)*parent_rate * m;
+ do_div(ret, n);
+
+ return ret;
}
-static int clk_fd_set_rate(struct clk *hw, unsigned long rate,
+static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_fractional_divider *fd = to_clk_fd(hw);
- unsigned long div;
- unsigned n, m;
+ unsigned long m, n;
u32 val;
- div = gcd(parent_rate, rate);
- m = rate / div;
- n = parent_rate / div;
+ rational_best_approximation(rate, parent_rate,
+ GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
+ &m, &n);
+
+ if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) {
+ m--;
+ n--;
+ }
- val = readl(fd->reg);
+ val = clk_fd_readl(fd);
val &= ~(fd->mmask | fd->nmask);
val |= (m << fd->mshift) | (n << fd->nshift);
- writel(val, fd->reg);
+ clk_fd_writel(fd, val);
return 0;
}
@@ -103,22 +146,24 @@ struct clk *clk_fractional_divider_alloc(
fd->reg = reg;
fd->mshift = mshift;
- fd->mmask = (BIT(mwidth) - 1) << mshift;
+ fd->mwidth = mwidth;
+ fd->mmask = GENMASK(mwidth - 1, 0) << mshift;
fd->nshift = nshift;
- fd->nmask = (BIT(nwidth) - 1) << nshift;
+ fd->nwidth = nwidth;
+ fd->nmask = GENMASK(nwidth - 1, 0) << nshift;
fd->flags = clk_divider_flags;
- fd->clk.name = name;
- fd->clk.ops = &clk_fractional_divider_ops;
- fd->clk.flags = flags;
- fd->clk.parent_names = parent_name ? &parent_name : NULL;
- fd->clk.num_parents = parent_name ? 1 : 0;
+ fd->hw.clk.name = name;
+ fd->hw.clk.ops = &clk_fractional_divider_ops;
+ fd->hw.clk.flags = flags;
+ fd->hw.clk.parent_names = parent_name ? &parent_name : NULL;
+ fd->hw.clk.num_parents = parent_name ? 1 : 0;
- return &fd->clk;
+ return &fd->hw.clk;
}
void clk_fractional_divider_free(struct clk *clk_fd)
{
- struct clk_fractional_divider *fd = to_clk_fd(clk_fd);
+ struct clk_fractional_divider *fd = to_clk_fd(clk_to_clk_hw(clk_fd));
free(fd);
}
@@ -138,7 +183,7 @@ struct clk *clk_fractional_divider(
if (IS_ERR(fd))
return fd;
- ret = clk_register(fd);
+ ret = bclk_register(fd);
if (ret) {
clk_fractional_divider_free(fd);
return ERR_PTR(ret);
diff --git a/drivers/clk/clk-gate-shared.c b/drivers/clk/clk-gate-shared.c
index 54c002e836..069f6975b1 100644
--- a/drivers/clk/clk-gate-shared.c
+++ b/drivers/clk/clk-gate-shared.c
@@ -11,13 +11,13 @@
#include <linux/err.h>
struct clk_gate_shared {
- struct clk clk;
+ struct clk_hw hw;
const char *parent;
const char *companion_gate;
struct clk *companion_clk;
};
-#define to_clk_gate_shared(_clk) container_of(_clk, struct clk_gate_shared, clk)
+#define to_clk_gate_shared(_hw) container_of(_hw, struct clk_gate_shared, hw)
static struct clk *lookup_companion(struct clk_gate_shared *g)
{
@@ -30,23 +30,23 @@ static struct clk *lookup_companion(struct clk_gate_shared *g)
return g->companion_clk;
}
-static int clk_gate_shared_enable(struct clk *clk)
+static int clk_gate_shared_enable(struct clk_hw *hw)
{
- struct clk_gate_shared *g = to_clk_gate_shared(clk);
+ struct clk_gate_shared *g = to_clk_gate_shared(hw);
return clk_enable(lookup_companion(g));
}
-static void clk_gate_shared_disable(struct clk *clk)
+static void clk_gate_shared_disable(struct clk_hw *hw)
{
- struct clk_gate_shared *g = to_clk_gate_shared(clk);
+ struct clk_gate_shared *g = to_clk_gate_shared(hw);
clk_disable(lookup_companion(g));
}
-static int clk_gate_shared_is_enabled(struct clk *clk)
+static int clk_gate_shared_is_enabled(struct clk_hw *hw)
{
- struct clk_gate_shared *g = to_clk_gate_shared(clk);
+ struct clk_gate_shared *g = to_clk_gate_shared(hw);
return clk_is_enabled(lookup_companion(g));
}
@@ -67,18 +67,19 @@ static struct clk *clk_gate_shared_alloc(const char *name, const char *parent,
g->parent = parent;
g->companion_gate = companion;
g->companion_clk = ERR_PTR(-EINVAL);
- g->clk.ops = &clk_gate_shared_ops;
- g->clk.name = name;
- g->clk.flags = flags;
- g->clk.parent_names = &g->parent;
- g->clk.num_parents = 1;
+ g->hw.clk.ops = &clk_gate_shared_ops;
+ g->hw.clk.name = name;
+ g->hw.clk.flags = flags;
+ g->hw.clk.parent_names = &g->parent;
+ g->hw.clk.num_parents = 1;
- return &g->clk;
+ return &g->hw.clk;
}
static void clk_gate_shared_free(struct clk *clk)
{
- struct clk_gate_shared *g = to_clk_gate_shared(clk);
+ struct clk_hw *hw = clk_to_clk_hw(clk);
+ struct clk_gate_shared *g = to_clk_gate_shared(hw);
free(g);
}
@@ -103,7 +104,7 @@ struct clk *clk_gate_shared(const char *name, const char *parent, const char *co
clk = clk_gate_shared_alloc(name , parent, companion, flags);
- ret = clk_register(clk);
+ ret = bclk_register(clk);
if (ret) {
clk_gate_shared_free(clk);
return ERR_PTR(ret);
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 59dd643b99..d31920fd0b 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -10,10 +10,10 @@
#include <linux/clk.h>
#include <linux/err.h>
-static void clk_gate_endisable(struct clk *clk, int enable)
+static void clk_gate_endisable(struct clk_hw *hw, int enable)
{
- struct clk_gate *gate = container_of(clk, struct clk_gate, clk);
- int set = gate->flags & CLK_GATE_INVERTED ? 1 : 0;
+ struct clk_gate *gate = container_of(hw, struct clk_gate, hw);
+ int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
u32 val;
set ^= enable;
@@ -34,29 +34,29 @@ static void clk_gate_endisable(struct clk *clk, int enable)
writel(val, gate->reg);
}
-static int clk_gate_enable(struct clk *clk)
+static int clk_gate_enable(struct clk_hw *hw)
{
- clk_gate_endisable(clk, 1);
+ clk_gate_endisable(hw, 1);
return 0;
}
-static void clk_gate_disable(struct clk *clk)
+static void clk_gate_disable(struct clk_hw *hw)
{
- clk_gate_endisable(clk, 0);
+ clk_gate_endisable(hw, 0);
}
-int clk_gate_is_enabled(struct clk *clk)
+int clk_gate_is_enabled(struct clk_hw *hw)
{
- struct clk_gate *g = container_of(clk, struct clk_gate, clk);
+ struct clk_gate *g = container_of(hw, struct clk_gate, hw);
u32 val;
val = readl(g->reg);
if (val & (1 << g->shift))
- return g->flags & CLK_GATE_INVERTED ? 0 : 1;
+ return g->flags & CLK_GATE_SET_TO_DISABLE ? 0 : 1;
else
- return g->flags & CLK_GATE_INVERTED ? 1 : 0;
+ return g->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
}
struct clk_ops clk_gate_ops = {
@@ -75,19 +75,20 @@ struct clk *clk_gate_alloc(const char *name, const char *parent,
g->parent = parent;
g->reg = reg;
g->shift = shift;
- g->clk.ops = &clk_gate_ops;
- g->clk.name = name;
- g->clk.flags = flags;
- g->clk.parent_names = &g->parent;
- g->clk.num_parents = 1;
+ g->hw.clk.ops = &clk_gate_ops;
+ g->hw.clk.name = name;
+ g->hw.clk.flags = flags;
+ g->hw.clk.parent_names = &g->parent;
+ g->hw.clk.num_parents = 1;
g->flags = clk_gate_flags;
- return &g->clk;
+ return &g->hw.clk;
}
void clk_gate_free(struct clk *clk_gate)
{
- struct clk_gate *g = to_clk_gate(clk_gate);
+ struct clk_hw *hw = clk_to_clk_hw(clk_gate);
+ struct clk_gate *g = to_clk_gate(hw);
free(g);
}
@@ -100,9 +101,10 @@ struct clk *clk_gate(const char *name, const char *parent, void __iomem *reg,
g = clk_gate_alloc(name , parent, reg, shift, flags, clk_gate_flags);
- ret = clk_register(g);
+ ret = bclk_register(g);
if (ret) {
- free(to_clk_gate(g));
+ struct clk_hw *hw = clk_to_clk_hw(g);
+ free(to_clk_gate(hw));
return ERR_PTR(ret);
}
@@ -112,5 +114,13 @@ struct clk *clk_gate(const char *name, const char *parent, void __iomem *reg,
struct clk *clk_gate_inverted(const char *name, const char *parent,
void __iomem *reg, u8 shift, unsigned flags)
{
- return clk_gate(name, parent, reg, shift, flags, CLK_GATE_INVERTED);
+ return clk_gate(name, parent, reg, shift, flags, CLK_GATE_SET_TO_DISABLE);
+}
+
+struct clk *clk_register_gate(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+ void __iomem *reg, u8 bit_idx,
+ u8 clk_gate_flags, spinlock_t *lock)
+{
+ return clk_gate(name, parent_name, reg, bit_idx, flags, clk_gate_flags);
}
diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c
index 1345fbc9ea..940a20523e 100644
--- a/drivers/clk/clk-gpio.c
+++ b/drivers/clk/clk-gpio.c
@@ -14,30 +14,30 @@
#include <init.h>
struct clk_gpio {
- struct clk clk;
+ struct clk_hw hw;
const char *parent;
int gpio;
};
-#define to_clk_gpio(_clk) container_of(_clk, struct clk_gpio, clk)
+#define to_clk_gpio(_hw) container_of(_hw, struct clk_gpio, hw)
-static int clk_gpio_enable(struct clk *clk)
+static int clk_gpio_enable(struct clk_hw *hw)
{
- struct clk_gpio *clk_gpio = to_clk_gpio(clk);
+ struct clk_gpio *clk_gpio = to_clk_gpio(hw);
gpio_set_active(clk_gpio->gpio, true);
return 0;
}
-static void clk_gpio_disable(struct clk *clk)
+static void clk_gpio_disable(struct clk_hw *hw)
{
- struct clk_gpio *clk_gpio = to_clk_gpio(clk);
+ struct clk_gpio *clk_gpio = to_clk_gpio(hw);
gpio_set_active(clk_gpio->gpio, false);
}
-static int clk_gpio_is_enabled(struct clk *clk)
+static int clk_gpio_is_enabled(struct clk_hw *hw)
{
- struct clk_gpio *clk_gpio = to_clk_gpio(clk);
+ struct clk_gpio *clk_gpio = to_clk_gpio(hw);
return gpio_is_active(clk_gpio->gpio);
}
@@ -50,8 +50,9 @@ static struct clk_ops clk_gpio_ops = {
.is_enabled = clk_gpio_is_enabled,
};
-static int of_gpio_clk_setup(struct device_node *node)
+static int of_gpio_clk_probe(struct device *dev)
{
+ struct device_node *node = dev->device_node;
struct clk_gpio *clk_gpio;
enum of_gpio_flags of_flags;
unsigned long flags;
@@ -67,13 +68,13 @@ static int of_gpio_clk_setup(struct device_node *node)
goto no_parent;
}
- clk_gpio->clk.ops = &clk_gpio_ops;
- clk_gpio->clk.parent_names = &clk_gpio->parent;
- clk_gpio->clk.num_parents = 1;
+ clk_gpio->hw.clk.ops = &clk_gpio_ops;
+ clk_gpio->hw.clk.parent_names = &clk_gpio->parent;
+ clk_gpio->hw.clk.num_parents = 1;
- clk_gpio->clk.name = node->name;
+ clk_gpio->hw.clk.name = node->name;
of_property_read_string(node, "clock-output-names",
- &clk_gpio->clk.name);
+ &clk_gpio->hw.clk.name);
ret = of_get_named_gpio_flags(node, "enable-gpios", 0,
&of_flags);
@@ -86,15 +87,15 @@ static int of_gpio_clk_setup(struct device_node *node)
flags = GPIOF_OUT_INIT_ACTIVE;
if (of_flags & OF_GPIO_ACTIVE_LOW)
flags |= GPIOF_ACTIVE_LOW;
- ret = gpio_request_one(clk_gpio->gpio, flags, clk_gpio->clk.name);
+ ret = gpio_request_one(clk_gpio->gpio, flags, clk_gpio->hw.clk.name);
if (ret)
goto no_request;
- ret = clk_register(&clk_gpio->clk);
+ ret = bclk_register(&clk_gpio->hw.clk);
if (ret)
goto no_register;
- return of_clk_add_provider(node, of_clk_src_simple_get, &clk_gpio->clk);
+ return of_clk_add_provider(node, of_clk_src_simple_get, &clk_gpio->hw.clk);
no_register:
gpio_free(clk_gpio->gpio);
@@ -105,16 +106,16 @@ no_parent:
return ret;
}
-/* Can't use OF_CLK_DECLARE due to need to run after GPIOcontrollers have
- * registrered */
-
static const struct of_device_id clk_gpio_device_id[] = {
- { .compatible = "gpio-gate-clock", .data = of_gpio_clk_setup, },
+ { .compatible = "gpio-gate-clock", },
{}
};
+MODULE_DEVICE_TABLE(of, clk_gpio_device_id);
-static int clk_gpio_init(void)
-{
- return of_clk_init(NULL, clk_gpio_device_id);
-}
-coredevice_initcall(clk_gpio_init);
+static struct driver gpio_gate_clock_driver = {
+ .probe = of_gpio_clk_probe,
+ .name = "gpio-gate-clock",
+ .of_compatible = DRV_OF_COMPAT(clk_gpio_device_id),
+};
+
+core_platform_driver(gpio_gate_clock_driver);
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index a4743c51b0..1d94e09167 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -10,44 +10,153 @@
#include <linux/clk.h>
#include <linux/err.h>
-static int clk_mux_get_parent(struct clk *clk)
+int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
+ unsigned int val)
{
- struct clk_mux *m = container_of(clk, struct clk_mux, clk);
+ int num_parents = clk_hw_get_num_parents(hw);
+
+ if (table) {
+ int i;
+
+ for (i = 0; i < num_parents; i++)
+ if (table[i] == val)
+ return i;
+ return -EINVAL;
+ }
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(clk_mux_val_to_index);
+
+unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index)
+{
+ return table ? table[index] : index;
+}
+EXPORT_SYMBOL_GPL(clk_mux_index_to_val);
+
+static int clk_mux_get_parent(struct clk_hw *hw)
+{
+ struct clk_mux *m = to_clk_mux(hw);
int idx = readl(m->reg) >> m->shift & ((1 << m->width) - 1);
- return idx;
+ return clk_mux_val_to_index(hw, m->table, m->flags, idx);
}
-static int clk_mux_set_parent(struct clk *clk, u8 idx)
+static int clk_mux_set_parent(struct clk_hw *hw, u8 idx)
{
- struct clk_mux *m = container_of(clk, struct clk_mux, clk);
+ struct clk_mux *m = to_clk_mux(hw);
u32 val;
if (m->flags & CLK_MUX_READ_ONLY) {
- if (clk_mux_get_parent(clk) != idx)
+ if (clk_mux_get_parent(hw) != idx)
return -EPERM;
else
return 0;
}
+ idx = clk_mux_index_to_val(m->table, m->flags, idx);
+
val = readl(m->reg);
val &= ~(((1 << m->width) - 1) << m->shift);
val |= idx << m->shift;
- if (clk->flags & CLK_MUX_HIWORD_MASK)
+ if (m->flags & CLK_MUX_HIWORD_MASK)
val |= ((1 << m->width) - 1) << (m->shift + 16);
writel(val, m->reg);
return 0;
}
-struct clk_ops clk_mux_ops = {
- .set_rate = clk_parent_set_rate,
- .round_rate = clk_parent_round_rate,
+static struct clk *clk_get_parent_index(struct clk *clk, int num)
+{
+ if (num >= clk->num_parents)
+ return NULL;
+
+ if (clk->parents[num])
+ return clk->parents[num];
+
+ clk->parents[num] = clk_lookup(clk->parent_names[num]);
+
+ return clk->parents[num];
+}
+
+static struct clk *clk_mux_best_parent(struct clk *mux, unsigned long rate,
+ unsigned long *rrate)
+{
+ struct clk *bestparent = NULL;
+ long bestrate = LONG_MAX;
+ int i;
+
+ for (i = 0; i < mux->num_parents; i++) {
+ struct clk *parent = clk_get_parent_index(mux, i);
+ unsigned long r;
+
+ if (IS_ERR_OR_NULL(parent))
+ continue;
+
+ if (mux->flags & CLK_SET_RATE_PARENT)
+ r = clk_round_rate(parent, rate);
+ else
+ r = clk_get_rate(parent);
+
+ if (abs((long)rate - r) < abs((long)rate - bestrate)) {
+ bestrate = r;
+ bestparent = parent;
+ }
+ }
+
+ *rrate = bestrate;
+
+ return bestparent;
+}
+
+long clk_mux_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct clk *clk = clk_hw_to_clk(hw);
+ unsigned long rrate;
+ struct clk *bestparent;
+
+ if (clk->flags & CLK_SET_RATE_NO_REPARENT)
+ return clk_parent_round_rate(hw, rate, prate);
+
+ bestparent = clk_mux_best_parent(clk, rate, &rrate);
+
+ return rrate;
+}
+EXPORT_SYMBOL_GPL(clk_mux_round_rate);
+
+static int clk_mux_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk *clk = clk_hw_to_clk(hw);
+ struct clk *parent;
+ unsigned long rrate;
+ int ret;
+
+ if (clk->flags & CLK_SET_RATE_NO_REPARENT)
+ return clk_parent_set_rate(hw, rate, parent_rate);
+
+ parent = clk_mux_best_parent(clk, rate, &rrate);
+
+ ret = clk_set_parent(clk, parent);
+ if (ret)
+ return ret;
+
+ return clk_set_rate(parent, rate);
+}
+
+const struct clk_ops clk_mux_ops = {
+ .set_rate = clk_mux_set_rate,
+ .round_rate = clk_mux_round_rate,
.get_parent = clk_mux_get_parent,
.set_parent = clk_mux_set_parent,
};
+const struct clk_ops clk_mux_ro_ops = {
+ .get_parent = clk_mux_get_parent,
+};
+
struct clk *clk_mux_alloc(const char *name, unsigned clk_flags, void __iomem *reg,
u8 shift, u8 width, const char * const *parents, u8 num_parents,
unsigned mux_flags)
@@ -58,18 +167,19 @@ struct clk *clk_mux_alloc(const char *name, unsigned clk_flags, void __iomem *re
m->shift = shift;
m->width = width;
m->flags = mux_flags;
- m->clk.ops = &clk_mux_ops;
- m->clk.name = name;
- m->clk.flags = clk_flags;
- m->clk.parent_names = parents;
- m->clk.num_parents = num_parents;
+ m->hw.clk.ops = &clk_mux_ops;
+ m->hw.clk.name = name;
+ m->hw.clk.flags = clk_flags;
+ m->hw.clk.parent_names = parents;
+ m->hw.clk.num_parents = num_parents;
- return &m->clk;
+ return &m->hw.clk;
}
void clk_mux_free(struct clk *clk_mux)
{
- struct clk_mux *m = to_clk_mux(clk_mux);
+ struct clk_hw *hw = clk_to_clk_hw(clk_mux);
+ struct clk_mux *m = to_clk_mux(hw);
free(m);
}
@@ -84,11 +194,78 @@ struct clk *clk_mux(const char *name, unsigned clk_flags, void __iomem *reg,
m = clk_mux_alloc(name, clk_flags, reg, shift, width, parents,
num_parents, mux_flags);
- ret = clk_register(m);
+ ret = bclk_register(m);
if (ret) {
- free(to_clk_mux(m));
+ struct clk_hw *hw = clk_to_clk_hw(m);
+ free(to_clk_mux(hw));
return ERR_PTR(ret);
}
return m;
}
+
+struct clk *clk_register_mux(struct device *dev, const char *name,
+ const char * const *parent_names, u8 num_parents,
+ unsigned long flags,
+ void __iomem *reg, u8 shift, u8 width,
+ u8 clk_mux_flags, spinlock_t *lock)
+{
+ return clk_mux(name, flags, reg, shift, width, parent_names,
+ num_parents, clk_mux_flags);
+}
+
+struct clk_hw *__clk_hw_register_mux(struct device *dev,
+ const char *name, u8 num_parents,
+ const char * const *parent_names,
+ unsigned long flags, void __iomem *reg,
+ u8 shift, u32 mask,
+ u8 clk_mux_flags, u32 *table,
+ spinlock_t *lock)
+{
+ struct clk_mux *mux;
+ struct clk_hw *hw;
+ struct clk_init_data init = {};
+ u8 width = 0;
+ int ret = -EINVAL;
+
+ width = fls(mask) - ffs(mask) + 1;
+
+ if (clk_mux_flags & CLK_MUX_HIWORD_MASK) {
+ if (width + shift > 16) {
+ pr_err("mux value exceeds LOWORD field\n");
+ return ERR_PTR(-EINVAL);
+ }
+ }
+
+ /* allocate the mux */
+ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+ if (!mux)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ if (clk_mux_flags & CLK_MUX_READ_ONLY)
+ init.ops = &clk_mux_ro_ops;
+ else
+ init.ops = &clk_mux_ops;
+ init.flags = flags;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+
+ /* struct clk_mux assignments */
+ mux->reg = reg;
+ mux->shift = shift;
+ mux->width = width;
+ mux->flags = clk_mux_flags;
+ mux->lock = lock;
+ mux->table = table;
+ mux->hw.init = &init;
+
+ hw = &mux->hw;
+ ret = clk_hw_register(dev, hw);
+ if (ret) {
+ kfree(mux);
+ hw = ERR_PTR(ret);
+ }
+
+ return hw;
+}
diff --git a/drivers/clk/clk-qoric.c b/drivers/clk/clk-qoric.c
index 2ffc7613fa..44155692a8 100644
--- a/drivers/clk/clk-qoric.c
+++ b/drivers/clk/clk-qoric.c
@@ -13,7 +13,7 @@
#include <linux/kernel.h>
#include <of_address.h>
#include <of.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#define PLL_DIV1 0
#define PLL_DIV2 1
@@ -27,14 +27,15 @@
#define CGA_PLL4 4 /* only on clockgen-1.0, which lacks CGB */
#define CGB_PLL1 4
#define CGB_PLL2 5
+#define MAX_PLL_DIV 32
struct clockgen_pll_div {
- struct clk *clk;
+ struct clk_hw *hw;
char name[32];
};
struct clockgen_pll {
- struct clockgen_pll_div div[8];
+ struct clockgen_pll_div div[MAX_PLL_DIV];
};
#define CLKSEL_VALID 1
@@ -143,6 +144,58 @@ static const struct clockgen_muxinfo clockgen2_cmux_cgb = {
},
};
+static const struct clockgen_muxinfo ls1028a_hwa1 = {
+ {
+ { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+ {},
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+ },
+};
+
+static const struct clockgen_muxinfo ls1028a_hwa2 = {
+ {
+ { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
+ {},
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+ },
+};
+
+static const struct clockgen_muxinfo ls1028a_hwa3 = {
+ {
+ { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+ {},
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+ },
+};
+
+static const struct clockgen_muxinfo ls1028a_hwa4 = {
+ {
+ { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+ { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 },
+ {},
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+ },
+};
+
static const struct clockgen_muxinfo ls1043a_hwa1 = {
{
{},
@@ -203,6 +256,13 @@ static void __init t2080_init_periph(struct clockgen *cg)
cg->fman[0] = cg->hwaccel[0];
}
+static const struct clockgen_chipinfo chipinfo_ls1012a = {
+ .compat = "fsl,ls1012a-clockgen",
+ .cmux_groups = { &ls1012a_cmux },
+ .cmux_to_group = { 0, -1 },
+ .pll_mask = 0x03,
+};
+
static const struct clockgen_chipinfo chipinfo_ls1021a = {
.compat = "fsl,ls1021a-clockgen",
.cmux_groups = { &t1023_cmux },
@@ -210,6 +270,15 @@ static const struct clockgen_chipinfo chipinfo_ls1021a = {
.pll_mask = 0x03,
};
+static const struct clockgen_chipinfo chipinfo_ls1028a = {
+ .compat = "fsl,ls1028a-clockgen",
+ .cmux_groups = { &clockgen2_cmux_cga12 },
+ .hwaccel = { &ls1028a_hwa1, &ls1028a_hwa2, &ls1028a_hwa3, &ls1028a_hwa4 },
+ .cmux_to_group = { 0, 0, 0, 0, -1 },
+ .pll_mask = 0x07,
+ .flags = CG_VER3 | CG_LITTLE_ENDIAN,
+};
+
static const struct clockgen_chipinfo chipinfo_ls1043a = {
.compat = "fsl,ls1043a-clockgen",
.init_periph = t2080_init_periph,
@@ -238,13 +307,6 @@ static const struct clockgen_chipinfo chipinfo_ls1088a = {
.flags = CG_VER3 | CG_LITTLE_ENDIAN,
};
-static const struct clockgen_chipinfo chipinfo_ls1012a = {
- .compat = "fsl,ls1012a-clockgen",
- .cmux_groups = { &ls1012a_cmux },
- .cmux_to_group = { 0, -1 },
- .pll_mask = 0x03,
-};
-
static const struct clockgen_chipinfo chipinfo_ls2080a = {
.compat = "fsl,ls2080a-clockgen",
.cmux_groups = { &clockgen2_cmux_cga12, &clockgen2_cmux_cgb },
@@ -254,20 +316,20 @@ static const struct clockgen_chipinfo chipinfo_ls2080a = {
};
struct mux_hwclock {
- struct clk clk;
+ struct clk_hw hw;
struct clockgen *cg;
const struct clockgen_muxinfo *info;
u32 __iomem *reg;
int num_parents;
};
-#define to_mux_hwclock(p) container_of(p, struct mux_hwclock, clk)
+#define to_mux_hwclock(p) container_of(p, struct mux_hwclock, hw)
#define CLKSEL_MASK 0x78000000
#define CLKSEL_SHIFT 27
-static int mux_set_parent(struct clk *clk, u8 idx)
+static int mux_set_parent(struct clk_hw *hw, u8 idx)
{
- struct mux_hwclock *hwc = to_mux_hwclock(clk);
+ struct mux_hwclock *hwc = to_mux_hwclock(hw);
if (idx >= hwc->num_parents)
return -EINVAL;
@@ -277,9 +339,9 @@ static int mux_set_parent(struct clk *clk, u8 idx)
return 0;
}
-static int mux_get_parent(struct clk *clk)
+static int mux_get_parent(struct clk_hw *hw)
{
- struct mux_hwclock *hwc = to_mux_hwclock(clk);
+ struct mux_hwclock *hwc = to_mux_hwclock(hw);
return (cg_in(hwc->cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
}
@@ -318,7 +380,7 @@ static struct clk * __init create_mux_common(struct clockgen *cg,
const struct clk_ops *ops,
const char *fmt, int idx)
{
- struct clk *clk = &hwc->clk;
+ struct clk_hw *hw = &hwc->hw;
const struct clockgen_pll_div *div;
const char **parent_names;
int i, ret;
@@ -333,20 +395,20 @@ static struct clk * __init create_mux_common(struct clockgen *cg,
parent_names[i] = div->name;
}
- clk->name = xasprintf(fmt, idx);;
- clk->ops = ops;
- clk->parent_names = parent_names;
- clk->num_parents = hwc->num_parents = i;
+ hw->clk.name = xasprintf(fmt, idx);;
+ hw->clk.ops = ops;
+ hw->clk.parent_names = parent_names;
+ hw->clk.num_parents = hwc->num_parents = i;
hwc->cg = cg;
- ret = clk_register(clk);
+ ret = bclk_register(&hw->clk);
if (ret) {
- pr_err("%s: Couldn't register %s: %d\n", __func__, clk->name, ret);
+ pr_err("%s: Couldn't register %s: %d\n", __func__, clk_hw_get_name(hw), ret);
kfree(hwc);
return NULL;
}
- return clk;
+ return &hw->clk;
}
static struct clk * __init create_one_cmux(struct clockgen *cg, int idx)
@@ -499,7 +561,7 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
continue;
}
- pll->div[i].clk = clk;
+ pll->div[i].hw = clk_to_clk_hw(clk);
}
}
@@ -551,7 +613,7 @@ static struct clk *clockgen_clk_get(struct of_phandle_args *clkspec, void *data)
pll = &cg->pll[PLATFORM_PLL];
if (idx >= ARRAY_SIZE(pll->div))
goto bad_args;
- clk = pll->div[idx].clk;
+ clk = clk_hw_to_clk(pll->div[idx].hw);
break;
case 5:
if (idx != 0)
@@ -581,7 +643,7 @@ static void __init clockgen_init(struct device_node *np,
clockgen.node = np;
clockgen.regs = of_iomap(np, 0);
if (!clockgen.regs) {
- pr_err("of_iomap failed for %s\n", np->full_name);
+ pr_err("of_iomap failed for %pOF\n", np);
return;
}
@@ -589,10 +651,10 @@ static void __init clockgen_init(struct device_node *np,
clockgen.sysclk = of_clk_get(clockgen.node, 0);
if (IS_ERR(clockgen.sysclk)) {
- pr_err("sysclk not found: %s\n", strerrorp(clockgen.sysclk));
+ pr_err("sysclk not found: %pe\n", clockgen.sysclk);
return;
}
-
+
clockgen.coreclk = of_clk_get(clockgen.node, 1);
if (IS_ERR(clockgen.coreclk))
clockgen.coreclk = NULL;
@@ -605,8 +667,8 @@ static void __init clockgen_init(struct device_node *np,
ret = of_clk_add_provider(np, clockgen_clk_get, &clockgen);
if (ret) {
- pr_err("Couldn't register clk provider for node %s: %d\n",
- np->full_name, ret);
+ pr_err("Couldn't register clk provider for node %pOF: %d\n",
+ np, ret);
}
return;
@@ -622,6 +684,11 @@ static void __maybe_unused clockgen_init_ls1021a(struct device_node *np)
clockgen_init(np, &chipinfo_ls1021a);
}
+static void __maybe_unused clockgen_init_ls1028a(struct device_node *np)
+{
+ clockgen_init(np, &chipinfo_ls1028a);
+}
+
static void __maybe_unused clockgen_init_ls1043a(struct device_node *np)
{
clockgen_init(np, &chipinfo_ls1043a);
@@ -648,6 +715,9 @@ CLK_OF_DECLARE(qoriq_clockgen_ls1012a, "fsl,ls1012a-clockgen", clockgen_init_ls1
#ifdef CONFIG_ARCH_LS1021
CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init_ls1021a);
#endif
+#ifdef CONFIG_ARCH_LS1028
+CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1028a-clockgen", clockgen_init_ls1028a);
+#endif
#ifdef CONFIG_ARCH_LS1043
CLK_OF_DECLARE(qoriq_clockgen_ls1043a, "fsl,ls1043a-clockgen", clockgen_init_ls1043a);
#endif
diff --git a/drivers/clk/clk-rpi.c b/drivers/clk/clk-rpi.c
new file mode 100644
index 0000000000..d93d96a953
--- /dev/null
+++ b/drivers/clk/clk-rpi.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <linux/clk.h>
+#include <io.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+
+#include <mach/bcm283x/core.h>
+#include <mach/bcm283x/mbox.h>
+#include <mach/bcm283x/platform.h>
+#include <dt-bindings/clock/bcm2835.h>
+
+#define BCM2711_CLOCK_END (BCM2711_CLOCK_EMMC2 + 1)
+
+static struct clk *clks[BCM2711_CLOCK_END];
+static struct clk_onecell_data clk_data;
+
+struct msg_get_clock_rate {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_get_clock_rate get_clock_rate;
+ u32 end_tag;
+};
+
+static struct clk *rpi_register_firmware_clock(u32 clock_id, const char *name)
+{
+ BCM2835_MBOX_STACK_ALIGN(struct msg_get_clock_rate, msg);
+ int ret;
+
+ BCM2835_MBOX_INIT_HDR(msg);
+ BCM2835_MBOX_INIT_TAG(&msg->get_clock_rate, GET_CLOCK_RATE);
+ msg->get_clock_rate.body.req.clock_id = clock_id;
+
+ ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg->hdr);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return clk_fixed(name, msg->get_clock_rate.body.resp.rate_hz);
+}
+
+static int bcm2835_cprman_init(struct device *dev)
+{
+ struct clk *clk_cs;
+
+ clk_cs = clk_fixed("bcm2835-cs", 1 * 1000 * 1000);
+ clk_register_clkdev(clk_cs, NULL, "bcm2835-cs");
+
+ return 0;
+}
+
+static int rpi_cprman_probe(struct device *dev)
+{
+ int (*init)(struct device *dev);
+
+ init = device_get_match_data(dev);
+ if (init) {
+ int ret;
+
+ ret = init(dev);
+ if (ret)
+ return ret;
+ }
+
+ clks[BCM2835_CLOCK_EMMC] =
+ rpi_register_firmware_clock(BCM2835_MBOX_CLOCK_ID_EMMC,
+ "bcm2835_mci0");
+ if (IS_ERR(clks[BCM2835_CLOCK_EMMC]))
+ return PTR_ERR(clks[BCM2835_CLOCK_EMMC]);
+
+ clks[BCM2835_CLOCK_VPU] =
+ rpi_register_firmware_clock(BCM2835_MBOX_CLOCK_ID_CORE,
+ "vpu");
+ if (IS_ERR(clks[BCM2835_CLOCK_VPU]))
+ return PTR_ERR(clks[BCM2835_CLOCK_VPU]);
+
+ clks[BCM2711_CLOCK_EMMC2] =
+ rpi_register_firmware_clock(BCM2835_MBOX_CLOCK_ID_EMMC2,
+ "bcm2711_emmc2");
+ if (IS_ERR(clks[BCM2711_CLOCK_EMMC2]))
+ return PTR_ERR(clks[BCM2711_CLOCK_EMMC2]);
+
+ clks[BCM2835_CLOCK_UART] = clk_fixed("uart0-pl0110", 48 * 1000 * 1000);
+ clk_register_clkdev(clks[BCM2835_CLOCK_UART], NULL, "uart0-pl0110");
+
+ clk_data.clks = clks;
+ clk_data.clk_num = BCM2711_CLOCK_END;
+ of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, &clk_data);
+
+ return 0;
+}
+
+static __maybe_unused struct of_device_id bcm2835_cprman_dt_ids[] = {
+ { .compatible = "brcm,bcm2835-cprman", .data = bcm2835_cprman_init },
+ { .compatible = "brcm,bcm2711-cprman" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, bcm2835_cprman_dt_ids);
+
+static struct driver bcm2835_cprman_driver = {
+ .probe = rpi_cprman_probe,
+ .name = "raspberrypi-cprman",
+ .of_compatible = DRV_OF_COMPAT(bcm2835_cprman_dt_ids),
+};
+core_platform_driver(bcm2835_cprman_driver);
diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c
new file mode 100644
index 0000000000..5c9f61ae0b
--- /dev/null
+++ b/drivers/clk/clk-scmi.c
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * System Control and Power Interface (SCMI) Protocol based clock driver
+ *
+ * Copyright (C) 2018-2022 ARM Ltd.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <of.h>
+#include <module.h>
+#include <linux/scmi_protocol.h>
+#include <linux/math64.h>
+
+static const struct scmi_clk_proto_ops *scmi_proto_clk_ops;
+
+struct scmi_clk {
+ u32 id;
+ struct clk_hw hw;
+ const struct scmi_clock_info *info;
+ const struct scmi_protocol_handle *ph;
+};
+
+#define to_scmi_clk(clk) container_of(clk, struct scmi_clk, hw)
+
+static unsigned long scmi_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ int ret;
+ u64 rate;
+ struct scmi_clk *clk = to_scmi_clk(hw);
+
+ ret = scmi_proto_clk_ops->rate_get(clk->ph, clk->id, &rate);
+ if (ret)
+ return 0;
+ return rate;
+}
+
+static long scmi_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ u64 fmin, fmax, ftmp;
+ struct scmi_clk *clk = to_scmi_clk(hw);
+
+ /*
+ * We can't figure out what rate it will be, so just return the
+ * rate back to the caller. scmi_clk_recalc_rate() will be called
+ * after the rate is set and we'll know what rate the clock is
+ * running at then.
+ */
+ if (clk->info->rate_discrete)
+ return rate;
+
+ fmin = clk->info->range.min_rate;
+ fmax = clk->info->range.max_rate;
+ if (rate <= fmin)
+ return fmin;
+ else if (rate >= fmax)
+ return fmax;
+
+ ftmp = rate - fmin;
+ ftmp += clk->info->range.step_size - 1; /* to round up */
+ do_div(ftmp, clk->info->range.step_size);
+
+ return ftmp * clk->info->range.step_size + fmin;
+}
+
+static int scmi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct scmi_clk *clk = to_scmi_clk(hw);
+
+ return scmi_proto_clk_ops->rate_set(clk->ph, clk->id, rate);
+}
+
+static int scmi_clk_enable(struct clk_hw *hw)
+{
+ struct scmi_clk *clk = to_scmi_clk(hw);
+
+ return scmi_proto_clk_ops->enable(clk->ph, clk->id);
+}
+
+static void scmi_clk_disable(struct clk_hw *hw)
+{
+ struct scmi_clk *clk = to_scmi_clk(hw);
+
+ scmi_proto_clk_ops->disable(clk->ph, clk->id);
+}
+
+static int scmi_clk_atomic_enable(struct clk_hw *hw)
+{
+ struct scmi_clk *clk = to_scmi_clk(hw);
+
+ return scmi_proto_clk_ops->enable_atomic(clk->ph, clk->id);
+}
+
+static void scmi_clk_atomic_disable(struct clk_hw *hw)
+{
+ struct scmi_clk *clk = to_scmi_clk(hw);
+
+ scmi_proto_clk_ops->disable_atomic(clk->ph, clk->id);
+}
+
+/*
+ * We can provide enable/disable atomic callbacks only if the underlying SCMI
+ * transport for an SCMI instance is configured to handle SCMI commands in an
+ * atomic manner.
+ *
+ * When no SCMI atomic transport support is available we instead provide only
+ * the prepare/unprepare API, as allowed by the clock framework when atomic
+ * calls are not available.
+ *
+ * Two distinct sets of clk_ops are provided since we could have multiple SCMI
+ * instances with different underlying transport quality, so they cannot be
+ * shared.
+ */
+static const struct clk_ops scmi_clk_ops = {
+ .recalc_rate = scmi_clk_recalc_rate,
+ .round_rate = scmi_clk_round_rate,
+ .set_rate = scmi_clk_set_rate,
+ .enable = scmi_clk_enable,
+ .disable = scmi_clk_disable,
+};
+
+static const struct clk_ops scmi_atomic_clk_ops = {
+ .recalc_rate = scmi_clk_recalc_rate,
+ .round_rate = scmi_clk_round_rate,
+ .set_rate = scmi_clk_set_rate,
+ .enable = scmi_clk_atomic_enable,
+ .disable = scmi_clk_atomic_disable,
+};
+
+static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk,
+ const struct clk_ops *scmi_ops)
+{
+ struct clk_init_data init = {
+ .flags = CLK_GET_RATE_NOCACHE,
+
+ .num_parents = 0,
+ .ops = scmi_ops,
+ .name = sclk->info->name,
+ };
+
+ sclk->hw.init = &init;
+ return clk_hw_register(dev, &sclk->hw);
+}
+
+static int scmi_clocks_probe(struct scmi_device *sdev)
+{
+ int idx, count, err;
+ unsigned int atomic_threshold;
+ bool is_atomic;
+ struct clk_hw **hws;
+ struct clk_hw_onecell_data *clk_data;
+ struct device *dev = &sdev->dev;
+ struct device_node *np = dev->of_node;
+ const struct scmi_handle *handle = sdev->handle;
+ struct scmi_protocol_handle *ph;
+
+ if (!handle)
+ return -ENODEV;
+
+ scmi_proto_clk_ops =
+ handle->dev_protocol_get(sdev, SCMI_PROTOCOL_CLOCK, &ph);
+ if (IS_ERR(scmi_proto_clk_ops))
+ return PTR_ERR(scmi_proto_clk_ops);
+
+ count = scmi_proto_clk_ops->count_get(ph);
+ if (count < 0) {
+ dev_err(dev, "%pOFn: invalid clock output count\n", np);
+ return -EINVAL;
+ }
+
+ clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, count),
+ GFP_KERNEL);
+ if (!clk_data)
+ return -ENOMEM;
+
+ clk_data->num = count;
+ hws = clk_data->hws;
+
+ is_atomic = handle->is_transport_atomic(handle, &atomic_threshold);
+
+ for (idx = 0; idx < count; idx++) {
+ struct scmi_clk *sclk;
+ const struct clk_ops *scmi_ops;
+
+ sclk = devm_kzalloc(dev, sizeof(*sclk), GFP_KERNEL);
+ if (!sclk)
+ return -ENOMEM;
+
+ sclk->info = scmi_proto_clk_ops->info_get(ph, idx);
+ if (!sclk->info) {
+ dev_dbg(dev, "invalid clock info for idx %d\n", idx);
+ continue;
+ }
+
+ sclk->id = idx;
+ sclk->ph = ph;
+
+ /*
+ * Note that when transport is atomic but SCMI protocol did not
+ * specify (or support) an enable_latency associated with a
+ * clock, we default to use atomic operations mode.
+ */
+ if (is_atomic &&
+ sclk->info->enable_latency <= atomic_threshold)
+ scmi_ops = &scmi_atomic_clk_ops;
+ else
+ scmi_ops = &scmi_clk_ops;
+
+ err = scmi_clk_ops_init(dev, sclk, scmi_ops);
+ if (err) {
+ dev_err(dev, "failed to register clock %d\n", idx);
+ devm_kfree(dev, sclk);
+ hws[idx] = NULL;
+ } else {
+ dev_dbg(dev, "Registered clock:%s%s\n",
+ sclk->info->name,
+ scmi_ops == &scmi_atomic_clk_ops ?
+ " (atomic ops)" : "");
+ hws[idx] = &sclk->hw;
+ }
+ }
+
+ return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
+}
+
+static const struct scmi_device_id scmi_id_table[] = {
+ { SCMI_PROTOCOL_CLOCK, "clocks" },
+ { },
+};
+MODULE_DEVICE_TABLE(scmi, scmi_id_table);
+
+static struct scmi_driver scmi_clocks_driver = {
+ .name = "scmi-clocks",
+ .probe = scmi_clocks_probe,
+ .id_table = scmi_id_table,
+};
+core_scmi_driver(scmi_clocks_driver);
+
+MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
+MODULE_DESCRIPTION("ARM SCMI clock driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c
new file mode 100644
index 0000000000..d6ccfa6d15
--- /dev/null
+++ b/drivers/clk/clk-stm32f4.c
@@ -0,0 +1,1907 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Author: Daniel Thompson <daniel.thompson@linaro.org>
+ *
+ * Inspired by clk-asm9260.c .
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <io.h>
+#include <of.h>
+#include <of_address.h>
+#include <linux/math64.h>
+#include <linux/iopoll.h>
+#include <linux/regmap.h>
+#include <mfd/syscon.h>
+
+/*
+ * Include list of clocks wich are not derived from system clock (SYSCLOCK)
+ * The index of these clocks is the secondary index of DT bindings
+ *
+ */
+#include <dt-bindings/clock/stm32fx-clock.h>
+
+#define STM32F4_RCC_CR 0x00
+#define STM32F4_RCC_PLLCFGR 0x04
+#define STM32F4_RCC_CFGR 0x08
+#define STM32F4_RCC_AHB1ENR 0x30
+#define STM32F4_RCC_AHB2ENR 0x34
+#define STM32F4_RCC_AHB3ENR 0x38
+#define STM32F4_RCC_APB1ENR 0x40
+#define STM32F4_RCC_APB2ENR 0x44
+#define STM32F4_RCC_BDCR 0x70
+#define STM32F4_RCC_CSR 0x74
+#define STM32F4_RCC_PLLI2SCFGR 0x84
+#define STM32F4_RCC_PLLSAICFGR 0x88
+#define STM32F4_RCC_DCKCFGR 0x8c
+#define STM32F7_RCC_DCKCFGR2 0x90
+
+#define NONE -1
+#define NO_IDX NONE
+#define NO_MUX NONE
+#define NO_GATE NONE
+
+struct stm32f4_gate_data {
+ u8 offset;
+ u8 bit_idx;
+ const char *name;
+ const char *parent_name;
+ unsigned long flags;
+};
+
+static const struct stm32f4_gate_data stm32f429_gates[] __initconst = {
+ { STM32F4_RCC_AHB1ENR, 0, "gpioa", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 1, "gpiob", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 2, "gpioc", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 3, "gpiod", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 4, "gpioe", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 5, "gpiof", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 6, "gpiog", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 7, "gpioh", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 8, "gpioi", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 9, "gpioj", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 10, "gpiok", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 12, "crc", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 18, "bkpsra", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 20, "ccmdatam", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 21, "dma1", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 22, "dma2", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 23, "dma2d", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 25, "ethmac", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 26, "ethmactx", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 27, "ethmacrx", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 28, "ethmacptp", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 29, "otghs", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 30, "otghsulpi", "ahb_div" },
+
+ { STM32F4_RCC_AHB2ENR, 0, "dcmi", "ahb_div" },
+ { STM32F4_RCC_AHB2ENR, 4, "cryp", "ahb_div" },
+ { STM32F4_RCC_AHB2ENR, 5, "hash", "ahb_div" },
+ { STM32F4_RCC_AHB2ENR, 6, "rng", "pll48" },
+ { STM32F4_RCC_AHB2ENR, 7, "otgfs", "pll48" },
+
+ { STM32F4_RCC_AHB3ENR, 0, "fmc", "ahb_div",
+ CLK_IGNORE_UNUSED },
+
+ { STM32F4_RCC_APB1ENR, 0, "tim2", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 1, "tim3", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 2, "tim4", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 3, "tim5", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 4, "tim6", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 5, "tim7", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 6, "tim12", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 7, "tim13", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 8, "tim14", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 11, "wwdg", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 14, "spi2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 15, "spi3", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 17, "uart2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 18, "uart3", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 19, "uart4", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 20, "uart5", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 21, "i2c1", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 22, "i2c2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 23, "i2c3", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 25, "can1", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 26, "can2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 28, "pwr", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 29, "dac", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 30, "uart7", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 31, "uart8", "apb1_div" },
+
+ { STM32F4_RCC_APB2ENR, 0, "tim1", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 1, "tim8", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 4, "usart1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 5, "usart6", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 8, "adc1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 9, "adc2", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 10, "adc3", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 11, "sdio", "pll48" },
+ { STM32F4_RCC_APB2ENR, 12, "spi1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 13, "spi4", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 14, "syscfg", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 16, "tim9", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 17, "tim10", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 18, "tim11", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
+};
+
+static const struct stm32f4_gate_data stm32f469_gates[] __initconst = {
+ { STM32F4_RCC_AHB1ENR, 0, "gpioa", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 1, "gpiob", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 2, "gpioc", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 3, "gpiod", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 4, "gpioe", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 5, "gpiof", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 6, "gpiog", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 7, "gpioh", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 8, "gpioi", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 9, "gpioj", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 10, "gpiok", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 12, "crc", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 18, "bkpsra", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 20, "ccmdatam", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 21, "dma1", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 22, "dma2", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 23, "dma2d", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 25, "ethmac", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 26, "ethmactx", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 27, "ethmacrx", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 28, "ethmacptp", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 29, "otghs", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 30, "otghsulpi", "ahb_div" },
+
+ { STM32F4_RCC_AHB2ENR, 0, "dcmi", "ahb_div" },
+ { STM32F4_RCC_AHB2ENR, 4, "cryp", "ahb_div" },
+ { STM32F4_RCC_AHB2ENR, 5, "hash", "ahb_div" },
+ { STM32F4_RCC_AHB2ENR, 6, "rng", "pll48" },
+ { STM32F4_RCC_AHB2ENR, 7, "otgfs", "pll48" },
+
+ { STM32F4_RCC_AHB3ENR, 0, "fmc", "ahb_div",
+ CLK_IGNORE_UNUSED },
+ { STM32F4_RCC_AHB3ENR, 1, "qspi", "ahb_div",
+ CLK_IGNORE_UNUSED },
+
+ { STM32F4_RCC_APB1ENR, 0, "tim2", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 1, "tim3", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 2, "tim4", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 3, "tim5", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 4, "tim6", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 5, "tim7", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 6, "tim12", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 7, "tim13", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 8, "tim14", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 11, "wwdg", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 14, "spi2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 15, "spi3", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 17, "uart2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 18, "uart3", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 19, "uart4", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 20, "uart5", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 21, "i2c1", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 22, "i2c2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 23, "i2c3", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 25, "can1", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 26, "can2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 28, "pwr", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 29, "dac", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 30, "uart7", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 31, "uart8", "apb1_div" },
+
+ { STM32F4_RCC_APB2ENR, 0, "tim1", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 1, "tim8", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 4, "usart1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 5, "usart6", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 8, "adc1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 9, "adc2", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 10, "adc3", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 11, "sdio", "sdmux" },
+ { STM32F4_RCC_APB2ENR, 12, "spi1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 13, "spi4", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 14, "syscfg", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 16, "tim9", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 17, "tim10", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 18, "tim11", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
+};
+
+static const struct stm32f4_gate_data stm32f746_gates[] __initconst = {
+ { STM32F4_RCC_AHB1ENR, 0, "gpioa", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 1, "gpiob", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 2, "gpioc", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 3, "gpiod", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 4, "gpioe", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 5, "gpiof", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 6, "gpiog", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 7, "gpioh", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 8, "gpioi", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 9, "gpioj", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 10, "gpiok", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 12, "crc", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 18, "bkpsra", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 20, "dtcmram", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 21, "dma1", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 22, "dma2", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 23, "dma2d", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 25, "ethmac", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 26, "ethmactx", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 27, "ethmacrx", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 28, "ethmacptp", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 29, "otghs", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 30, "otghsulpi", "ahb_div" },
+
+ { STM32F4_RCC_AHB2ENR, 0, "dcmi", "ahb_div" },
+ { STM32F4_RCC_AHB2ENR, 4, "cryp", "ahb_div" },
+ { STM32F4_RCC_AHB2ENR, 5, "hash", "ahb_div" },
+ { STM32F4_RCC_AHB2ENR, 6, "rng", "pll48" },
+ { STM32F4_RCC_AHB2ENR, 7, "otgfs", "pll48" },
+
+ { STM32F4_RCC_AHB3ENR, 0, "fmc", "ahb_div",
+ CLK_IGNORE_UNUSED },
+ { STM32F4_RCC_AHB3ENR, 1, "qspi", "ahb_div",
+ CLK_IGNORE_UNUSED },
+
+ { STM32F4_RCC_APB1ENR, 0, "tim2", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 1, "tim3", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 2, "tim4", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 3, "tim5", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 4, "tim6", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 5, "tim7", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 6, "tim12", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 7, "tim13", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 8, "tim14", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 11, "wwdg", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 14, "spi2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 15, "spi3", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 16, "spdifrx", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 25, "can1", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 26, "can2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 27, "cec", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 28, "pwr", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 29, "dac", "apb1_div" },
+
+ { STM32F4_RCC_APB2ENR, 0, "tim1", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 1, "tim8", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 7, "sdmmc2", "sdmux" },
+ { STM32F4_RCC_APB2ENR, 8, "adc1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 9, "adc2", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 10, "adc3", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 11, "sdmmc", "sdmux" },
+ { STM32F4_RCC_APB2ENR, 12, "spi1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 13, "spi4", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 14, "syscfg", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 16, "tim9", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 17, "tim10", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 18, "tim11", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 23, "sai2", "apb2_div" },
+};
+
+static const struct stm32f4_gate_data stm32f769_gates[] __initconst = {
+ { STM32F4_RCC_AHB1ENR, 0, "gpioa", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 1, "gpiob", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 2, "gpioc", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 3, "gpiod", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 4, "gpioe", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 5, "gpiof", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 6, "gpiog", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 7, "gpioh", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 8, "gpioi", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 9, "gpioj", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 10, "gpiok", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 12, "crc", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 18, "bkpsra", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 20, "dtcmram", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 21, "dma1", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 22, "dma2", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 23, "dma2d", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 25, "ethmac", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 26, "ethmactx", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 27, "ethmacrx", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 28, "ethmacptp", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 29, "otghs", "ahb_div" },
+ { STM32F4_RCC_AHB1ENR, 30, "otghsulpi", "ahb_div" },
+
+ { STM32F4_RCC_AHB2ENR, 0, "dcmi", "ahb_div" },
+ { STM32F4_RCC_AHB2ENR, 1, "jpeg", "ahb_div" },
+ { STM32F4_RCC_AHB2ENR, 4, "cryp", "ahb_div" },
+ { STM32F4_RCC_AHB2ENR, 5, "hash", "ahb_div" },
+ { STM32F4_RCC_AHB2ENR, 6, "rng", "pll48" },
+ { STM32F4_RCC_AHB2ENR, 7, "otgfs", "pll48" },
+
+ { STM32F4_RCC_AHB3ENR, 0, "fmc", "ahb_div",
+ CLK_IGNORE_UNUSED },
+ { STM32F4_RCC_AHB3ENR, 1, "qspi", "ahb_div",
+ CLK_IGNORE_UNUSED },
+
+ { STM32F4_RCC_APB1ENR, 0, "tim2", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 1, "tim3", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 2, "tim4", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 3, "tim5", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 4, "tim6", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 5, "tim7", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 6, "tim12", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 7, "tim13", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 8, "tim14", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 10, "rtcapb", "apb1_mul" },
+ { STM32F4_RCC_APB1ENR, 11, "wwdg", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 13, "can3", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 14, "spi2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 15, "spi3", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 16, "spdifrx", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 25, "can1", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 26, "can2", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 27, "cec", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 28, "pwr", "apb1_div" },
+ { STM32F4_RCC_APB1ENR, 29, "dac", "apb1_div" },
+
+ { STM32F4_RCC_APB2ENR, 0, "tim1", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 1, "tim8", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 7, "sdmmc2", "sdmux2" },
+ { STM32F4_RCC_APB2ENR, 8, "adc1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 9, "adc2", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 10, "adc3", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 11, "sdmmc1", "sdmux1" },
+ { STM32F4_RCC_APB2ENR, 12, "spi1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 13, "spi4", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 14, "syscfg", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 16, "tim9", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 17, "tim10", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 18, "tim11", "apb2_mul" },
+ { STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 23, "sai2", "apb2_div" },
+ { STM32F4_RCC_APB2ENR, 30, "mdio", "apb2_div" },
+};
+
+/*
+ * This bitmask tells us which bit offsets (0..192) on STM32F4[23]xxx
+ * have gate bits associated with them. Its combined hweight is 71.
+ */
+#define MAX_GATE_MAP 3
+
+static const u64 stm32f42xx_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
+ 0x0000000000000001ull,
+ 0x04777f33f6fec9ffull };
+
+static const u64 stm32f46xx_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
+ 0x0000000000000003ull,
+ 0x0c777f33f6fec9ffull };
+
+static const u64 stm32f746_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
+ 0x0000000000000003ull,
+ 0x04f77f833e01c9ffull };
+
+static const u64 stm32f769_gate_map[MAX_GATE_MAP] = { 0x000000f37ef417ffull,
+ 0x0000000000000003ull,
+ 0x44F77F833E01EDFFull };
+
+static const u64 *stm32f4_gate_map;
+
+static struct clk_hw **clks;
+
+static DEFINE_SPINLOCK(stm32f4_clk_lock);
+static void __iomem *base;
+
+static struct regmap *pdrm;
+
+static int stm32fx_end_primary_clk;
+
+/*
+ * "Multiplier" device for APBx clocks.
+ *
+ * The APBx dividers are power-of-two dividers and, if *not* running in 1:1
+ * mode, they also tap out the one of the low order state bits to run the
+ * timers. ST datasheets represent this feature as a (conditional) clock
+ * multiplier.
+ */
+struct clk_apb_mul {
+ struct clk_hw hw;
+ u8 bit_idx;
+};
+
+#define to_clk_apb_mul(_hw) container_of(_hw, struct clk_apb_mul, hw)
+
+static unsigned long clk_apb_mul_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_apb_mul *am = to_clk_apb_mul(hw);
+
+ if (readl(base + STM32F4_RCC_CFGR) & BIT(am->bit_idx))
+ return parent_rate * 2;
+
+ return parent_rate;
+}
+
+static long clk_apb_mul_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct clk_apb_mul *am = to_clk_apb_mul(hw);
+ unsigned long mult = 1;
+
+ if (readl(base + STM32F4_RCC_CFGR) & BIT(am->bit_idx))
+ mult = 2;
+
+ if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
+ unsigned long best_parent = rate / mult;
+
+ *prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
+ }
+
+ return *prate * mult;
+}
+
+static int clk_apb_mul_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ /*
+ * We must report success but we can do so unconditionally because
+ * clk_apb_mul_round_rate returns values that ensure this call is a
+ * nop.
+ */
+
+ return 0;
+}
+
+static const struct clk_ops clk_apb_mul_factor_ops = {
+ .round_rate = clk_apb_mul_round_rate,
+ .set_rate = clk_apb_mul_set_rate,
+ .recalc_rate = clk_apb_mul_recalc_rate,
+};
+
+static struct clk *clk_register_apb_mul(struct device *dev, const char *name,
+ const char *parent_name,
+ unsigned long flags, u8 bit_idx)
+{
+ struct clk_apb_mul *am;
+ struct clk_init_data init;
+ struct clk *clk;
+
+ am = kzalloc(sizeof(*am), GFP_KERNEL);
+ if (!am)
+ return ERR_PTR(-ENOMEM);
+
+ am->bit_idx = bit_idx;
+ am->hw.init = &init;
+
+ init.name = name;
+ init.ops = &clk_apb_mul_factor_ops;
+ init.flags = flags;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ clk = clk_register(dev, &am->hw);
+
+ if (IS_ERR(clk))
+ kfree(am);
+
+ return clk;
+}
+
+enum {
+ PLL,
+ PLL_I2S,
+ PLL_SAI,
+};
+
+static const struct clk_div_table pll_divp_table[] = {
+ { 0, 2 }, { 1, 4 }, { 2, 6 }, { 3, 8 }, { 0 }
+};
+
+static const struct clk_div_table pll_divq_table[] = {
+ { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 }, { 7, 7 },
+ { 8, 8 }, { 9, 9 }, { 10, 10 }, { 11, 11 }, { 12, 12 }, { 13, 13 },
+ { 14, 14 }, { 15, 15 },
+ { 0 }
+};
+
+static const struct clk_div_table pll_divr_table[] = {
+ { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 }, { 7, 7 }, { 0 }
+};
+
+struct stm32f4_pll {
+ spinlock_t *lock;
+ struct clk_gate gate;
+ u8 offset;
+ u8 bit_rdy_idx;
+ u8 status;
+ u8 n_start;
+};
+
+#define to_stm32f4_pll(_gate) container_of(_gate, struct stm32f4_pll, gate)
+
+struct stm32f4_pll_post_div_data {
+ int idx;
+ int pll_idx;
+ const char *name;
+ const char *parent;
+ u8 flag;
+ u8 offset;
+ u8 shift;
+ u8 width;
+ u8 flag_div;
+ const struct clk_div_table *div_table;
+};
+
+struct stm32f4_vco_data {
+ const char *vco_name;
+ u8 offset;
+ u8 bit_idx;
+ u8 bit_rdy_idx;
+};
+
+static const struct stm32f4_vco_data vco_data[] = {
+ { "vco", STM32F4_RCC_PLLCFGR, 24, 25 },
+ { "vco-i2s", STM32F4_RCC_PLLI2SCFGR, 26, 27 },
+ { "vco-sai", STM32F4_RCC_PLLSAICFGR, 28, 29 },
+};
+
+
+static const struct clk_div_table post_divr_table[] = {
+ { 0, 2 }, { 1, 4 }, { 2, 8 }, { 3, 16 }, { 0 }
+};
+
+#define MAX_POST_DIV 3
+static const struct stm32f4_pll_post_div_data post_div_data[MAX_POST_DIV] = {
+ { CLK_I2SQ_PDIV, PLL_VCO_I2S, "plli2s-q-div", "plli2s-q",
+ CLK_SET_RATE_PARENT, STM32F4_RCC_DCKCFGR, 0, 5, 0, NULL},
+
+ { CLK_SAIQ_PDIV, PLL_VCO_SAI, "pllsai-q-div", "pllsai-q",
+ CLK_SET_RATE_PARENT, STM32F4_RCC_DCKCFGR, 8, 5, 0, NULL },
+
+ { NO_IDX, PLL_VCO_SAI, "pllsai-r-div", "pllsai-r", CLK_SET_RATE_PARENT,
+ STM32F4_RCC_DCKCFGR, 16, 2, 0, post_divr_table },
+};
+
+struct stm32f4_div_data {
+ u8 shift;
+ u8 width;
+ u8 flag_div;
+ const struct clk_div_table *div_table;
+};
+
+#define MAX_PLL_DIV 3
+static const struct stm32f4_div_data div_data[MAX_PLL_DIV] = {
+ { 16, 2, 0, pll_divp_table },
+ { 24, 4, 0, pll_divq_table },
+ { 28, 3, 0, pll_divr_table },
+};
+
+struct stm32f4_pll_data {
+ u8 pll_num;
+ u8 n_start;
+ const char *div_name[MAX_PLL_DIV];
+};
+
+static const struct stm32f4_pll_data stm32f429_pll[MAX_PLL_DIV] = {
+ { PLL, 192, { "pll", "pll48", NULL } },
+ { PLL_I2S, 192, { NULL, "plli2s-q", "plli2s-r" } },
+ { PLL_SAI, 49, { NULL, "pllsai-q", "pllsai-r" } },
+};
+
+static const struct stm32f4_pll_data stm32f469_pll[MAX_PLL_DIV] = {
+ { PLL, 50, { "pll", "pll-q", "pll-r" } },
+ { PLL_I2S, 50, { "plli2s-p", "plli2s-q", "plli2s-r" } },
+ { PLL_SAI, 50, { "pllsai-p", "pllsai-q", "pllsai-r" } },
+};
+
+static int stm32f4_pll_is_enabled(struct clk_hw *hw)
+{
+ return clk_gate_ops.is_enabled(hw);
+}
+
+#define PLL_TIMEOUT 10000
+
+static int stm32f4_pll_enable(struct clk_hw *hw)
+{
+ struct clk_gate *gate = to_clk_gate(hw);
+ struct stm32f4_pll *pll = to_stm32f4_pll(gate);
+ int bit_status;
+ unsigned int timeout = PLL_TIMEOUT;
+
+ if (clk_gate_ops.is_enabled(hw))
+ return 0;
+
+ clk_gate_ops.enable(hw);
+
+ do {
+ bit_status = !(readl(gate->reg) & BIT(pll->bit_rdy_idx));
+
+ } while (bit_status && --timeout);
+
+ return bit_status;
+}
+
+static void stm32f4_pll_disable(struct clk_hw *hw)
+{
+ clk_gate_ops.disable(hw);
+}
+
+static unsigned long stm32f4_pll_recalc(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_gate *gate = to_clk_gate(hw);
+ struct stm32f4_pll *pll = to_stm32f4_pll(gate);
+ unsigned long n;
+
+ n = (readl(base + pll->offset) >> 6) & 0x1ff;
+
+ return parent_rate * n;
+}
+
+static long stm32f4_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct clk_gate *gate = to_clk_gate(hw);
+ struct stm32f4_pll *pll = to_stm32f4_pll(gate);
+ unsigned long n;
+
+ n = rate / *prate;
+
+ if (n < pll->n_start)
+ n = pll->n_start;
+ else if (n > 432)
+ n = 432;
+
+ return *prate * n;
+}
+
+static int stm32f4_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_gate *gate = to_clk_gate(hw);
+ struct stm32f4_pll *pll = to_stm32f4_pll(gate);
+
+ unsigned long n;
+ unsigned long val;
+ int pll_state;
+
+ pll_state = stm32f4_pll_is_enabled(hw);
+
+ if (pll_state)
+ stm32f4_pll_disable(hw);
+
+ n = rate / parent_rate;
+
+ val = readl(base + pll->offset) & ~(0x1ff << 6);
+
+ writel(val | ((n & 0x1ff) << 6), base + pll->offset);
+
+ if (pll_state)
+ stm32f4_pll_enable(hw);
+
+ return 0;
+}
+
+static const struct clk_ops stm32f4_pll_gate_ops = {
+ .enable = stm32f4_pll_enable,
+ .disable = stm32f4_pll_disable,
+ .is_enabled = stm32f4_pll_is_enabled,
+ .recalc_rate = stm32f4_pll_recalc,
+ .round_rate = stm32f4_pll_round_rate,
+ .set_rate = stm32f4_pll_set_rate,
+};
+
+struct stm32f4_pll_div {
+ struct clk_divider div;
+ struct clk_hw *hw_pll;
+};
+
+#define to_pll_div_clk(_div) container_of(_div, struct stm32f4_pll_div, div)
+
+static unsigned long stm32f4_pll_div_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return clk_divider_ops.recalc_rate(hw, parent_rate);
+}
+
+static long stm32f4_pll_div_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ return clk_divider_ops.round_rate(hw, rate, prate);
+}
+
+static int stm32f4_pll_div_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ int pll_state, ret;
+
+ struct clk_divider *div = to_clk_divider(hw);
+ struct stm32f4_pll_div *pll_div = to_pll_div_clk(div);
+
+ pll_state = stm32f4_pll_is_enabled(pll_div->hw_pll);
+
+ if (pll_state)
+ stm32f4_pll_disable(pll_div->hw_pll);
+
+ ret = clk_divider_ops.set_rate(hw, rate, parent_rate);
+
+ if (pll_state)
+ stm32f4_pll_enable(pll_div->hw_pll);
+
+ return ret;
+}
+
+static const struct clk_ops stm32f4_pll_div_ops = {
+ .recalc_rate = stm32f4_pll_div_recalc_rate,
+ .round_rate = stm32f4_pll_div_round_rate,
+ .set_rate = stm32f4_pll_div_set_rate,
+};
+
+static struct clk_hw *clk_register_pll_div(const char *name,
+ const char *parent_name, unsigned long flags,
+ void __iomem *reg, u8 shift, u8 width,
+ u8 clk_divider_flags, const struct clk_div_table *table,
+ struct clk_hw *pll_hw, spinlock_t *lock)
+{
+ struct stm32f4_pll_div *pll_div;
+ struct clk_hw *hw;
+ struct clk_init_data init;
+ int ret;
+
+ /* allocate the divider */
+ pll_div = kzalloc(sizeof(*pll_div), GFP_KERNEL);
+ if (!pll_div)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &stm32f4_pll_div_ops;
+ init.flags = flags;
+ init.parent_names = (parent_name ? &parent_name : NULL);
+ init.num_parents = (parent_name ? 1 : 0);
+
+ /* struct clk_divider assignments */
+ pll_div->div.reg = reg;
+ pll_div->div.shift = shift;
+ pll_div->div.width = width;
+ pll_div->div.flags = clk_divider_flags;
+ pll_div->div.lock = lock;
+ pll_div->div.table = table;
+ pll_div->div.hw.init = &init;
+
+ pll_div->hw_pll = pll_hw;
+
+ /* register the clock */
+ hw = &pll_div->div.hw;
+ ret = clk_hw_register(NULL, hw);
+ if (ret) {
+ kfree(pll_div);
+ hw = ERR_PTR(ret);
+ }
+
+ return hw;
+}
+
+static struct clk_hw *stm32f4_rcc_register_pll(const char *pllsrc,
+ const struct stm32f4_pll_data *data, spinlock_t *lock)
+{
+ struct stm32f4_pll *pll;
+ struct clk_init_data init = { NULL };
+ void __iomem *reg;
+ struct clk_hw *pll_hw;
+ int ret;
+ int i;
+ const struct stm32f4_vco_data *vco;
+
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll)
+ return ERR_PTR(-ENOMEM);
+
+ vco = &vco_data[data->pll_num];
+
+ init.name = vco->vco_name;
+ init.ops = &stm32f4_pll_gate_ops;
+ /* init.flags = CLK_SET_RATE_GATE; */
+ init.parent_names = &pllsrc;
+ init.num_parents = 1;
+
+ pll->gate.lock = lock;
+ pll->gate.reg = base + STM32F4_RCC_CR;
+ pll->gate.shift = vco->bit_idx;
+ pll->gate.hw.init = &init;
+
+ pll->offset = vco->offset;
+ pll->n_start = data->n_start;
+ pll->bit_rdy_idx = vco->bit_rdy_idx;
+ pll->status = (readl(base + STM32F4_RCC_CR) >> vco->bit_idx) & 0x1;
+
+ reg = base + pll->offset;
+
+ pll_hw = &pll->gate.hw;
+ ret = clk_hw_register(NULL, pll_hw);
+ if (ret) {
+ kfree(pll);
+ return ERR_PTR(ret);
+ }
+
+ for (i = 0; i < MAX_PLL_DIV; i++)
+ if (data->div_name[i])
+ clk_register_pll_div(data->div_name[i],
+ vco->vco_name,
+ 0,
+ reg,
+ div_data[i].shift,
+ div_data[i].width,
+ div_data[i].flag_div,
+ div_data[i].div_table,
+ pll_hw,
+ lock);
+ return pll_hw;
+}
+
+/*
+ * Converts the primary and secondary indices (as they appear in DT) to an
+ * offset into our struct clock array.
+ */
+static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary)
+{
+ u64 table[MAX_GATE_MAP];
+
+ if (primary == 1) {
+ if (WARN_ON(secondary >= stm32fx_end_primary_clk))
+ return -EINVAL;
+ return secondary;
+ }
+
+ memcpy(table, stm32f4_gate_map, sizeof(table));
+
+ /* only bits set in table can be used as indices */
+ if (WARN_ON(secondary >= BITS_PER_BYTE * sizeof(table) ||
+ 0 == (table[BIT_ULL_WORD(secondary)] &
+ BIT_ULL_MASK(secondary))))
+ return -EINVAL;
+
+ /* mask out bits above our current index */
+ table[BIT_ULL_WORD(secondary)] &=
+ GENMASK_ULL(secondary % BITS_PER_LONG_LONG, 0);
+
+ return stm32fx_end_primary_clk - 1 + hweight64(table[0]) +
+ (BIT_ULL_WORD(secondary) >= 1 ? hweight64(table[1]) : 0) +
+ (BIT_ULL_WORD(secondary) >= 2 ? hweight64(table[2]) : 0);
+}
+
+static struct clk_hw *
+stm32f4_rcc_lookup_clk(struct of_phandle_args *clkspec, void *data)
+{
+ int i = stm32f4_rcc_lookup_clk_idx(clkspec->args[0], clkspec->args[1]);
+
+ if (i < 0)
+ return ERR_PTR(-EINVAL);
+
+ return clks[i];
+}
+
+#define to_rgclk(_rgate) container_of(_rgate, struct stm32_rgate, gate)
+
+static inline void disable_power_domain_write_protection(void)
+{
+ if (pdrm)
+ regmap_update_bits(pdrm, 0x00, (1 << 8), (1 << 8));
+}
+
+static inline void enable_power_domain_write_protection(void)
+{
+ if (pdrm)
+ regmap_update_bits(pdrm, 0x00, (1 << 8), (0 << 8));
+}
+
+static inline void sofware_reset_backup_domain(void)
+{
+ unsigned long val;
+
+ val = readl(base + STM32F4_RCC_BDCR);
+ writel(val | BIT(16), base + STM32F4_RCC_BDCR);
+ writel(val & ~BIT(16), base + STM32F4_RCC_BDCR);
+}
+
+struct stm32_rgate {
+ struct clk_gate gate;
+ u8 bit_rdy_idx;
+};
+
+#define RGATE_TIMEOUT 50000
+
+static int rgclk_enable(struct clk_hw *hw)
+{
+ struct clk_gate *gate = to_clk_gate(hw);
+ struct stm32_rgate *rgate = to_rgclk(gate);
+ int bit_status;
+ unsigned int timeout = RGATE_TIMEOUT;
+
+ if (clk_gate_ops.is_enabled(hw))
+ return 0;
+
+ disable_power_domain_write_protection();
+
+ clk_gate_ops.enable(hw);
+
+ do {
+ bit_status = !(readl(gate->reg) & BIT(rgate->bit_rdy_idx));
+ if (bit_status)
+ udelay(100);
+
+ } while (bit_status && --timeout);
+
+ enable_power_domain_write_protection();
+
+ return bit_status;
+}
+
+static void rgclk_disable(struct clk_hw *hw)
+{
+ clk_gate_ops.disable(hw);
+}
+
+static int rgclk_is_enabled(struct clk_hw *hw)
+{
+ return clk_gate_ops.is_enabled(hw);
+}
+
+static const struct clk_ops rgclk_ops = {
+ .enable = rgclk_enable,
+ .disable = rgclk_disable,
+ .is_enabled = rgclk_is_enabled,
+};
+
+static struct clk_hw *clk_register_rgate(struct device *dev, const char *name,
+ const char *parent_name,
+ unsigned long flags,
+ void __iomem *reg, u8 bit_idx,
+ u8 bit_rdy_idx,
+ u8 clk_gate_flags, spinlock_t *lock)
+{
+ struct stm32_rgate *rgate;
+ struct clk_init_data init = { NULL };
+ struct clk_hw *hw;
+ int ret;
+
+ rgate = kzalloc(sizeof(*rgate), GFP_KERNEL);
+ if (!rgate)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &rgclk_ops;
+ init.flags = flags;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ rgate->bit_rdy_idx = bit_rdy_idx;
+
+ rgate->gate.lock = lock;
+ rgate->gate.reg = reg;
+ rgate->gate.shift = bit_idx;
+ rgate->gate.hw.init = &init;
+
+ hw = &rgate->gate.hw;
+ ret = clk_hw_register(dev, hw);
+ if (ret) {
+ kfree(rgate);
+ hw = ERR_PTR(ret);
+ }
+
+ return hw;
+}
+
+static int cclk_gate_enable(struct clk_hw *hw)
+{
+ int ret;
+
+ disable_power_domain_write_protection();
+
+ ret = clk_gate_ops.enable(hw);
+
+ enable_power_domain_write_protection();
+
+ return ret;
+}
+
+static void cclk_gate_disable(struct clk_hw *hw)
+{
+ disable_power_domain_write_protection();
+
+ clk_gate_ops.disable(hw);
+
+ enable_power_domain_write_protection();
+}
+
+static int cclk_gate_is_enabled(struct clk_hw *hw)
+{
+ return clk_gate_ops.is_enabled(hw);
+}
+
+static const struct clk_ops cclk_gate_ops = {
+ .enable = cclk_gate_enable,
+ .disable = cclk_gate_disable,
+ .is_enabled = cclk_gate_is_enabled,
+};
+
+static int cclk_mux_get_parent(struct clk_hw *hw)
+{
+ return clk_mux_ops.get_parent(hw);
+}
+
+static int cclk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ int ret;
+
+ disable_power_domain_write_protection();
+
+ sofware_reset_backup_domain();
+
+ ret = clk_mux_ops.set_parent(hw, index);
+
+ enable_power_domain_write_protection();
+
+ return ret;
+}
+
+static const struct clk_ops cclk_mux_ops = {
+ .get_parent = cclk_mux_get_parent,
+ .set_parent = cclk_mux_set_parent,
+};
+
+static struct clk_hw *stm32_register_cclk(struct device *dev,
+ const char *name,
+ const char * const *parent_names,
+ int num_parents,
+ void __iomem *reg, u8 bit_idx,
+ u8 shift, unsigned long flags,
+ spinlock_t *lock)
+{
+ struct clk_hw *hw;
+ struct clk_gate *gate;
+ struct clk_mux *mux;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ hw = ERR_PTR(-EINVAL);
+ goto fail;
+ }
+
+ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+ if (!mux) {
+ kfree(gate);
+ hw = ERR_PTR(-EINVAL);
+ goto fail;
+ }
+
+ gate->reg = reg;
+ gate->shift = bit_idx;
+ gate->flags = 0;
+ gate->lock = lock;
+
+ mux->reg = reg;
+ mux->shift = shift;
+ mux->width = 2;
+ mux->flags = 0;
+
+ hw = clk_hw_register_composite(dev, name, parent_names, num_parents,
+ &mux->hw, &cclk_mux_ops,
+ NULL, NULL,
+ &gate->hw, &cclk_gate_ops,
+ flags);
+
+ if (IS_ERR(hw)) {
+ kfree(gate);
+ kfree(mux);
+ }
+
+fail:
+ return hw;
+}
+
+static const char *sys_parents[] __initdata = { "hsi", NULL, "pll" };
+
+static const struct clk_div_table ahb_div_table[] = {
+ { 0x0, 1 }, { 0x1, 1 }, { 0x2, 1 }, { 0x3, 1 },
+ { 0x4, 1 }, { 0x5, 1 }, { 0x6, 1 }, { 0x7, 1 },
+ { 0x8, 2 }, { 0x9, 4 }, { 0xa, 8 }, { 0xb, 16 },
+ { 0xc, 64 }, { 0xd, 128 }, { 0xe, 256 }, { 0xf, 512 },
+ { 0 },
+};
+
+static const struct clk_div_table apb_div_table[] = {
+ { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 },
+ { 4, 2 }, { 5, 4 }, { 6, 8 }, { 7, 16 },
+ { 0 },
+};
+
+static const char *rtc_parents[4] = {
+ "no-clock", "lse", "lsi", "hse-rtc"
+};
+
+static const char *pll_src = "pll-src";
+
+static const char *pllsrc_parent[2] = { "hsi", NULL };
+
+static const char *dsi_parent[2] = { NULL, "pll-r" };
+
+static const char *lcd_parent[1] = { "pllsai-r-div" };
+
+static const char *i2s_parents[2] = { "plli2s-r", NULL };
+
+static const char *sai_parents[4] = { "pllsai-q-div", "plli2s-q-div", NULL,
+ "no-clock" };
+
+static const char *pll48_parents[2] = { "pll-q", "pllsai-p" };
+
+static const char *sdmux_parents[2] = { "pll48", "sys" };
+
+static const char *hdmi_parents[2] = { "lse", "hsi_div488" };
+
+static const char *spdif_parent[1] = { "plli2s-p" };
+
+static const char *lptim_parent[4] = { "apb1_mul", "lsi", "hsi", "lse" };
+
+static const char *uart_parents1[4] = { "apb2_div", "sys", "hsi", "lse" };
+static const char *uart_parents2[4] = { "apb1_div", "sys", "hsi", "lse" };
+
+static const char *i2c_parents[4] = { "apb1_div", "sys", "hsi", "no-clock" };
+
+static const char * const dfsdm1_src[] = { "apb2_div", "sys" };
+static const char * const adsfdm1_parent[] = { "sai1_clk", "sai2_clk" };
+
+struct stm32_aux_clk {
+ int idx;
+ const char *name;
+ const char * const *parent_names;
+ int num_parents;
+ int offset_mux;
+ u8 shift;
+ u8 mask;
+ int offset_gate;
+ u8 bit_idx;
+ unsigned long flags;
+};
+
+struct stm32f4_clk_data {
+ const struct stm32f4_gate_data *gates_data;
+ const u64 *gates_map;
+ int gates_num;
+ const struct stm32f4_pll_data *pll_data;
+ const struct stm32_aux_clk *aux_clk;
+ int aux_clk_num;
+ int end_primary;
+};
+
+static const struct stm32_aux_clk stm32f429_aux_clk[] = {
+ {
+ CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
+ NO_MUX, 0, 0,
+ STM32F4_RCC_APB2ENR, 26,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ CLK_I2S, "i2s", i2s_parents, ARRAY_SIZE(i2s_parents),
+ STM32F4_RCC_CFGR, 23, 1,
+ NO_GATE, 0,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ CLK_SAI1, "sai1-a", sai_parents, ARRAY_SIZE(sai_parents),
+ STM32F4_RCC_DCKCFGR, 20, 3,
+ STM32F4_RCC_APB2ENR, 22,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ CLK_SAI2, "sai1-b", sai_parents, ARRAY_SIZE(sai_parents),
+ STM32F4_RCC_DCKCFGR, 22, 3,
+ STM32F4_RCC_APB2ENR, 22,
+ CLK_SET_RATE_PARENT
+ },
+};
+
+static const struct stm32_aux_clk stm32f469_aux_clk[] = {
+ {
+ CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
+ NO_MUX, 0, 0,
+ STM32F4_RCC_APB2ENR, 26,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ CLK_I2S, "i2s", i2s_parents, ARRAY_SIZE(i2s_parents),
+ STM32F4_RCC_CFGR, 23, 1,
+ NO_GATE, 0,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ CLK_SAI1, "sai1-a", sai_parents, ARRAY_SIZE(sai_parents),
+ STM32F4_RCC_DCKCFGR, 20, 3,
+ STM32F4_RCC_APB2ENR, 22,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ CLK_SAI2, "sai1-b", sai_parents, ARRAY_SIZE(sai_parents),
+ STM32F4_RCC_DCKCFGR, 22, 3,
+ STM32F4_RCC_APB2ENR, 22,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ NO_IDX, "pll48", pll48_parents, ARRAY_SIZE(pll48_parents),
+ STM32F4_RCC_DCKCFGR, 27, 1,
+ NO_GATE, 0,
+ 0
+ },
+ {
+ NO_IDX, "sdmux", sdmux_parents, ARRAY_SIZE(sdmux_parents),
+ STM32F4_RCC_DCKCFGR, 28, 1,
+ NO_GATE, 0,
+ 0
+ },
+ {
+ CLK_F469_DSI, "dsi", dsi_parent, ARRAY_SIZE(dsi_parent),
+ STM32F4_RCC_DCKCFGR, 29, 1,
+ STM32F4_RCC_APB2ENR, 27,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT
+ },
+};
+
+static const struct stm32_aux_clk stm32f746_aux_clk[] = {
+ {
+ CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
+ NO_MUX, 0, 0,
+ STM32F4_RCC_APB2ENR, 26,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ CLK_I2S, "i2s", i2s_parents, ARRAY_SIZE(i2s_parents),
+ STM32F4_RCC_CFGR, 23, 1,
+ NO_GATE, 0,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ CLK_SAI1, "sai1_clk", sai_parents, ARRAY_SIZE(sai_parents),
+ STM32F4_RCC_DCKCFGR, 20, 3,
+ STM32F4_RCC_APB2ENR, 22,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ CLK_SAI2, "sai2_clk", sai_parents, ARRAY_SIZE(sai_parents),
+ STM32F4_RCC_DCKCFGR, 22, 3,
+ STM32F4_RCC_APB2ENR, 23,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ NO_IDX, "pll48", pll48_parents, ARRAY_SIZE(pll48_parents),
+ STM32F7_RCC_DCKCFGR2, 27, 1,
+ NO_GATE, 0,
+ 0
+ },
+ {
+ NO_IDX, "sdmux", sdmux_parents, ARRAY_SIZE(sdmux_parents),
+ STM32F7_RCC_DCKCFGR2, 28, 1,
+ NO_GATE, 0,
+ 0
+ },
+ {
+ CLK_HDMI_CEC, "hdmi-cec",
+ hdmi_parents, ARRAY_SIZE(hdmi_parents),
+ STM32F7_RCC_DCKCFGR2, 26, 1,
+ NO_GATE, 0,
+ 0
+ },
+ {
+ CLK_SPDIF, "spdif-rx",
+ spdif_parent, ARRAY_SIZE(spdif_parent),
+ STM32F7_RCC_DCKCFGR2, 22, 3,
+ STM32F4_RCC_APB2ENR, 23,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ CLK_USART1, "usart1",
+ uart_parents1, ARRAY_SIZE(uart_parents1),
+ STM32F7_RCC_DCKCFGR2, 0, 3,
+ STM32F4_RCC_APB2ENR, 4,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_USART2, "usart2",
+ uart_parents2, ARRAY_SIZE(uart_parents1),
+ STM32F7_RCC_DCKCFGR2, 2, 3,
+ STM32F4_RCC_APB1ENR, 17,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_USART3, "usart3",
+ uart_parents2, ARRAY_SIZE(uart_parents1),
+ STM32F7_RCC_DCKCFGR2, 4, 3,
+ STM32F4_RCC_APB1ENR, 18,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_UART4, "uart4",
+ uart_parents2, ARRAY_SIZE(uart_parents1),
+ STM32F7_RCC_DCKCFGR2, 6, 3,
+ STM32F4_RCC_APB1ENR, 19,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_UART5, "uart5",
+ uart_parents2, ARRAY_SIZE(uart_parents1),
+ STM32F7_RCC_DCKCFGR2, 8, 3,
+ STM32F4_RCC_APB1ENR, 20,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_USART6, "usart6",
+ uart_parents1, ARRAY_SIZE(uart_parents1),
+ STM32F7_RCC_DCKCFGR2, 10, 3,
+ STM32F4_RCC_APB2ENR, 5,
+ CLK_SET_RATE_PARENT,
+ },
+
+ {
+ CLK_UART7, "uart7",
+ uart_parents2, ARRAY_SIZE(uart_parents1),
+ STM32F7_RCC_DCKCFGR2, 12, 3,
+ STM32F4_RCC_APB1ENR, 30,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_UART8, "uart8",
+ uart_parents2, ARRAY_SIZE(uart_parents1),
+ STM32F7_RCC_DCKCFGR2, 14, 3,
+ STM32F4_RCC_APB1ENR, 31,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_I2C1, "i2c1",
+ i2c_parents, ARRAY_SIZE(i2c_parents),
+ STM32F7_RCC_DCKCFGR2, 16, 3,
+ STM32F4_RCC_APB1ENR, 21,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_I2C2, "i2c2",
+ i2c_parents, ARRAY_SIZE(i2c_parents),
+ STM32F7_RCC_DCKCFGR2, 18, 3,
+ STM32F4_RCC_APB1ENR, 22,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_I2C3, "i2c3",
+ i2c_parents, ARRAY_SIZE(i2c_parents),
+ STM32F7_RCC_DCKCFGR2, 20, 3,
+ STM32F4_RCC_APB1ENR, 23,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_I2C4, "i2c4",
+ i2c_parents, ARRAY_SIZE(i2c_parents),
+ STM32F7_RCC_DCKCFGR2, 22, 3,
+ STM32F4_RCC_APB1ENR, 24,
+ CLK_SET_RATE_PARENT,
+ },
+
+ {
+ CLK_LPTIMER, "lptim1",
+ lptim_parent, ARRAY_SIZE(lptim_parent),
+ STM32F7_RCC_DCKCFGR2, 24, 3,
+ STM32F4_RCC_APB1ENR, 9,
+ CLK_SET_RATE_PARENT
+ },
+};
+
+static const struct stm32_aux_clk stm32f769_aux_clk[] = {
+ {
+ CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
+ NO_MUX, 0, 0,
+ STM32F4_RCC_APB2ENR, 26,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ CLK_I2S, "i2s", i2s_parents, ARRAY_SIZE(i2s_parents),
+ STM32F4_RCC_CFGR, 23, 1,
+ NO_GATE, 0,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ CLK_SAI1, "sai1_clk", sai_parents, ARRAY_SIZE(sai_parents),
+ STM32F4_RCC_DCKCFGR, 20, 3,
+ STM32F4_RCC_APB2ENR, 22,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ CLK_SAI2, "sai2_clk", sai_parents, ARRAY_SIZE(sai_parents),
+ STM32F4_RCC_DCKCFGR, 22, 3,
+ STM32F4_RCC_APB2ENR, 23,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ NO_IDX, "pll48", pll48_parents, ARRAY_SIZE(pll48_parents),
+ STM32F7_RCC_DCKCFGR2, 27, 1,
+ NO_GATE, 0,
+ 0
+ },
+ {
+ NO_IDX, "sdmux1", sdmux_parents, ARRAY_SIZE(sdmux_parents),
+ STM32F7_RCC_DCKCFGR2, 28, 1,
+ NO_GATE, 0,
+ 0
+ },
+ {
+ NO_IDX, "sdmux2", sdmux_parents, ARRAY_SIZE(sdmux_parents),
+ STM32F7_RCC_DCKCFGR2, 29, 1,
+ NO_GATE, 0,
+ 0
+ },
+ {
+ CLK_HDMI_CEC, "hdmi-cec",
+ hdmi_parents, ARRAY_SIZE(hdmi_parents),
+ STM32F7_RCC_DCKCFGR2, 26, 1,
+ NO_GATE, 0,
+ 0
+ },
+ {
+ CLK_SPDIF, "spdif-rx",
+ spdif_parent, ARRAY_SIZE(spdif_parent),
+ STM32F7_RCC_DCKCFGR2, 22, 3,
+ STM32F4_RCC_APB2ENR, 23,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ CLK_USART1, "usart1",
+ uart_parents1, ARRAY_SIZE(uart_parents1),
+ STM32F7_RCC_DCKCFGR2, 0, 3,
+ STM32F4_RCC_APB2ENR, 4,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_USART2, "usart2",
+ uart_parents2, ARRAY_SIZE(uart_parents1),
+ STM32F7_RCC_DCKCFGR2, 2, 3,
+ STM32F4_RCC_APB1ENR, 17,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_USART3, "usart3",
+ uart_parents2, ARRAY_SIZE(uart_parents1),
+ STM32F7_RCC_DCKCFGR2, 4, 3,
+ STM32F4_RCC_APB1ENR, 18,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_UART4, "uart4",
+ uart_parents2, ARRAY_SIZE(uart_parents1),
+ STM32F7_RCC_DCKCFGR2, 6, 3,
+ STM32F4_RCC_APB1ENR, 19,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_UART5, "uart5",
+ uart_parents2, ARRAY_SIZE(uart_parents1),
+ STM32F7_RCC_DCKCFGR2, 8, 3,
+ STM32F4_RCC_APB1ENR, 20,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_USART6, "usart6",
+ uart_parents1, ARRAY_SIZE(uart_parents1),
+ STM32F7_RCC_DCKCFGR2, 10, 3,
+ STM32F4_RCC_APB2ENR, 5,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_UART7, "uart7",
+ uart_parents2, ARRAY_SIZE(uart_parents1),
+ STM32F7_RCC_DCKCFGR2, 12, 3,
+ STM32F4_RCC_APB1ENR, 30,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_UART8, "uart8",
+ uart_parents2, ARRAY_SIZE(uart_parents1),
+ STM32F7_RCC_DCKCFGR2, 14, 3,
+ STM32F4_RCC_APB1ENR, 31,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_I2C1, "i2c1",
+ i2c_parents, ARRAY_SIZE(i2c_parents),
+ STM32F7_RCC_DCKCFGR2, 16, 3,
+ STM32F4_RCC_APB1ENR, 21,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_I2C2, "i2c2",
+ i2c_parents, ARRAY_SIZE(i2c_parents),
+ STM32F7_RCC_DCKCFGR2, 18, 3,
+ STM32F4_RCC_APB1ENR, 22,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_I2C3, "i2c3",
+ i2c_parents, ARRAY_SIZE(i2c_parents),
+ STM32F7_RCC_DCKCFGR2, 20, 3,
+ STM32F4_RCC_APB1ENR, 23,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_I2C4, "i2c4",
+ i2c_parents, ARRAY_SIZE(i2c_parents),
+ STM32F7_RCC_DCKCFGR2, 22, 3,
+ STM32F4_RCC_APB1ENR, 24,
+ CLK_SET_RATE_PARENT,
+ },
+ {
+ CLK_LPTIMER, "lptim1",
+ lptim_parent, ARRAY_SIZE(lptim_parent),
+ STM32F7_RCC_DCKCFGR2, 24, 3,
+ STM32F4_RCC_APB1ENR, 9,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ CLK_F769_DSI, "dsi",
+ dsi_parent, ARRAY_SIZE(dsi_parent),
+ STM32F7_RCC_DCKCFGR2, 0, 1,
+ STM32F4_RCC_APB2ENR, 27,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ CLK_DFSDM1, "dfsdm1",
+ dfsdm1_src, ARRAY_SIZE(dfsdm1_src),
+ STM32F4_RCC_DCKCFGR, 25, 1,
+ STM32F4_RCC_APB2ENR, 29,
+ CLK_SET_RATE_PARENT
+ },
+ {
+ CLK_ADFSDM1, "adfsdm1",
+ adsfdm1_parent, ARRAY_SIZE(adsfdm1_parent),
+ STM32F4_RCC_DCKCFGR, 26, 1,
+ STM32F4_RCC_APB2ENR, 29,
+ CLK_SET_RATE_PARENT
+ },
+};
+
+static const struct stm32f4_clk_data stm32f429_clk_data = {
+ .end_primary = END_PRIMARY_CLK,
+ .gates_data = stm32f429_gates,
+ .gates_map = stm32f42xx_gate_map,
+ .gates_num = ARRAY_SIZE(stm32f429_gates),
+ .pll_data = stm32f429_pll,
+ .aux_clk = stm32f429_aux_clk,
+ .aux_clk_num = ARRAY_SIZE(stm32f429_aux_clk),
+};
+
+static const struct stm32f4_clk_data stm32f469_clk_data = {
+ .end_primary = END_PRIMARY_CLK,
+ .gates_data = stm32f469_gates,
+ .gates_map = stm32f46xx_gate_map,
+ .gates_num = ARRAY_SIZE(stm32f469_gates),
+ .pll_data = stm32f469_pll,
+ .aux_clk = stm32f469_aux_clk,
+ .aux_clk_num = ARRAY_SIZE(stm32f469_aux_clk),
+};
+
+static const struct stm32f4_clk_data stm32f746_clk_data = {
+ .end_primary = END_PRIMARY_CLK_F7,
+ .gates_data = stm32f746_gates,
+ .gates_map = stm32f746_gate_map,
+ .gates_num = ARRAY_SIZE(stm32f746_gates),
+ .pll_data = stm32f469_pll,
+ .aux_clk = stm32f746_aux_clk,
+ .aux_clk_num = ARRAY_SIZE(stm32f746_aux_clk),
+};
+
+static const struct stm32f4_clk_data stm32f769_clk_data = {
+ .end_primary = END_PRIMARY_CLK_F7,
+ .gates_data = stm32f769_gates,
+ .gates_map = stm32f769_gate_map,
+ .gates_num = ARRAY_SIZE(stm32f769_gates),
+ .pll_data = stm32f469_pll,
+ .aux_clk = stm32f769_aux_clk,
+ .aux_clk_num = ARRAY_SIZE(stm32f769_aux_clk),
+};
+
+static const struct of_device_id stm32f4_of_match[] = {
+ {
+ .compatible = "st,stm32f42xx-rcc",
+ .data = &stm32f429_clk_data
+ },
+ {
+ .compatible = "st,stm32f469-rcc",
+ .data = &stm32f469_clk_data
+ },
+ {
+ .compatible = "st,stm32f746-rcc",
+ .data = &stm32f746_clk_data
+ },
+ {
+ .compatible = "st,stm32f769-rcc",
+ .data = &stm32f769_clk_data
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, stm32f4_of_match);
+
+static struct clk_hw *stm32_register_aux_clk(const char *name,
+ const char * const *parent_names, int num_parents,
+ int offset_mux, u8 shift, u8 mask,
+ int offset_gate, u8 bit_idx,
+ unsigned long flags, spinlock_t *lock)
+{
+ struct clk_hw *hw;
+ struct clk_gate *gate = NULL;
+ struct clk_mux *mux = NULL;
+ struct clk_hw *mux_hw = NULL, *gate_hw = NULL;
+ const struct clk_ops *mux_ops = NULL, *gate_ops = NULL;
+
+ if (offset_gate != NO_GATE) {
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ hw = ERR_PTR(-EINVAL);
+ goto fail;
+ }
+
+ gate->reg = base + offset_gate;
+ gate->shift = bit_idx;
+ gate->flags = 0;
+ gate->lock = lock;
+ gate_hw = &gate->hw;
+ gate_ops = &clk_gate_ops;
+ }
+
+ if (offset_mux != NO_MUX) {
+ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+ if (!mux) {
+ hw = ERR_PTR(-EINVAL);
+ goto fail;
+ }
+
+ mux->reg = base + offset_mux;
+ mux->shift = shift;
+ mux->width = hweight8(mask);
+ mux->flags = 0;
+ mux_hw = &mux->hw;
+ mux_ops = &clk_mux_ops;
+ }
+
+ if (mux_hw == NULL && gate_hw == NULL) {
+ hw = ERR_PTR(-EINVAL);
+ goto fail;
+ }
+
+ hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
+ mux_hw, mux_ops,
+ NULL, NULL,
+ gate_hw, gate_ops,
+ flags);
+
+fail:
+ if (IS_ERR(hw)) {
+ kfree(gate);
+ kfree(mux);
+ }
+
+ return hw;
+}
+
+static void __init stm32f4_rcc_init(struct device_node *np)
+{
+ const char *hse_clk, *i2s_in_clk;
+ int n;
+ const struct of_device_id *match;
+ const struct stm32f4_clk_data *data;
+ unsigned long pllm;
+ struct clk_hw *pll_src_hw;
+
+ base = of_iomap(np, 0);
+ if (!base) {
+ pr_err("%pOFn: unable to map resource\n", np);
+ return;
+ }
+
+ pdrm = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
+ if (IS_ERR(pdrm)) {
+ pdrm = NULL;
+ pr_warn("%s: Unable to get syscfg\n", __func__);
+ }
+
+ match = of_match_node(stm32f4_of_match, np);
+ if (WARN_ON(!match))
+ return;
+
+ data = match->data;
+
+ stm32fx_end_primary_clk = data->end_primary;
+
+ clks = kmalloc_array(data->gates_num + stm32fx_end_primary_clk,
+ sizeof(*clks), GFP_KERNEL);
+ if (!clks)
+ goto fail;
+
+ stm32f4_gate_map = data->gates_map;
+
+ hse_clk = of_clk_get_parent_name(np, 0);
+ dsi_parent[0] = hse_clk;
+ pllsrc_parent[1] = hse_clk;
+
+ i2s_in_clk = of_clk_get_parent_name(np, 1);
+
+ i2s_parents[1] = i2s_in_clk;
+ sai_parents[2] = i2s_in_clk;
+
+ if (of_device_is_compatible(np, "st,stm32f769-rcc")) {
+ clk_hw_register_gate(NULL, "dfsdm1_apb", "apb2_div", 0,
+ base + STM32F4_RCC_APB2ENR, 29,
+ CLK_IGNORE_UNUSED, &stm32f4_clk_lock);
+ dsi_parent[0] = pll_src;
+ sai_parents[3] = pll_src;
+ }
+
+ clks[CLK_HSI] = clk_hw_register_fixed_rate(NULL, "hsi",
+ NULL, 0, 16000000);
+
+ pll_src_hw = clk_hw_register_mux(NULL, pll_src, pllsrc_parent,
+ ARRAY_SIZE(pllsrc_parent), 0,
+ base + STM32F4_RCC_PLLCFGR, 22, 1, 0,
+ &stm32f4_clk_lock);
+
+ pllm = readl(base + STM32F4_RCC_PLLCFGR) & 0x3f;
+
+ clk_hw_register_fixed_factor(NULL, "vco_in", pll_src,
+ 0, 1, pllm);
+
+ stm32f4_rcc_register_pll("vco_in", &data->pll_data[0],
+ &stm32f4_clk_lock);
+
+ clks[PLL_VCO_I2S] = stm32f4_rcc_register_pll("vco_in",
+ &data->pll_data[1], &stm32f4_clk_lock);
+
+ clks[PLL_VCO_SAI] = stm32f4_rcc_register_pll("vco_in",
+ &data->pll_data[2], &stm32f4_clk_lock);
+
+ for (n = 0; n < MAX_POST_DIV; n++) {
+ const struct stm32f4_pll_post_div_data *post_div;
+ struct clk_hw *hw;
+
+ post_div = &post_div_data[n];
+
+ hw = clk_register_pll_div(post_div->name,
+ post_div->parent,
+ post_div->flag,
+ base + post_div->offset,
+ post_div->shift,
+ post_div->width,
+ post_div->flag_div,
+ post_div->div_table,
+ clks[post_div->pll_idx],
+ &stm32f4_clk_lock);
+
+ if (post_div->idx != NO_IDX)
+ clks[post_div->idx] = hw;
+ }
+
+ sys_parents[1] = hse_clk;
+
+ clks[CLK_SYSCLK] = clk_hw_register_mux_table(
+ NULL, "sys", sys_parents, ARRAY_SIZE(sys_parents), 0,
+ base + STM32F4_RCC_CFGR, 0, 3, 0, NULL, &stm32f4_clk_lock);
+
+ clk_register_divider_table(NULL, "ahb_div", "sys",
+ CLK_SET_RATE_PARENT, base + STM32F4_RCC_CFGR,
+ 4, 4, 0, ahb_div_table, &stm32f4_clk_lock);
+
+ clk_register_divider_table(NULL, "apb1_div", "ahb_div",
+ CLK_SET_RATE_PARENT, base + STM32F4_RCC_CFGR,
+ 10, 3, 0, apb_div_table, &stm32f4_clk_lock);
+ clk_register_apb_mul(NULL, "apb1_mul", "apb1_div",
+ CLK_SET_RATE_PARENT, 12);
+
+ clk_register_divider_table(NULL, "apb2_div", "ahb_div",
+ CLK_SET_RATE_PARENT, base + STM32F4_RCC_CFGR,
+ 13, 3, 0, apb_div_table, &stm32f4_clk_lock);
+ clk_register_apb_mul(NULL, "apb2_mul", "apb2_div",
+ CLK_SET_RATE_PARENT, 15);
+
+ clks[SYSTICK] = clk_hw_register_fixed_factor(NULL, "systick", "ahb_div",
+ 0, 1, 8);
+ clks[FCLK] = clk_hw_register_fixed_factor(NULL, "fclk", "ahb_div",
+ 0, 1, 1);
+
+ for (n = 0; n < data->gates_num; n++) {
+ const struct stm32f4_gate_data *gd;
+ unsigned int secondary;
+ int idx;
+
+ gd = &data->gates_data[n];
+ secondary = 8 * (gd->offset - STM32F4_RCC_AHB1ENR) +
+ gd->bit_idx;
+ idx = stm32f4_rcc_lookup_clk_idx(0, secondary);
+
+ if (idx < 0)
+ goto fail;
+
+ clks[idx] = clk_hw_register_gate(
+ NULL, gd->name, gd->parent_name, gd->flags,
+ base + gd->offset, gd->bit_idx, 0, &stm32f4_clk_lock);
+
+ if (IS_ERR(clks[idx])) {
+ pr_err("%pOF: Unable to register leaf clock %s\n",
+ np, gd->name);
+ goto fail;
+ }
+ }
+
+ clks[CLK_LSI] = clk_register_rgate(NULL, "lsi", "clk-lsi", 0,
+ base + STM32F4_RCC_CSR, 0, 1, 0, &stm32f4_clk_lock);
+
+ if (IS_ERR(clks[CLK_LSI])) {
+ pr_err("Unable to register lsi clock\n");
+ goto fail;
+ }
+
+ clks[CLK_LSE] = clk_register_rgate(NULL, "lse", "clk-lse", 0,
+ base + STM32F4_RCC_BDCR, 0, 1, 0, &stm32f4_clk_lock);
+
+ if (IS_ERR(clks[CLK_LSE])) {
+ pr_err("Unable to register lse clock\n");
+ goto fail;
+ }
+
+ clks[CLK_HSE_RTC] = clk_hw_register_divider(NULL, "hse-rtc", "clk-hse",
+ 0, base + STM32F4_RCC_CFGR, 16, 5, 0,
+ &stm32f4_clk_lock);
+
+ if (IS_ERR(clks[CLK_HSE_RTC])) {
+ pr_err("Unable to register hse-rtc clock\n");
+ goto fail;
+ }
+
+ clks[CLK_RTC] = stm32_register_cclk(NULL, "rtc", rtc_parents, 4,
+ base + STM32F4_RCC_BDCR, 15, 8, 0, &stm32f4_clk_lock);
+
+ if (IS_ERR(clks[CLK_RTC])) {
+ pr_err("Unable to register rtc clock\n");
+ goto fail;
+ }
+
+ for (n = 0; n < data->aux_clk_num; n++) {
+ const struct stm32_aux_clk *aux_clk;
+ struct clk_hw *hw;
+
+ aux_clk = &data->aux_clk[n];
+
+ hw = stm32_register_aux_clk(aux_clk->name,
+ aux_clk->parent_names, aux_clk->num_parents,
+ aux_clk->offset_mux, aux_clk->shift,
+ aux_clk->mask, aux_clk->offset_gate,
+ aux_clk->bit_idx, aux_clk->flags,
+ &stm32f4_clk_lock);
+
+ if (IS_ERR(hw)) {
+ pr_warn("Unable to register %s clk\n", aux_clk->name);
+ continue;
+ }
+
+ if (aux_clk->idx != NO_IDX)
+ clks[aux_clk->idx] = hw;
+ }
+
+ if (of_device_is_compatible(np, "st,stm32f746-rcc")) {
+
+ clk_hw_register_fixed_factor(NULL, "hsi_div488", "hsi", 0,
+ 1, 488);
+
+ clks[CLK_PLL_SRC] = pll_src_hw;
+ }
+
+ of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL);
+
+ return;
+fail:
+ kfree(clks);
+}
+CLK_OF_DECLARE_DRIVER(stm32f42xx_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
+CLK_OF_DECLARE_DRIVER(stm32f46xx_rcc, "st,stm32f469-rcc", stm32f4_rcc_init);
+CLK_OF_DECLARE_DRIVER(stm32f746_rcc, "st,stm32f746-rcc", stm32f4_rcc_init);
+CLK_OF_DECLARE_DRIVER(stm32f769_rcc, "st,stm32f769-rcc", stm32f4_rcc_init);
diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c
index 6016c5bfd0..9ea4c0b830 100644
--- a/drivers/clk/clk-stm32mp1.c
+++ b/drivers/clk/clk-stm32mp1.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) STMicroelectronics 2018 - All Rights Reserved
* Author: Olivier Bideau <olivier.bideau@st.com> for STMicroelectronics.
@@ -6,14 +6,22 @@
*/
#include <linux/clk.h>
+#include <clock.h>
#include <linux/err.h>
+#include <linux/overflow.h>
#include <io.h>
#include <of.h>
#include <of_address.h>
-#include <asm-generic/div64.h>
+#include <driver.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <soc/stm32/reboot.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
+static DEFINE_SPINLOCK(rlock);
+
#define RCC_OCENSETR 0x0C
#define RCC_HSICFGR 0x18
#define RCC_RDLSICR 0x144
@@ -116,7 +124,7 @@ static const char * const cpu_src[] = {
};
static const char * const axi_src[] = {
- "ck_hsi", "ck_hse", "pll2_p", "pll3_p"
+ "ck_hsi", "ck_hse", "pll2_p"
};
static const char * const per_src[] = {
@@ -220,19 +228,19 @@ static const char * const usart6_src[] = {
};
static const char * const fdcan_src[] = {
- "ck_hse", "pll3_q", "pll4_q"
+ "ck_hse", "pll3_q", "pll4_q", "pll4_r"
};
static const char * const sai_src[] = {
- "pll4_q", "pll3_q", "i2s_ckin", "ck_per"
+ "pll4_q", "pll3_q", "i2s_ckin", "ck_per", "pll3_r"
};
static const char * const sai2_src[] = {
- "pll4_q", "pll3_q", "i2s_ckin", "ck_per", "spdif_ck_symb"
+ "pll4_q", "pll3_q", "i2s_ckin", "ck_per", "spdif_ck_symb", "pll3_r"
};
static const char * const adc12_src[] = {
- "pll4_q", "ck_per"
+ "pll4_r", "ck_per", "pll3_q"
};
static const char * const dsi_src[] = {
@@ -240,7 +248,7 @@ static const char * const dsi_src[] = {
};
static const char * const rtc_src[] = {
- "off", "ck_lse", "ck_lsi", "ck_hse_rtc"
+ "off", "ck_lse", "ck_lsi", "ck_hse"
};
static const char * const mco1_src[] = {
@@ -264,7 +272,7 @@ static const struct clk_div_table axi_div_table[] = {
static const struct clk_div_table mcu_div_table[] = {
{ 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 },
{ 4, 16 }, { 5, 32 }, { 6, 64 }, { 7, 128 },
- { 8, 512 }, { 9, 512 }, { 10, 512}, { 11, 512 },
+ { 8, 256 }, { 9, 512 }, { 10, 512}, { 11, 512 },
{ 12, 512 }, { 13, 512 }, { 14, 512}, { 15, 512 },
{ 0 },
};
@@ -285,7 +293,7 @@ static const struct clk_div_table ck_trace_div_table[] = {
struct stm32_mmux {
u8 nbr_clk;
- struct clk *hws[MAX_MUX_CLK];
+ struct clk_hw *hws[MAX_MUX_CLK];
};
struct stm32_clk_mmux {
@@ -312,7 +320,10 @@ struct clock_config {
int num_parents;
unsigned long flags;
void *cfg;
- struct clk * (*func)(void __iomem *base, const struct clock_config *cfg);
+ struct clk_hw * (*func)(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
+ const struct clock_config *cfg);
};
#define NO_ID ~0
@@ -368,71 +379,90 @@ struct stm32_composite_cfg {
const struct stm32_mux_cfg *mux;
};
-static struct clk *
-_clk_hw_register_gate(void __iomem *base,
+static struct clk_hw *
+_clk_hw_register_gate(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
const struct clock_config *cfg)
{
struct gate_cfg *gate_cfg = cfg->cfg;
- return clk_gate(cfg->name, cfg->parent_name, gate_cfg->reg_off + base,
- gate_cfg->bit_idx, cfg->flags, gate_cfg->gate_flags);
+ return clk_hw_register_gate(dev,
+ cfg->name,
+ cfg->parent_name,
+ cfg->flags,
+ gate_cfg->reg_off + base,
+ gate_cfg->bit_idx,
+ gate_cfg->gate_flags,
+ lock);
}
-static struct clk *
-_clk_hw_register_fixed_factor(void __iomem *base,
+static struct clk_hw *
+_clk_hw_register_fixed_factor(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
const struct clock_config *cfg)
{
struct fixed_factor_cfg *ff_cfg = cfg->cfg;
- return clk_fixed_factor(cfg->name, cfg->parent_name, ff_cfg->mult,
- ff_cfg->div, cfg->flags);
+ return clk_hw_register_fixed_factor(dev, cfg->name, cfg->parent_name,
+ cfg->flags, ff_cfg->mult,
+ ff_cfg->div);
}
-static struct clk *
-_clk_hw_register_divider_table(void __iomem *base,
+static struct clk_hw *
+_clk_hw_register_divider_table(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
const struct clock_config *cfg)
{
-
struct div_cfg *div_cfg = cfg->cfg;
- if (div_cfg->table)
- return clk_divider_table(cfg->name, cfg->parent_name, cfg->flags,
- div_cfg->reg_off + base, div_cfg->shift,
- div_cfg->width, div_cfg->table,
- div_cfg->div_flags);
- else
- return clk_divider(cfg->name, cfg->parent_name, cfg->flags,
- div_cfg->reg_off + base, div_cfg->shift,
- div_cfg->width, div_cfg->div_flags);
+ return clk_hw_register_divider_table(dev,
+ cfg->name,
+ cfg->parent_name,
+ cfg->flags,
+ div_cfg->reg_off + base,
+ div_cfg->shift,
+ div_cfg->width,
+ div_cfg->div_flags,
+ div_cfg->table,
+ lock);
}
-static struct clk *
-_clk_hw_register_mux(void __iomem *base,
+static struct clk_hw *
+_clk_hw_register_mux(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
const struct clock_config *cfg)
{
struct mux_cfg *mux_cfg = cfg->cfg;
- return clk_mux(cfg->name,cfg->flags, mux_cfg->reg_off + base, mux_cfg->shift,
- mux_cfg->width, cfg->parent_names, cfg->num_parents,
- mux_cfg->mux_flags);
+ return clk_hw_register_mux(dev, cfg->name, cfg->parent_names,
+ cfg->num_parents, cfg->flags,
+ mux_cfg->reg_off + base, mux_cfg->shift,
+ mux_cfg->width, mux_cfg->mux_flags, lock);
}
/* MP1 Gate clock with set & clear registers */
-static int mp1_gate_clk_enable(struct clk *clk)
+static int mp1_gate_clk_enable(struct clk_hw *hw)
{
- if (!clk_gate_ops.is_enabled(clk))
- clk_gate_ops.enable(clk);
+ if (!clk_gate_ops.is_enabled(hw))
+ clk_gate_ops.enable(hw);
return 0;
}
-static void mp1_gate_clk_disable(struct clk *clk)
+static void mp1_gate_clk_disable(struct clk_hw *hw)
{
- struct clk_gate *gate = to_clk_gate(clk);
+ struct clk_gate *gate = to_clk_gate(hw);
+ unsigned long flags = 0;
- if (clk_gate_ops.is_enabled(clk)) {
- writel(BIT(gate->shift), gate->reg + RCC_CLR);
+ if (clk_gate_ops.is_enabled(hw)) {
+ spin_lock_irqsave(gate->lock, flags);
+ writel_relaxed(BIT(gate->shift), gate->reg + RCC_CLR);
+ spin_unlock_irqrestore(gate->lock, flags);
}
}
@@ -442,12 +472,13 @@ static const struct clk_ops mp1_gate_clk_ops = {
.is_enabled = clk_gate_is_enabled,
};
-static struct clk *_get_stm32_mux(void __iomem *base,
- const struct stm32_mux_cfg *cfg)
+static struct clk_hw *_get_stm32_mux(struct device *dev, void __iomem *base,
+ const struct stm32_mux_cfg *cfg,
+ spinlock_t *lock)
{
struct stm32_clk_mmux *mmux;
struct clk_mux *mux;
- struct clk *mux_hw;
+ struct clk_hw *mux_hw;
if (cfg->mmux) {
mmux = kzalloc(sizeof(*mmux), GFP_KERNEL);
@@ -457,10 +488,13 @@ static struct clk *_get_stm32_mux(void __iomem *base,
mmux->mux.reg = cfg->mux->reg_off + base;
mmux->mux.shift = cfg->mux->shift;
mmux->mux.width = cfg->mux->width;
+ mmux->mux.flags = cfg->mux->mux_flags;
+ mmux->mux.table = cfg->mux->table;
+ mmux->mux.lock = lock;
mmux->mmux = cfg->mmux;
- mux_hw = &mmux->mux.clk;
+ mux_hw = &mmux->mux.hw;
cfg->mmux->hws[cfg->mmux->nbr_clk++] = mux_hw;
- mux = &mmux->mux;
+
} else {
mux = kzalloc(sizeof(*mux), GFP_KERNEL);
if (!mux)
@@ -469,23 +503,23 @@ static struct clk *_get_stm32_mux(void __iomem *base,
mux->reg = cfg->mux->reg_off + base;
mux->shift = cfg->mux->shift;
mux->width = cfg->mux->width;
- mux_hw = &mux->clk;
+ mux->flags = cfg->mux->mux_flags;
+ mux->table = cfg->mux->table;
+ mux->lock = lock;
+ mux_hw = &mux->hw;
}
- if (cfg->ops)
- mux->clk.ops = cfg->ops;
- else
- mux->clk.ops = &clk_mux_ops;
-
return mux_hw;
}
-static struct clk *_get_stm32_div(void __iomem *base,
- const struct stm32_div_cfg *cfg)
+static struct clk_hw *_get_stm32_div(struct device *dev, void __iomem *base,
+ const struct stm32_div_cfg *cfg,
+ spinlock_t *lock)
{
struct clk_divider *div;
div = kzalloc(sizeof(*div), GFP_KERNEL);
+
if (!div)
return ERR_PTR(-ENOMEM);
@@ -494,21 +528,18 @@ static struct clk *_get_stm32_div(void __iomem *base,
div->width = cfg->div->width;
div->flags = cfg->div->div_flags;
div->table = cfg->div->table;
+ div->lock = lock;
- if (cfg->ops)
- div->clk.ops = cfg->ops;
- else
- div->clk.ops = &clk_divider_ops;
-
- return &div->clk;
+ return &div->hw;
}
-static struct clk_gate *
-_get_stm32_gate(void __iomem *base,
- const struct stm32_gate_cfg *cfg)
+static struct clk_hw *_get_stm32_gate(struct device *dev, void __iomem *base,
+ const struct stm32_gate_cfg *cfg,
+ spinlock_t *lock)
{
struct stm32_clk_mgate *mgate;
struct clk_gate *gate;
+ struct clk_hw *gate_hw;
if (cfg->mgate) {
mgate = kzalloc(sizeof(*mgate), GFP_KERNEL);
@@ -518,11 +549,12 @@ _get_stm32_gate(void __iomem *base,
mgate->gate.reg = cfg->gate->reg_off + base;
mgate->gate.shift = cfg->gate->bit_idx;
mgate->gate.flags = cfg->gate->gate_flags;
+ mgate->gate.lock = lock;
mgate->mask = BIT(cfg->mgate->nbr_clk++);
mgate->mgate = cfg->mgate;
- gate = &mgate->gate;
+ gate_hw = &mgate->gate.hw;
} else {
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
@@ -532,96 +564,128 @@ _get_stm32_gate(void __iomem *base,
gate->reg = cfg->gate->reg_off + base;
gate->shift = cfg->gate->bit_idx;
gate->flags = cfg->gate->gate_flags;
+ gate->lock = lock;
+
+ gate_hw = &gate->hw;
}
-
- if (cfg->ops)
- gate->clk.ops = cfg->ops;
- else
- gate->clk.ops = &clk_gate_ops;
- return gate;
+ return gate_hw;
}
-static struct clk *
-clk_stm32_register_gate_ops(const char *name,
+static struct clk_hw *
+clk_stm32_register_gate_ops(struct device *dev,
+ const char *name,
const char *parent_name,
unsigned long flags,
void __iomem *base,
- const struct stm32_gate_cfg *cfg)
+ const struct stm32_gate_cfg *cfg,
+ spinlock_t *lock)
{
- struct clk *clk;
- struct clk_gate *gate;
+ struct clk_init_data init = { NULL };
+ struct clk_hw *hw;
int ret;
- gate = _get_stm32_gate(base, cfg);
- if (IS_ERR(gate))
+ init.name = name;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.flags = flags;
+
+ init.ops = &clk_gate_ops;
+
+ if (cfg->ops)
+ init.ops = cfg->ops;
+
+ hw = _get_stm32_gate(dev, base, cfg, lock);
+ if (IS_ERR(hw))
return ERR_PTR(-ENOMEM);
- gate->parent = parent_name;
- clk = &gate->clk;
- clk->name = name;
- clk->parent_names = &gate->parent;
- clk->num_parents = 1;
- clk->flags = flags;
+ hw->init = &init;
- ret = clk_register(clk);
+ ret = clk_hw_register(dev, hw);
if (ret)
- clk = ERR_PTR(ret);
+ hw = ERR_PTR(ret);
- return clk;
+ return hw;
}
-static struct clk *
-clk_stm32_register_composite(const char *name, const char * const *parent_names,
+static struct clk_hw *
+clk_stm32_register_composite(struct device *dev,
+ const char *name, const char * const *parent_names,
int num_parents, void __iomem *base,
const struct stm32_composite_cfg *cfg,
- unsigned long flags)
+ unsigned long flags, spinlock_t *lock)
{
- struct clk *mux_hw, *div_hw, *gate_hw;
- struct clk_gate *gate;
+ const struct clk_ops *mux_ops, *div_ops, *gate_ops;
+ struct clk_hw *mux_hw, *div_hw, *gate_hw;
mux_hw = NULL;
div_hw = NULL;
gate_hw = NULL;
+ mux_ops = NULL;
+ div_ops = NULL;
+ gate_ops = NULL;
+
+ if (cfg->mux) {
+ mux_hw = _get_stm32_mux(dev, base, cfg->mux, lock);
+
+ if (!IS_ERR(mux_hw)) {
+ mux_ops = &clk_mux_ops;
+
+ if (cfg->mux->ops)
+ mux_ops = cfg->mux->ops;
+ }
+ }
- if (cfg->mux)
- mux_hw = _get_stm32_mux(base, cfg->mux);
+ if (cfg->div) {
+ div_hw = _get_stm32_div(dev, base, cfg->div, lock);
- if (cfg->div)
- div_hw = _get_stm32_div(base, cfg->div);
+ if (!IS_ERR(div_hw)) {
+ div_ops = &clk_divider_ops;
+
+ if (cfg->div->ops)
+ div_ops = cfg->div->ops;
+ }
+ }
if (cfg->gate) {
- gate = _get_stm32_gate(base, cfg->gate);
- gate_hw = &gate->clk;
+ gate_hw = _get_stm32_gate(dev, base, cfg->gate, lock);
+
+ if (!IS_ERR(gate_hw)) {
+ gate_ops = &clk_gate_ops;
+
+ if (cfg->gate->ops)
+ gate_ops = cfg->gate->ops;
+ }
}
- return clk_register_composite(name, parent_names, num_parents,
- mux_hw, div_hw, gate_hw, flags);
+ return clk_hw_register_composite(dev, name, parent_names, num_parents,
+ mux_hw, mux_ops, div_hw, div_ops,
+ gate_hw, gate_ops, flags);
}
#define to_clk_mgate(_gate) container_of(_gate, struct stm32_clk_mgate, gate)
-static int mp1_mgate_clk_enable(struct clk *clk)
+static int mp1_mgate_clk_enable(struct clk_hw *hw)
{
- struct clk_gate *gate = to_clk_gate(clk);
+ struct clk_gate *gate = to_clk_gate(hw);
struct stm32_clk_mgate *clk_mgate = to_clk_mgate(gate);
clk_mgate->mgate->flag |= clk_mgate->mask;
- mp1_gate_clk_enable(clk);
+ mp1_gate_clk_enable(hw);
return 0;
}
-static void mp1_mgate_clk_disable(struct clk *clk)
+static void mp1_mgate_clk_disable(struct clk_hw *hw)
{
- struct clk_gate *gate = to_clk_gate(clk);
+ struct clk_gate *gate = to_clk_gate(hw);
struct stm32_clk_mgate *clk_mgate = to_clk_mgate(gate);
clk_mgate->mgate->flag &= ~clk_mgate->mask;
if (clk_mgate->mgate->flag == 0)
- mp1_gate_clk_disable(clk);
+ mp1_gate_clk_disable(hw);
}
static const struct clk_ops mp1_mgate_clk_ops = {
@@ -633,43 +697,32 @@ static const struct clk_ops mp1_mgate_clk_ops = {
#define to_clk_mmux(_mux) container_of(_mux, struct stm32_clk_mmux, mux)
-static int clk_mmux_get_parent(struct clk *clk)
+static int clk_mmux_get_parent(struct clk_hw *hw)
{
- return clk_mux_ops.get_parent(clk);
+ return clk_mux_ops.get_parent(hw);
}
-static int clk_mmux_set_parent(struct clk *clk, u8 index)
+static int clk_mmux_set_parent(struct clk_hw *hw, u8 index)
{
- struct clk_mux *mux = to_clk_mux(clk);
- struct stm32_clk_mmux *clk_mmux = to_clk_mmux(mux);
- struct clk *parent;
- int ret, n;
-
- ret = clk_mux_ops.set_parent(clk, index);
- if (ret)
- return ret;
-
- parent = clk_get_parent(clk);
-
- for (n = 0; n < clk_mmux->mmux->nbr_clk; n++)
- clk_set_parent(clk_mmux->mmux->hws[n], parent);
-
- return 0;
+ return clk_mux_ops.set_parent(hw, index);
}
static const struct clk_ops clk_mmux_ops = {
.get_parent = clk_mmux_get_parent,
.set_parent = clk_mmux_set_parent,
+ .round_rate = clk_mux_round_rate,
};
/* STM32 PLL */
struct stm32_pll_obj {
+ /* lock pll enable/disable registers */
+ spinlock_t *lock;
void __iomem *reg;
- const char *parent;
- struct clk clk;
+ struct clk_hw hw;
+ struct clk_mux mux;
};
-#define to_pll(clk) container_of(clk, struct stm32_pll_obj, clk)
+#define to_pll(_hw) container_of(_hw, struct stm32_pll_obj, hw)
#define PLL_ON BIT(0)
#define PLL_RDY BIT(1)
@@ -681,29 +734,34 @@ struct stm32_pll_obj {
#define FRAC_MASK 0x1FFF
#define FRAC_SHIFT 3
#define FRACLE BIT(16)
+#define PLL_MUX_SHIFT 0
+#define PLL_MUX_WIDTH 2
-static int __pll_is_enabled(struct clk *clk)
+static int __pll_is_enabled(struct clk_hw *hw)
{
- struct stm32_pll_obj *clk_elem = to_pll(clk);
+ struct stm32_pll_obj *clk_elem = to_pll(hw);
- return readl(clk_elem->reg) & PLL_ON;
+ return readl_relaxed(clk_elem->reg) & PLL_ON;
}
#define TIMEOUT 5
-static int pll_enable(struct clk *clk)
+static int pll_enable(struct clk_hw *hw)
{
- struct stm32_pll_obj *clk_elem = to_pll(clk);
+ struct stm32_pll_obj *clk_elem = to_pll(hw);
u32 reg;
+ unsigned long flags = 0;
unsigned int timeout = TIMEOUT;
int bit_status = 0;
- if (__pll_is_enabled(clk))
+ spin_lock_irqsave(clk_elem->lock, flags);
+
+ if (__pll_is_enabled(hw))
goto unlock;
- reg = readl(clk_elem->reg);
+ reg = readl_relaxed(clk_elem->reg);
reg |= PLL_ON;
- writel(reg, clk_elem->reg);
+ writel_relaxed(reg, clk_elem->reg);
/* We can't use readl_poll_timeout() because we can be blocked if
* someone enables this clock before clocksource changes.
@@ -711,7 +769,7 @@ static int pll_enable(struct clk *clk)
* interruptions and enable op does not allow to be interrupted.
*/
do {
- bit_status = !(readl(clk_elem->reg) & PLL_RDY);
+ bit_status = !(readl_relaxed(clk_elem->reg) & PLL_RDY);
if (bit_status)
udelay(120);
@@ -719,40 +777,47 @@ static int pll_enable(struct clk *clk)
} while (bit_status && --timeout);
unlock:
+ spin_unlock_irqrestore(clk_elem->lock, flags);
+
return bit_status;
}
-static void pll_disable(struct clk *clk)
+static void pll_disable(struct clk_hw *hw)
{
- struct stm32_pll_obj *clk_elem = to_pll(clk);
+ struct stm32_pll_obj *clk_elem = to_pll(hw);
u32 reg;
+ unsigned long flags = 0;
- reg = readl(clk_elem->reg);
+ spin_lock_irqsave(clk_elem->lock, flags);
+
+ reg = readl_relaxed(clk_elem->reg);
reg &= ~PLL_ON;
- writel(reg, clk_elem->reg);
+ writel_relaxed(reg, clk_elem->reg);
+
+ spin_unlock_irqrestore(clk_elem->lock, flags);
}
-static u32 pll_frac_val(struct clk *clk)
+static u32 pll_frac_val(struct clk_hw *hw)
{
- struct stm32_pll_obj *clk_elem = to_pll(clk);
+ struct stm32_pll_obj *clk_elem = to_pll(hw);
u32 reg, frac = 0;
- reg = readl(clk_elem->reg + FRAC_OFFSET);
+ reg = readl_relaxed(clk_elem->reg + FRAC_OFFSET);
if (reg & FRACLE)
frac = (reg >> FRAC_SHIFT) & FRAC_MASK;
return frac;
}
-static unsigned long pll_recalc_rate(struct clk *clk,
+static unsigned long pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct stm32_pll_obj *clk_elem = to_pll(clk);
+ struct stm32_pll_obj *clk_elem = to_pll(hw);
u32 reg;
u32 frac, divm, divn;
u64 rate, rate_frac = 0;
- reg = readl(clk_elem->reg + 4);
+ reg = readl_relaxed(clk_elem->reg + 4);
divm = ((reg >> DIVM_SHIFT) & DIVM_MASK) + 1;
divn = ((reg >> DIVN_SHIFT) & DIVN_MASK) + 1;
@@ -760,7 +825,7 @@ static unsigned long pll_recalc_rate(struct clk *clk,
do_div(rate, divm);
- frac = pll_frac_val(clk);
+ frac = pll_frac_val(hw);
if (frac) {
rate_frac = (u64)parent_rate * (u64)frac;
do_div(rate_frac, (divm * 8192));
@@ -769,78 +834,89 @@ static unsigned long pll_recalc_rate(struct clk *clk,
return rate + rate_frac;
}
-static int pll_is_enabled(struct clk *clk)
+static int pll_get_parent(struct clk_hw *hw)
{
- int ret;
+ struct stm32_pll_obj *clk_elem = to_pll(hw);
+ struct clk_hw *mux_hw = &clk_elem->mux.hw;
- ret = __pll_is_enabled(clk);
+ mux_hw->clk = hw->clk;
- return ret;
+ return clk_mux_ops.get_parent(mux_hw);
}
static const struct clk_ops pll_ops = {
.enable = pll_enable,
.disable = pll_disable,
.recalc_rate = pll_recalc_rate,
- .is_enabled = pll_is_enabled,
+ .is_enabled = __pll_is_enabled,
+ .get_parent = pll_get_parent,
};
-static struct clk *clk_register_pll(const char *name,
- const char *parent_name,
- void __iomem *reg,
- unsigned long flags)
+static struct clk_hw *clk_register_pll(struct device *dev, const char *name,
+ const char * const *parent_names,
+ int num_parents,
+ void __iomem *reg,
+ void __iomem *mux_reg,
+ unsigned long flags,
+ spinlock_t *lock)
{
struct stm32_pll_obj *element;
- struct clk *clk;
+ struct clk_init_data init;
+ struct clk_hw *hw;
int err;
element = kzalloc(sizeof(*element), GFP_KERNEL);
if (!element)
return ERR_PTR(-ENOMEM);
- element->parent = parent_name;
-
- clk = &element->clk;
+ init.name = name;
+ init.ops = &pll_ops;
+ init.flags = flags;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
- clk->name = name;
- clk->ops = &pll_ops;
- clk->flags = flags;
- clk->parent_names = &element->parent;
- clk->num_parents = 1;
+ element->mux.lock = lock;
+ element->mux.reg = mux_reg;
+ element->mux.shift = PLL_MUX_SHIFT;
+ element->mux.width = PLL_MUX_WIDTH;
+ element->mux.flags = CLK_MUX_READ_ONLY;
+ element->mux.reg = mux_reg;
+ element->hw.init = &init;
element->reg = reg;
+ element->lock = lock;
- err = clk_register(clk);
+ hw = &element->hw;
+ err = clk_hw_register(dev, hw);
- if (err) {
- kfree(element);
+ if (err)
return ERR_PTR(err);
- }
- return clk;
+ return hw;
}
/* Kernel Timer */
struct timer_cker {
+ /* lock the kernel output divider register */
+ spinlock_t *lock;
void __iomem *apbdiv;
void __iomem *timpre;
- const char *parent;
- struct clk clk;
+ struct clk_hw hw;
};
-#define to_timer_cker(_hw) container_of(_hw, struct timer_cker, clk)
+#define to_timer_cker(_hw) container_of(_hw, struct timer_cker, hw)
#define APB_DIV_MASK 0x07
#define TIM_PRE_MASK 0x01
-static unsigned long __bestmult(struct clk *clk, unsigned long rate,
+static unsigned long __bestmult(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct timer_cker *tim_ker = to_timer_cker(clk);
+ struct timer_cker *tim_ker = to_timer_cker(hw);
u32 prescaler;
unsigned int mult = 0;
- prescaler = readl(tim_ker->apbdiv) & APB_DIV_MASK;
+ prescaler = readl_relaxed(tim_ker->apbdiv) & APB_DIV_MASK;
if (prescaler < 2)
return 1;
@@ -852,47 +928,51 @@ static unsigned long __bestmult(struct clk *clk, unsigned long rate,
return mult;
}
-static long timer_ker_round_rate(struct clk *clk, unsigned long rate,
+static long timer_ker_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
- unsigned long factor = __bestmult(clk, rate, *parent_rate);
+ unsigned long factor = __bestmult(hw, rate, *parent_rate);
return *parent_rate * factor;
}
-static int timer_ker_set_rate(struct clk *clk, unsigned long rate,
+static int timer_ker_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct timer_cker *tim_ker = to_timer_cker(clk);
- unsigned long factor = __bestmult(clk, rate, parent_rate);
+ struct timer_cker *tim_ker = to_timer_cker(hw);
+ unsigned long flags = 0;
+ unsigned long factor = __bestmult(hw, rate, parent_rate);
int ret = 0;
+ spin_lock_irqsave(tim_ker->lock, flags);
+
switch (factor) {
case 1:
break;
case 2:
- writel(0, tim_ker->timpre);
+ writel_relaxed(0, tim_ker->timpre);
break;
case 4:
- writel(1, tim_ker->timpre);
+ writel_relaxed(1, tim_ker->timpre);
break;
default:
ret = -EINVAL;
}
+ spin_unlock_irqrestore(tim_ker->lock, flags);
return ret;
}
-static unsigned long timer_ker_recalc_rate(struct clk *hw,
+static unsigned long timer_ker_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct timer_cker *tim_ker = to_timer_cker(hw);
u32 prescaler, timpre;
u32 mul;
- prescaler = readl(tim_ker->apbdiv) & APB_DIV_MASK;
+ prescaler = readl_relaxed(tim_ker->apbdiv) & APB_DIV_MASK;
- timpre = readl(tim_ker->timpre) & TIM_PRE_MASK;
+ timpre = readl_relaxed(tim_ker->timpre) & TIM_PRE_MASK;
if (!prescaler)
return parent_rate;
@@ -909,51 +989,59 @@ static const struct clk_ops timer_ker_ops = {
};
-static struct clk *clk_register_cktim(const char *name,
+static struct clk_hw *clk_register_cktim(struct device *dev, const char *name,
const char *parent_name,
unsigned long flags,
void __iomem *apbdiv,
- void __iomem *timpre)
+ void __iomem *timpre,
+ spinlock_t *lock)
{
struct timer_cker *tim_ker;
- struct clk *clk;
+ struct clk_init_data init;
+ struct clk_hw *hw;
int err;
tim_ker = kzalloc(sizeof(*tim_ker), GFP_KERNEL);
if (!tim_ker)
return ERR_PTR(-ENOMEM);
- clk = &tim_ker->clk;
- tim_ker->parent = parent_name;
- clk->name = name;
- clk->parent_names = &tim_ker->parent;
- clk->num_parents = 1;
- clk->ops = &timer_ker_ops;
- clk->flags = flags;
+ init.name = name;
+ init.ops = &timer_ker_ops;
+ init.flags = flags;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ tim_ker->hw.init = &init;
+ tim_ker->lock = lock;
tim_ker->apbdiv = apbdiv;
tim_ker->timpre = timpre;
- err = clk_register(clk);
- if (err) {
- kfree(tim_ker);
+ hw = &tim_ker->hw;
+ err = clk_hw_register(dev, hw);
+
+ if (err)
return ERR_PTR(err);
- }
- return clk;
+ return hw;
}
struct stm32_pll_cfg {
u32 offset;
+ u32 muxoff;
};
-static struct clk *_clk_register_pll(void __iomem *base,
- const struct clock_config *cfg)
+static struct clk_hw *_clk_register_pll(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
+ const struct clock_config *cfg)
{
struct stm32_pll_cfg *stm_pll_cfg = cfg->cfg;
- return clk_register_pll(cfg->name, cfg->parent_name,
- base + stm_pll_cfg->offset, cfg->flags);
+ return clk_register_pll(dev, cfg->name, cfg->parent_names,
+ cfg->num_parents,
+ base + stm_pll_cfg->offset,
+ base + stm_pll_cfg->muxoff,
+ cfg->flags, lock);
}
struct stm32_cktim_cfg {
@@ -961,31 +1049,42 @@ struct stm32_cktim_cfg {
u32 offset_timpre;
};
-static struct clk *_clk_register_cktim(void __iomem *base,
- const struct clock_config *cfg)
+static struct clk_hw *_clk_register_cktim(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
+ const struct clock_config *cfg)
{
struct stm32_cktim_cfg *cktim_cfg = cfg->cfg;
- return clk_register_cktim(cfg->name, cfg->parent_name, cfg->flags,
+ return clk_register_cktim(dev, cfg->name, cfg->parent_name, cfg->flags,
cktim_cfg->offset_apbdiv + base,
- cktim_cfg->offset_timpre + base);
+ cktim_cfg->offset_timpre + base, lock);
}
-static struct clk *
-_clk_stm32_register_gate(void __iomem *base,
+static struct clk_hw *
+_clk_stm32_register_gate(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
const struct clock_config *cfg)
{
- return clk_stm32_register_gate_ops(cfg->name, cfg->parent_name,
- cfg->flags, base, cfg->cfg);
+ return clk_stm32_register_gate_ops(dev,
+ cfg->name,
+ cfg->parent_name,
+ cfg->flags,
+ base,
+ cfg->cfg,
+ lock);
}
-static struct clk *
-_clk_stm32_register_composite(void __iomem *base,
+static struct clk_hw *
+_clk_stm32_register_composite(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
const struct clock_config *cfg)
{
- return clk_stm32_register_composite(cfg->name, cfg->parent_names,
+ return clk_stm32_register_composite(dev, cfg->name, cfg->parent_names,
cfg->num_parents, base, cfg->cfg,
- cfg->flags);
+ cfg->flags, lock);
}
#define GATE(_id, _name, _parent, _flags, _offset, _bit_idx, _gate_flags)\
@@ -1052,14 +1151,16 @@ _clk_stm32_register_composite(void __iomem *base,
.func = _clk_hw_register_mux,\
}
-#define PLL(_id, _name, _parent, _flags, _offset)\
+#define PLL(_id, _name, _parents, _flags, _offset_p, _offset_mux)\
{\
.id = _id,\
.name = _name,\
- .parent_name = _parent,\
- .flags = _flags,\
+ .parent_names = _parents,\
+ .num_parents = ARRAY_SIZE(_parents),\
+ .flags = CLK_IGNORE_UNUSED | (_flags),\
.cfg = &(struct stm32_pll_cfg) {\
- .offset = _offset,\
+ .offset = _offset_p,\
+ .muxoff = _offset_mux,\
},\
.func = _clk_register_pll,\
}
@@ -1092,13 +1193,14 @@ _clk_stm32_register_composite(void __iomem *base,
.func = _clk_stm32_register_gate,\
}
-#define _STM32_GATE(_gate_offset, _gate_bit_idx, _gate_flags, _ops)\
+#define _STM32_GATE(_gate_offset, _gate_bit_idx, _gate_flags, _mgate, _ops)\
(&(struct stm32_gate_cfg) {\
&(struct gate_cfg) {\
.reg_off = _gate_offset,\
.bit_idx = _gate_bit_idx,\
.gate_flags = _gate_flags,\
},\
+ .mgate = _mgate,\
.ops = _ops,\
})
@@ -1107,11 +1209,11 @@ _clk_stm32_register_composite(void __iomem *base,
#define _GATE(_gate_offset, _gate_bit_idx, _gate_flags)\
_STM32_GATE(_gate_offset, _gate_bit_idx, _gate_flags,\
- NULL)\
+ NULL, NULL)\
#define _GATE_MP1(_gate_offset, _gate_bit_idx, _gate_flags)\
_STM32_GATE(_gate_offset, _gate_bit_idx, _gate_flags,\
- &mp1_gate_clk_ops)\
+ NULL, &mp1_gate_clk_ops)\
#define _MGATE_MP1(_mgate)\
.gate = &per_gate_cfg[_mgate]
@@ -1184,10 +1286,11 @@ _clk_stm32_register_composite(void __iomem *base,
MGATE_MP1(_id, _name, _parent, _flags, _mgate)
#define KCLK(_id, _name, _parents, _flags, _mgate, _mmux)\
- COMPOSITE(_id, _name, _parents, CLK_OPS_PARENT_ENABLE | _flags,\
- _MGATE_MP1(_mgate),\
- _MMUX(_mmux),\
- _NO_DIV)
+ COMPOSITE(_id, _name, _parents, CLK_OPS_PARENT_ENABLE |\
+ CLK_SET_RATE_NO_REPARENT | _flags,\
+ _MGATE_MP1(_mgate),\
+ _MMUX(_mmux),\
+ _NO_DIV)
enum {
G_SAI1,
@@ -1299,6 +1402,7 @@ enum {
G_CRYP1,
G_HASH1,
G_BKPSRAM,
+ G_DDRPERFM,
G_LAST
};
@@ -1385,6 +1489,7 @@ static struct stm32_gate_cfg per_gate_cfg[G_LAST] = {
K_GATE(G_STGENRO, RCC_APB4ENSETR, 20, 0),
K_MGATE(G_USBPHY, RCC_APB4ENSETR, 16, 0),
K_GATE(G_IWDG2, RCC_APB4ENSETR, 15, 0),
+ K_GATE(G_DDRPERFM, RCC_APB4ENSETR, 8, 0),
K_MGATE(G_DSI, RCC_APB4ENSETR, 4, 0),
K_MGATE(G_LTDC, RCC_APB4ENSETR, 0, 0),
@@ -1526,7 +1631,7 @@ static const struct stm32_mux_cfg ker_mux_cfg[M_LAST] = {
K_MMUX(M_ETHCK, RCC_ETHCKSELR, 0, 2, 0),
K_MMUX(M_I2C46, RCC_I2C46CKSELR, 0, 3, 0),
- /* Kernel simple mux */
+ /* Kernel simple mux */
K_MUX(M_RNG2, RCC_RNG2CKSELR, 0, 2, 0),
K_MUX(M_SDMMC3, RCC_SDMMC3CKSELR, 0, 3, 0),
K_MUX(M_FMC, RCC_FMCCKSELR, 0, 2, 0),
@@ -1552,34 +1657,26 @@ static const struct stm32_mux_cfg ker_mux_cfg[M_LAST] = {
};
static const struct clock_config stm32mp1_clock_cfg[] = {
- /* Oscillator divider */
- DIV(NO_ID, "clk-hsi-div", "clk-hsi", 0, RCC_HSICFGR, 0, 2,
- CLK_DIVIDER_READ_ONLY),
-
/* External / Internal Oscillators */
GATE_MP1(CK_HSE, "ck_hse", "clk-hse", 0, RCC_OCENSETR, 8, 0),
- GATE_MP1(CK_CSI, "ck_csi", "clk-csi", 0, RCC_OCENSETR, 4, 0),
- GATE_MP1(CK_HSI, "ck_hsi", "clk-hsi-div", 0, RCC_OCENSETR, 0, 0),
+ /* ck_csi is used by IO compensation and should be critical */
+ GATE_MP1(CK_CSI, "ck_csi", "clk-csi", CLK_IS_CRITICAL,
+ RCC_OCENSETR, 4, 0),
+ COMPOSITE(CK_HSI, "ck_hsi", PARENT("clk-hsi"), 0,
+ _GATE_MP1(RCC_OCENSETR, 0, 0),
+ _NO_MUX,
+ _DIV(RCC_HSICFGR, 0, 2, CLK_DIVIDER_POWER_OF_TWO |
+ CLK_DIVIDER_READ_ONLY, NULL)),
GATE(CK_LSI, "ck_lsi", "clk-lsi", 0, RCC_RDLSICR, 0, 0),
GATE(CK_LSE, "ck_lse", "clk-lse", 0, RCC_BDCR, 0, 0),
FIXED_FACTOR(CK_HSE_DIV2, "clk-hse-div2", "ck_hse", 0, 1, 2),
- /* ref clock pll */
- MUX(NO_ID, "ref1", ref12_parents, CLK_OPS_PARENT_ENABLE, RCC_RCK12SELR,
- 0, 2, CLK_MUX_READ_ONLY),
-
- MUX(NO_ID, "ref3", ref3_parents, CLK_OPS_PARENT_ENABLE, RCC_RCK3SELR,
- 0, 2, CLK_MUX_READ_ONLY),
-
- MUX(NO_ID, "ref4", ref4_parents, CLK_OPS_PARENT_ENABLE, RCC_RCK4SELR,
- 0, 2, CLK_MUX_READ_ONLY),
-
/* PLLs */
- PLL(PLL1, "pll1", "ref1", CLK_IGNORE_UNUSED, RCC_PLL1CR),
- PLL(PLL2, "pll2", "ref1", CLK_IGNORE_UNUSED, RCC_PLL2CR),
- PLL(PLL3, "pll3", "ref3", CLK_IGNORE_UNUSED, RCC_PLL3CR),
- PLL(PLL4, "pll4", "ref4", CLK_IGNORE_UNUSED, RCC_PLL4CR),
+ PLL(PLL1, "pll1", ref12_parents, 0, RCC_PLL1CR, RCC_RCK12SELR),
+ PLL(PLL2, "pll2", ref12_parents, 0, RCC_PLL2CR, RCC_RCK12SELR),
+ PLL(PLL3, "pll3", ref3_parents, 0, RCC_PLL3CR, RCC_RCK3SELR),
+ PLL(PLL4, "pll4", ref4_parents, 0, RCC_PLL4CR, RCC_RCK4SELR),
/* ODF */
COMPOSITE(PLL1_P, "pll1_p", PARENT("pll1"), 0,
@@ -1794,6 +1891,7 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
PCLK(CRC1, "crc1", "ck_axi", 0, G_CRC1),
PCLK(USBH, "usbh", "ck_axi", 0, G_USBH),
PCLK(ETHSTP, "ethstp", "ck_axi", 0, G_ETHSTP),
+ PCLK(DDRPERFM, "ddrperfm", "pclk4", 0, G_DDRPERFM),
/* Kernel clocks */
KCLK(SDMMC1_K, "sdmmc1_k", sdmmc12_src, 0, G_SDMMC1, M_SDMMC12),
@@ -1850,18 +1948,17 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
MGATE_MP1(GPU_K, "gpu_k", "pll2_q", 0, G_GPU),
MGATE_MP1(DAC12_K, "dac12_k", "ck_lsi", 0, G_DAC12),
- COMPOSITE(ETHPTP_K, "ethptp_k", eth_src, CLK_OPS_PARENT_ENABLE,
+ COMPOSITE(ETHPTP_K, "ethptp_k", eth_src, CLK_OPS_PARENT_ENABLE |
+ CLK_SET_RATE_NO_REPARENT,
_NO_GATE,
_MMUX(M_ETHCK),
_DIV(RCC_ETHCKSELR, 4, 4, 0, NULL)),
/* RTC clock */
- DIV(NO_ID, "ck_hse_rtc", "ck_hse", 0, RCC_RTCDIVR, 0, 7, 0),
-
COMPOSITE(RTC, "ck_rtc", rtc_src, CLK_OPS_PARENT_ENABLE |
- CLK_SET_RATE_PARENT,
- _GATE(RCC_BDCR, 20, 0),
- _MUX(RCC_BDCR, 16, 2, 0),
+ CLK_SET_RATE_PARENT,
+ _NO_GATE,
+ _NO_MUX,
_NO_DIV),
/* MCO clocks */
@@ -1887,16 +1984,76 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
_DIV(RCC_DBGCFGR, 0, 3, 0, ck_trace_div_table)),
};
-struct stm32_clock_match_data {
+static const u32 stm32mp1_clock_secured[] = {
+ CK_HSE,
+ CK_HSI,
+ CK_CSI,
+ CK_LSI,
+ CK_LSE,
+ PLL1,
+ PLL2,
+ PLL1_P,
+ PLL2_P,
+ PLL2_Q,
+ PLL2_R,
+ CK_MPU,
+ CK_AXI,
+ SPI6,
+ I2C4,
+ I2C6,
+ USART1,
+ RTCAPB,
+ TZC1,
+ TZC2,
+ TZPC,
+ IWDG1,
+ BSEC,
+ STGEN,
+ GPIOZ,
+ CRYP1,
+ HASH1,
+ RNG1,
+ BKPSRAM,
+ RNG1_K,
+ STGEN_K,
+ SPI6_K,
+ I2C4_K,
+ I2C6_K,
+ USART1_K,
+ RTC,
+};
+
+static bool stm32_check_security(const struct clock_config *cfg)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(stm32mp1_clock_secured); i++)
+ if (cfg->id == stm32mp1_clock_secured[i])
+ return true;
+ return false;
+}
+
+struct stm32_rcc_match_data {
const struct clock_config *cfg;
unsigned int num;
unsigned int maxbinding;
+ u32 clear_offset;
+ bool (*check_security)(const struct clock_config *cfg);
+};
+
+static struct stm32_rcc_match_data stm32mp1_data = {
+ .cfg = stm32mp1_clock_cfg,
+ .num = ARRAY_SIZE(stm32mp1_clock_cfg),
+ .maxbinding = STM32MP1_LAST_CLK,
+ .clear_offset = RCC_CLR,
};
-static struct stm32_clock_match_data stm32mp1_data = {
+static struct stm32_rcc_match_data stm32mp1_data_secure = {
.cfg = stm32mp1_clock_cfg,
.num = ARRAY_SIZE(stm32mp1_clock_cfg),
.maxbinding = STM32MP1_LAST_CLK,
+ .clear_offset = RCC_CLR,
+ .check_security = &stm32_check_security
};
static const struct of_device_id stm32mp1_match_data[] = {
@@ -1904,85 +2061,283 @@ static const struct of_device_id stm32mp1_match_data[] = {
.compatible = "st,stm32mp1-rcc",
.data = &stm32mp1_data,
},
+ {
+ .compatible = "st,stm32mp1-rcc-secure",
+ .data = &stm32mp1_data_secure,
+ },
{ }
};
+MODULE_DEVICE_TABLE(of, stm32mp1_match_data);
-static int stm32_register_hw_clk(struct clk_onecell_data *clk_data,
- void __iomem *base,
+static int stm32_register_hw_clk(struct device *dev,
+ struct clk_hw_onecell_data *clk_data,
+ void __iomem *base, spinlock_t *lock,
const struct clock_config *cfg)
{
- struct clk *clk = ERR_PTR(-ENOENT);
+ struct clk_hw **hws;
+ struct clk_hw *hw = ERR_PTR(-ENOENT);
+
+ hws = clk_data->hws;
if (cfg->func)
- clk = (*cfg->func)(base, cfg);
+ hw = (*cfg->func)(dev, clk_data, base, lock, cfg);
- if (IS_ERR(clk)) {
+ if (IS_ERR(hw)) {
pr_err("Unable to register %s\n", cfg->name);
- return PTR_ERR(clk);
+ return PTR_ERR(hw);
}
if (cfg->id != NO_ID)
- clk_data->clks[cfg->id] = clk;
+ hws[cfg->id] = hw;
return 0;
}
-static int stm32_rcc_init(struct device_node *np,
- void __iomem *base,
- const struct of_device_id *match_data)
+#define STM32_RESET_ID_MASK GENMASK(15, 0)
+
+struct stm32_reset_data {
+ /* reset lock */
+ spinlock_t lock;
+ struct reset_controller_dev rcdev;
+ void __iomem *membase;
+ u32 clear_offset;
+};
+
+static inline struct stm32_reset_data *
+to_stm32_reset_data(struct reset_controller_dev *rcdev)
{
- struct clk_onecell_data *clk_data;
- struct clk **clks;
- const struct of_device_id *match;
- const struct stm32_clock_match_data *data;
- int err, n, max_binding;
+ return container_of(rcdev, struct stm32_reset_data, rcdev);
+}
- match = of_match_node(match_data, np);
- if (!match) {
- pr_err("%s: match data not found\n", __func__);
- return -ENODEV;
+static int stm32_reset_update(struct reset_controller_dev *rcdev,
+ unsigned long id, bool assert)
+{
+ struct stm32_reset_data *data = to_stm32_reset_data(rcdev);
+ int reg_width = sizeof(u32);
+ int bank = id / (reg_width * BITS_PER_BYTE);
+ int offset = id % (reg_width * BITS_PER_BYTE);
+
+ if (data->clear_offset) {
+ void __iomem *addr;
+
+ addr = data->membase + (bank * reg_width);
+ if (!assert)
+ addr += data->clear_offset;
+
+ writel(BIT(offset), addr);
+
+ } else {
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&data->lock, flags);
+
+ reg = readl(data->membase + (bank * reg_width));
+
+ if (assert)
+ reg |= BIT(offset);
+ else
+ reg &= ~BIT(offset);
+
+ writel(reg, data->membase + (bank * reg_width));
+
+ spin_unlock_irqrestore(&data->lock, flags);
}
- data = match->data;
+ return 0;
+}
+
+static int stm32_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return stm32_reset_update(rcdev, id, true);
+}
+
+static int stm32_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return stm32_reset_update(rcdev, id, false);
+}
+
+static int stm32_reset_status(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct stm32_reset_data *data = to_stm32_reset_data(rcdev);
+ int reg_width = sizeof(u32);
+ int bank = id / (reg_width * BITS_PER_BYTE);
+ int offset = id % (reg_width * BITS_PER_BYTE);
+ u32 reg;
+
+ reg = readl(data->membase + (bank * reg_width));
- max_binding = data->maxbinding;
+ return !!(reg & BIT(offset));
+}
- clk_data = xzalloc(sizeof(*clk_data));
- clk_data->clks = xzalloc(sizeof(void *) * max_binding);
- clk_data->clk_num = max_binding;
+static const struct reset_control_ops stm32_reset_ops = {
+ .assert = stm32_reset_assert,
+ .deassert = stm32_reset_deassert,
+ .status = stm32_reset_status,
+};
- clks = clk_data->clks;
+static int stm32_rcc_reset_init(struct device *dev, void __iomem *base,
+ const struct of_device_id *match)
+{
+ const struct stm32_rcc_match_data *data = match->data;
+ struct stm32_reset_data *reset_data = NULL;
+
+ reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
+ if (!reset_data)
+ return -ENOMEM;
+
+ reset_data->membase = base;
+ reset_data->rcdev.ops = &stm32_reset_ops;
+ reset_data->rcdev.of_node = dev_of_node(dev);
+ reset_data->rcdev.nr_resets = STM32_RESET_ID_MASK;
+ reset_data->clear_offset = data->clear_offset;
+
+ return reset_controller_register(&reset_data->rcdev);
+}
+
+static int stm32_rcc_clock_init(struct device *dev, void __iomem *base,
+ const struct of_device_id *match)
+{
+ const struct stm32_rcc_match_data *data = match->data;
+ struct clk_hw_onecell_data *clk_data;
+ struct clk_hw **hws;
+ int err, n, max_binding;
+
+ max_binding = data->maxbinding;
+
+ clk_data = kzalloc(struct_size(clk_data, hws, max_binding),
+ GFP_KERNEL);
+ if (!clk_data)
+ return -ENOMEM;
+
+ clk_data->num = max_binding;
+
+ hws = clk_data->hws;
for (n = 0; n < max_binding; n++)
- clks[n] = ERR_PTR(-ENOENT);
+ hws[n] = ERR_PTR(-ENOENT);
for (n = 0; n < data->num; n++) {
- err = stm32_register_hw_clk(clk_data, base,
+ if (data->check_security && data->check_security(&data->cfg[n]))
+ continue;
+
+ err = stm32_register_hw_clk(dev, clk_data, base, &rlock,
&data->cfg[n]);
if (err) {
- pr_err("%s: can't register %s\n", __func__,
- data->cfg[n].name);
-
- kfree(clk_data);
+ dev_err(dev, "Can't register clk %s: %d\n",
+ data->cfg[n].name, err);
return err;
}
}
- return of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+ return of_clk_add_hw_provider(dev_of_node(dev), of_clk_hw_onecell_get, clk_data);
}
-static void stm32mp1_rcc_init(struct device_node *np)
+static int stm32_rcc_init(struct device *dev, void __iomem *base,
+ const struct of_device_id *match_data)
+{
+ const struct of_device_id *match;
+ int err;
+
+ match = of_match_node(match_data, dev_of_node(dev));
+ if (!match) {
+ dev_err(dev, "match data not found\n");
+ return -ENODEV;
+ }
+
+ /* RCC Reset Configuration */
+ err = stm32_rcc_reset_init(dev, base, match);
+ if (err) {
+ pr_err("stm32mp1 reset failed to initialize\n");
+ return err;
+ }
+
+ /* RCC Clock Configuration */
+ err = stm32_rcc_clock_init(dev, base, match);
+ if (err) {
+ pr_err("stm32mp1 clock failed to initialize\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int stm32mp1_rcc_init(struct device *dev)
{
void __iomem *base;
+ int ret;
- base = of_iomap(np, 0);
+ base = of_iomap(dev_of_node(dev), 0);
if (!base) {
- pr_err("%pOFn: unable to map resource", np);
- return;
+ dev_err(dev, "unable to map resource\n");
+ return -ENOMEM;
}
- stm32_rcc_init(np, base, stm32mp1_match_data);
+ ret = stm32_rcc_init(dev, base, stm32mp1_match_data);
+ if (ret)
+ return ret;
+
+ stm32mp_system_restart_init(dev);
+ return 0;
+}
+
+static int get_clock_deps(struct device *dev)
+{
+ static const char * const clock_deps_name[] = {
+ "hsi", "hse", "csi", "lsi", "lse",
+ };
+ size_t deps_size = sizeof(struct clk *) * ARRAY_SIZE(clock_deps_name);
+ struct clk **clk_deps;
+ int i;
+
+ clk_deps = kzalloc(deps_size, GFP_KERNEL);
+ if (!clk_deps)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(clock_deps_name); i++) {
+ struct clk *clk = of_clk_get_by_name(dev_of_node(dev),
+ clock_deps_name[i]);
+
+ if (IS_ERR(clk)) {
+ if (PTR_ERR(clk) != -EINVAL && PTR_ERR(clk) != -ENOENT)
+ return PTR_ERR(clk);
+ } else {
+ /* Device gets a reference count on the clock */
+ clk_deps[i] = clk_get(dev, __clk_get_name(clk));
+ clk_put(clk);
+ }
+ }
+
+ return 0;
+}
+
+static int stm32mp1_rcc_clocks_probe(struct device *dev)
+{
+ int ret = get_clock_deps(dev);
+
+ if (!ret)
+ ret = stm32mp1_rcc_init(dev);
+
+ return ret;
+}
+
+static void stm32mp1_rcc_clocks_remove(struct device *dev)
+{
+ struct device_node *child, *np = dev_of_node(dev);
+
+ for_each_available_child_of_node(np, child)
+ of_clk_del_provider(child);
}
-CLK_OF_DECLARE_DRIVER(stm32mp1_rcc, "st,stm32mp1-rcc", stm32mp1_rcc_init);
+static struct driver stm32mp1_rcc_clocks_driver = {
+ .name = "stm32mp1_rcc",
+ .of_compatible = stm32mp1_match_data,
+ .probe = stm32mp1_rcc_clocks_probe,
+ .remove = stm32mp1_rcc_clocks_remove,
+};
+
+core_platform_driver(stm32mp1_rcc_clocks_driver);
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 4386c95aa9..d3f5d5e838 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -36,6 +36,7 @@ static void clk_parent_disable(struct clk *clk)
int clk_enable(struct clk *clk)
{
+ struct clk_hw *hw;
int ret;
if (!clk)
@@ -44,13 +45,15 @@ int clk_enable(struct clk *clk)
if (IS_ERR(clk))
return PTR_ERR(clk);
+ hw = clk_to_clk_hw(clk);
+
if (!clk->enable_count) {
ret = clk_parent_enable(clk);
if (ret)
return ret;
if (clk->ops->enable) {
- ret = clk->ops->enable(clk);
+ ret = clk->ops->enable(hw);
if (ret) {
clk_parent_disable(clk);
return ret;
@@ -65,6 +68,8 @@ int clk_enable(struct clk *clk)
void clk_disable(struct clk *clk)
{
+ struct clk_hw *hw;
+
if (!clk)
return;
@@ -81,9 +86,11 @@ void clk_disable(struct clk *clk)
clk->enable_count--;
+ hw = clk_to_clk_hw(clk);
+
if (!clk->enable_count) {
if (clk->ops->disable)
- clk->ops->disable(clk);
+ clk->ops->disable(hw);
clk_parent_disable(clk);
}
@@ -91,6 +98,7 @@ void clk_disable(struct clk *clk)
unsigned long clk_get_rate(struct clk *clk)
{
+ struct clk_hw *hw;
struct clk *parent;
unsigned long parent_rate = 0;
@@ -106,14 +114,22 @@ unsigned long clk_get_rate(struct clk *clk)
if (!IS_ERR_OR_NULL(parent))
parent_rate = clk_get_rate(parent);
+ hw = clk_to_clk_hw(clk);
+
if (clk->ops->recalc_rate)
- return clk->ops->recalc_rate(clk, parent_rate);
+ return clk->ops->recalc_rate(hw, parent_rate);
return parent_rate;
}
+unsigned long clk_hw_get_rate(struct clk_hw *hw)
+{
+ return clk_get_rate(clk_hw_to_clk(hw));
+}
+
long clk_round_rate(struct clk *clk, unsigned long rate)
{
+ struct clk_hw *hw;
unsigned long parent_rate = 0;
struct clk *parent;
@@ -127,14 +143,22 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
if (parent)
parent_rate = clk_get_rate(parent);
+ hw = clk_to_clk_hw(clk);
+
if (clk->ops->round_rate)
- return clk->ops->round_rate(clk, rate, &parent_rate);
+ return clk->ops->round_rate(hw, rate, &parent_rate);
return clk_get_rate(clk);
}
+long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate)
+{
+ return clk_round_rate(&hw->clk, rate);
+}
+
int clk_set_rate(struct clk *clk, unsigned long rate)
{
+ struct clk_hw *hw;
struct clk *parent;
unsigned long parent_rate = 0;
int ret;
@@ -145,9 +169,18 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
if (IS_ERR(clk))
return PTR_ERR(clk);
+ if (clk_get_rate(clk) == clk_round_rate(clk, rate))
+ return 0;
+
if (!clk->ops->set_rate)
return -ENOSYS;
+ if (clk->flags & CLK_SET_RATE_UNGATE) {
+ ret = clk_enable(clk);
+ if (ret)
+ return ret;
+ }
+
parent = clk_get_parent(clk);
if (parent) {
parent_rate = clk_get_rate(parent);
@@ -155,18 +188,70 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
if (clk->flags & CLK_OPS_PARENT_ENABLE) {
ret = clk_enable(parent);
if (ret)
- return ret;
+ goto out;
}
}
- ret = clk->ops->set_rate(clk, rate, parent_rate);
+ hw = clk_to_clk_hw(clk);
+
+ ret = clk->ops->set_rate(hw, rate, parent_rate);
if (parent && clk->flags & CLK_OPS_PARENT_ENABLE)
clk_disable(parent);
+out:
+ if (clk->flags & CLK_SET_RATE_UNGATE)
+ clk_disable(clk);
+
return ret;
}
+int clk_hw_set_rate(struct clk_hw *hw, unsigned long rate)
+{
+ return clk_set_rate(&hw->clk, rate);
+}
+
+static int clk_fetch_parent_index(struct clk *clk,
+ struct clk *parent)
+{
+ int i;
+
+ if (!parent)
+ return -EINVAL;
+
+ for (i = 0; i < clk->num_parents; i++) {
+ if (IS_ERR_OR_NULL(clk->parents[i]))
+ clk->parents[i] = clk_lookup(clk->parent_names[i]);
+
+ if (!IS_ERR_OR_NULL(clk->parents[i]))
+ if (clk->parents[i] == parent)
+ break;
+ }
+
+ if (i == clk->num_parents)
+ return -EINVAL;
+
+ return i;
+}
+
+/**
+ * clk_hw_get_parent_index - return the index of the parent clock
+ * @hw: clk_hw associated with the clk being consumed
+ *
+ * Fetches and returns the index of parent clock. Returns -EINVAL if the given
+ * clock does not have a current parent.
+ */
+int clk_hw_get_parent_index(struct clk_hw *hw)
+{
+ struct clk_hw *parent = clk_hw_get_parent(hw);
+
+ if (WARN_ON(parent == NULL))
+ return -EINVAL;
+
+ return clk_fetch_parent_index(clk_hw_to_clk(hw), clk_hw_to_clk(parent));
+}
+EXPORT_SYMBOL_GPL(clk_hw_get_parent_index);
+
struct clk *clk_lookup(const char *name)
{
struct clk *c;
@@ -184,9 +269,13 @@ struct clk *clk_lookup(const char *name)
int clk_set_parent(struct clk *clk, struct clk *newparent)
{
+ struct clk_hw *hw;
int i, ret;
struct clk *curparent = clk_get_parent(clk);
+ if (!clk || !newparent)
+ return 0;
+
if (IS_ERR(clk))
return PTR_ERR(clk);
if (IS_ERR(newparent))
@@ -197,17 +286,9 @@ int clk_set_parent(struct clk *clk, struct clk *newparent)
if (!clk->ops->set_parent)
return -EINVAL;
- for (i = 0; i < clk->num_parents; i++) {
- if (IS_ERR_OR_NULL(clk->parents[i]))
- clk->parents[i] = clk_lookup(clk->parent_names[i]);
-
- if (!IS_ERR_OR_NULL(clk->parents[i]))
- if (clk->parents[i] == newparent)
- break;
- }
-
- if (i == clk->num_parents)
- return -EINVAL;
+ i = clk_fetch_parent_index(clk, newparent);
+ if (i < 0)
+ return i;
if (clk->enable_count)
clk_enable(newparent);
@@ -217,7 +298,9 @@ int clk_set_parent(struct clk *clk, struct clk *newparent)
clk_enable(newparent);
}
- ret = clk->ops->set_parent(clk, i);
+ hw = clk_to_clk_hw(clk);
+
+ ret = clk->ops->set_parent(hw, i);
if (clk->flags & CLK_OPS_PARENT_ENABLE) {
clk_disable(curparent);
@@ -230,21 +313,49 @@ int clk_set_parent(struct clk *clk, struct clk *newparent)
return ret;
}
+int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *newparent)
+{
+ return clk_set_parent(&hw->clk, &newparent->clk);
+}
+
+static struct clk *clk_get_parent_by_index(struct clk *clk, u8 idx)
+{
+ if (IS_ERR_OR_NULL(clk->parents[idx]))
+ clk->parents[idx] = clk_lookup(clk->parent_names[idx]);
+
+ return clk->parents[idx];
+}
+
+struct clk_hw *
+clk_hw_get_parent_by_index(const struct clk_hw *hw, unsigned int idx)
+{
+ struct clk *clk = clk_hw_to_clk(hw);
+
+ if (!clk || idx >= clk->num_parents || !clk->parents)
+ return NULL;
+
+ return clk_to_clk_hw(clk_get_parent_by_index(clk, idx));
+}
+EXPORT_SYMBOL_GPL(clk_hw_get_parent_by_index);
+
struct clk *clk_get_parent(struct clk *clk)
{
+ struct clk_hw *hw;
int idx;
- if (IS_ERR(clk))
+ if (IS_ERR_OR_NULL(clk))
return clk;
if (!clk->num_parents)
return ERR_PTR(-ENODEV);
+ hw = clk_to_clk_hw(clk);
+
if (clk->num_parents != 1) {
if (!clk->ops->get_parent)
return ERR_PTR(-EINVAL);
- idx = clk->ops->get_parent(clk);
+ idx = clk->ops->get_parent(hw);
if (idx >= clk->num_parents)
return ERR_PTR(-ENODEV);
@@ -252,15 +363,79 @@ struct clk *clk_get_parent(struct clk *clk)
idx = 0;
}
- if (IS_ERR_OR_NULL(clk->parents[idx]))
- clk->parents[idx] = clk_lookup(clk->parent_names[idx]);
+ return clk_get_parent_by_index(clk, idx);
+}
- return clk->parents[idx];
+struct clk_hw *clk_hw_get_parent(struct clk_hw *hw)
+{
+ struct clk *clk = clk_get_parent(clk_hw_to_clk(hw));
+
+ if (IS_ERR(clk))
+ return ERR_CAST(clk);
+
+ return clk_to_clk_hw(clk);
}
-int clk_register(struct clk *clk)
+/**
+ * clk_set_phase - adjust the phase shift of a clock signal
+ * @clk: clock signal source
+ * @degrees: number of degrees the signal is shifted
+ *
+ * Shifts the phase of a clock signal by the specified
+ * degrees. Returns 0 on success, -EERROR otherwise.
+ *
+ * This function makes no distinction about the input or reference
+ * signal that we adjust the clock signal phase against. For example
+ * phase locked-loop clock signal generators we may shift phase with
+ * respect to feedback clock signal input, but for other cases the
+ * clock phase may be shifted with respect to some other, unspecified
+ * signal.
+ *
+ * Additionally the concept of phase shift does not propagate through
+ * the clock tree hierarchy, which sets it apart from clock rates and
+ * clock accuracy. A parent clock phase attribute does not have an
+ * impact on the phase attribute of a child clock.
+ */
+int clk_set_phase(struct clk *clk, int degrees)
{
+ if (!clk)
+ return 0;
+
+ /* sanity check degrees */
+ degrees %= 360;
+ if (degrees < 0)
+ degrees += 360;
+
+ if (!clk->ops->set_phase)
+ return -EINVAL;
+
+ return clk->ops->set_phase(clk_to_clk_hw(clk), degrees);
+}
+
+/**
+ * clk_get_phase - return the phase shift of a clock signal
+ * @clk: clock signal source
+ *
+ * Returns the phase shift of a clock node in degrees, otherwise returns
+ * -EERROR.
+ */
+int clk_get_phase(struct clk *clk)
+{
+ int ret;
+
+ if (!clk->ops->get_phase)
+ return 0;
+
+ ret = clk->ops->get_phase(clk_to_clk_hw(clk));
+
+ return ret;
+}
+
+static int __bclk_register(struct clk *clk)
+{
+ struct clk_hw *hw = clk_to_clk_hw(clk);
struct clk *c;
+ int ret;
list_for_each_entry(c, &clks, list) {
if (!strcmp(c->name, clk->name)) {
@@ -270,19 +445,90 @@ int clk_register(struct clk *clk)
}
}
- clk->parents = xzalloc(sizeof(struct clk *) * clk->num_parents);
-
list_add_tail(&clk->list, &clks);
+ if (clk->ops->init) {
+ ret = clk->ops->init(hw);
+ if (ret)
+ goto out;
+ }
+
if (clk->flags & CLK_IS_CRITICAL)
clk_enable(clk);
return 0;
+out:
+ list_del(&clk->list);
+
+ return ret;
+}
+
+int bclk_register(struct clk *clk)
+{
+ int ret;
+
+ clk->parents = xzalloc(sizeof(struct clk *) * clk->num_parents);
+
+ ret = __bclk_register(clk);
+ if (ret)
+ free(clk->parents);
+
+ return ret;
+}
+
+struct clk *clk_register(struct device *dev, struct clk_hw *hw)
+{
+ struct clk *clk;
+ const struct clk_init_data *init = hw->init;
+ char **parent_names = NULL;
+ int i, ret;
+
+ if (!hw->init)
+ return ERR_PTR(-EINVAL);
+
+ clk = clk_hw_to_clk(hw);
+
+ memset(clk, 0, sizeof(*clk));
+
+ clk->name = xstrdup(init->name);
+ clk->ops = init->ops;
+ clk->num_parents = init->num_parents;
+
+ clk->parents = xzalloc(sizeof(struct clk *) * clk->num_parents);
+
+ if (init->parent_names) {
+ parent_names = xzalloc(init->num_parents * sizeof(char *));
+
+ for (i = 0; i < init->num_parents; i++)
+ parent_names[i] = xstrdup(init->parent_names[i]);
+
+ clk->parent_names = (const char *const*)parent_names;
+
+ } else {
+ for (i = 0; i < init->num_parents; i++)
+ clk->parents[i] = clk_hw_to_clk(init->parent_hws[i]);
+ }
+
+ clk->flags = init->flags;
+
+ ret = __bclk_register(clk);
+ if (ret) {
+ if (parent_names) {
+ for (i = 0; i < init->num_parents; i++)
+ free(parent_names[i]);
+ free(parent_names);
+ }
+ free(clk->parents);
+ return ERR_PTR(ret);
+ }
+
+ return clk;
}
int clk_is_enabled(struct clk *clk)
{
int enabled;
+ struct clk_hw *hw = clk_to_clk_hw(clk);
if (IS_ERR(clk))
return 0;
@@ -291,7 +537,7 @@ int clk_is_enabled(struct clk *clk)
/*
* If we can ask a clk, do it
*/
- enabled = clk->ops->is_enabled(clk);
+ enabled = clk->ops->is_enabled(hw);
} else {
if (clk->ops->enable) {
/*
@@ -320,31 +566,62 @@ int clk_is_enabled(struct clk *clk)
return clk_is_enabled(clk);
}
+int clk_hw_is_enabled(struct clk_hw *hw)
+{
+ return clk_is_enabled(&hw->clk);
+}
+
/*
* Generic struct clk_ops callbacks
*/
-int clk_is_enabled_always(struct clk *clk)
+int clk_is_enabled_always(struct clk_hw *hw)
{
return 1;
}
-long clk_parent_round_rate(struct clk *clk, unsigned long rate,
+long clk_parent_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
+ struct clk *clk = clk_hw_to_clk(hw);
+
if (!(clk->flags & CLK_SET_RATE_PARENT))
return *prate;
return clk_round_rate(clk_get_parent(clk), rate);
}
-int clk_parent_set_rate(struct clk *clk, unsigned long rate,
+int clk_parent_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
+ struct clk *clk = clk_hw_to_clk(hw);
+
if (!(clk->flags & CLK_SET_RATE_PARENT))
return 0;
return clk_set_rate(clk_get_parent(clk), rate);
}
+int clk_name_set_parent(const char *clkname, const char *clkparentname)
+{
+ struct clk *clk = clk_lookup(clkname);
+ struct clk *parent = clk_lookup(clkparentname);
+
+ if (IS_ERR(clk))
+ return -ENOENT;
+ if (IS_ERR(parent))
+ return -ENOENT;
+ return clk_set_parent(clk, parent);
+}
+
+int clk_name_set_rate(const char *clkname, unsigned long rate)
+{
+ struct clk *clk = clk_lookup(clkname);
+
+ if (IS_ERR(clk))
+ return -ENOENT;
+
+ return clk_set_rate(clk, rate);
+}
+
#if defined(CONFIG_COMMON_CLK_OF_PROVIDER)
/**
* struct of_clk_provider - Clock provider registration structure
@@ -359,12 +636,12 @@ struct of_clk_provider {
struct device_node *node;
struct clk *(*get)(struct of_phandle_args *clkspec, void *data);
+ struct clk_hw *(*get_hw)(struct of_phandle_args *clkspec, void *data);
void *data;
};
extern struct of_device_id __clk_of_table_start[];
-const struct of_device_id __clk_of_table_sentinel
- __attribute__ ((unused,section (".__clk_of_table_end")));
+const struct of_device_id __clk_of_table_sentinel __ll_elem(.__clk_of_table_end);
static LIST_HEAD(of_clk_providers);
@@ -375,6 +652,12 @@ struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
}
EXPORT_SYMBOL_GPL(of_clk_src_simple_get);
+struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec, void *data)
+{
+ return data;
+}
+EXPORT_SYMBOL_GPL(of_clk_hw_simple_get);
+
struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data)
{
struct clk_onecell_data *clk_data = data;
@@ -389,15 +672,27 @@ struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data)
}
EXPORT_SYMBOL_GPL(of_clk_src_onecell_get);
-/**
- * of_clk_add_provider() - Register a clock provider for a node
- * @np: Device node pointer associated with clock provider
- * @clk_src_get: callback for decoding clock
- * @data: context pointer for @clk_src_get callback.
- */
-int of_clk_add_provider(struct device_node *np,
+struct clk_hw *
+of_clk_hw_onecell_get(struct of_phandle_args *clkspec, void *data)
+{
+ struct clk_hw_onecell_data *hw_data = data;
+ unsigned int idx = clkspec->args[0];
+
+ if (idx >= hw_data->num) {
+ pr_err("%s: invalid index %u\n", __func__, idx);
+ return ERR_PTR(-EINVAL);
+ }
+
+ return hw_data->hws[idx];
+}
+EXPORT_SYMBOL_GPL(of_clk_hw_onecell_get);
+
+
+static int __of_clk_add_provider(struct device_node *np,
struct clk *(*clk_src_get)(struct of_phandle_args *clkspec,
void *data),
+ struct clk_hw *(*clk_hw_src_get)(struct of_phandle_args *clkspec,
+ void *data),
void *data)
{
struct of_clk_provider *cp;
@@ -409,14 +704,40 @@ int of_clk_add_provider(struct device_node *np,
cp->node = np;
cp->data = data;
cp->get = clk_src_get;
+ cp->get_hw = clk_hw_src_get;
list_add(&cp->link, &of_clk_providers);
- pr_debug("Added clock from %s\n", np ? np->full_name : "<none>");
+ pr_debug("Added clock from %pOF\n", np);
+
+ of_clk_set_defaults(np, true);
return 0;
}
+
+/**
+ * of_clk_add_provider() - Register a clock provider for a node
+ * @np: Device node pointer associated with clock provider
+ * @clk_src_get: callback for decoding clock
+ * @data: context pointer for @clk_src_get callback.
+ */
+int of_clk_add_provider(struct device_node *np,
+ struct clk *(*clk_src_get)(struct of_phandle_args *clkspec,
+ void *data),
+ void *data)
+{
+ return __of_clk_add_provider(np, clk_src_get, NULL, data);
+}
EXPORT_SYMBOL_GPL(of_clk_add_provider);
+int of_clk_add_hw_provider(struct device_node *np,
+ struct clk_hw *(*clk_hw_src_get)(struct of_phandle_args *clkspec,
+ void *data),
+ void *data)
+{
+ return __of_clk_add_provider(np, NULL, clk_hw_src_get, data);
+}
+EXPORT_SYMBOL_GPL(of_clk_add_hw_provider);
+
/**
* of_clk_del_provider() - Remove a previously registered clock provider
* @np: Device node pointer associated with clock provider
@@ -440,10 +761,17 @@ struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec)
struct of_clk_provider *provider;
struct clk *clk = ERR_PTR(-EPROBE_DEFER);
+ /* Ignore error, as CLK_OF_DECLARE clocks have no proper driver. */
+ of_device_ensure_probed(clkspec->np);
+
/* Check if we have such a provider in our array */
list_for_each_entry(provider, &of_clk_providers, link) {
- if (provider->node == clkspec->np)
- clk = provider->get(clkspec, provider->data);
+ if (provider->node == clkspec->np) {
+ if (provider->get)
+ clk = provider->get(clkspec, provider->data);
+ else
+ clk = clk_hw_to_clk(provider->get_hw(clkspec, provider->data));
+ }
if (!IS_ERR(clk))
break;
}
@@ -469,21 +797,60 @@ unsigned int of_clk_get_parent_count(struct device_node *np)
}
EXPORT_SYMBOL_GPL(of_clk_get_parent_count);
-char *of_clk_get_parent_name(struct device_node *np, unsigned int index)
+char *of_clk_get_parent_name(const struct device_node *np, int index)
{
struct of_phandle_args clkspec;
+ struct property *prop;
const char *clk_name;
+ const __be32 *vp;
+ u32 pv;
int rc;
+ int count;
+ struct clk *clk;
rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
- &clkspec);
+ &clkspec);
if (rc)
return NULL;
+ index = clkspec.args_count ? clkspec.args[0] : 0;
+ count = 0;
+
+ /* if there is an indices property, use it to transfer the index
+ * specified into an array offset for the clock-output-names property.
+ */
+ of_property_for_each_u32(clkspec.np, "clock-indices", prop, vp, pv) {
+ if (index == pv) {
+ index = count;
+ break;
+ }
+ count++;
+ }
+ /* We went off the end of 'clock-indices' without finding it */
+ if (prop && !vp)
+ return NULL;
+
if (of_property_read_string_index(clkspec.np, "clock-output-names",
- clkspec.args_count ? clkspec.args[0] : 0,
- &clk_name) < 0)
- clk_name = clkspec.np->name;
+ index,
+ &clk_name) < 0) {
+ /*
+ * Best effort to get the name if the clock has been
+ * registered with the framework. If the clock isn't
+ * registered, we return the node name as the name of
+ * the clock as long as #clock-cells = 0.
+ */
+ clk = of_clk_get_from_provider(&clkspec);
+ if (IS_ERR(clk)) {
+ if (clkspec.args_count == 0)
+ clk_name = clkspec.np->name;
+ else
+ clk_name = NULL;
+ } else {
+ clk_name = __clk_get_name(clk);
+ clk_put(clk);
+ }
+ }
+
return xstrdup(clk_name);
}
@@ -551,18 +918,30 @@ static int parent_ready(struct device_node *np)
}
}
+static LIST_HEAD(probed_clks);
+
+static bool of_clk_probed(struct device_node *np)
+{
+ struct clock_provider *clk_provider;
+
+ list_for_each_entry(clk_provider, &probed_clks, node)
+ if (clk_provider->np == np)
+ return true;
+ return false;
+}
+
/**
* of_clk_init() - Scan and init clock providers from the DT
- * @root: parent of the first level to probe or NULL for the root of the tree
- * @matches: array of compatible values and init functions for providers.
*
* This function scans the device tree for matching clock providers and
* calls their initialization functions
*
* Returns 0 on success, < 0 on failure.
*/
-int of_clk_init(struct device_node *root, const struct of_device_id *matches)
+int of_clk_init(void)
{
+ struct device_node *root = of_get_root_node();
+ const struct of_device_id *matches = __clk_of_table_start;
struct clock_provider *clk_provider, *next;
bool is_init_done;
bool force = false;
@@ -570,11 +949,7 @@ int of_clk_init(struct device_node *root, const struct of_device_id *matches)
const struct of_device_id *match;
if (!root)
- root = of_find_node_by_path("/");
- if (!root)
return -EINVAL;
- if (!matches)
- matches = __clk_of_table_start;
/* First prepare the list of the clocks providers */
for_each_matching_node_and_match(root, matches, &match) {
@@ -583,6 +958,11 @@ int of_clk_init(struct device_node *root, const struct of_device_id *matches)
if (!of_device_is_available(root))
continue;
+ if (of_clk_probed(root)) {
+ pr_debug("%s: already probed: %pOF\n", __func__, root);
+ continue;
+ }
+
parent = xzalloc(sizeof(*parent));
parent->clk_init_cb = match->data;
@@ -602,8 +982,7 @@ int of_clk_init(struct device_node *root, const struct of_device_id *matches)
clk_provider->clk_init_cb(np);
of_clk_set_defaults(np, true);
- list_del(&clk_provider->node);
- free(clk_provider);
+ list_move_tail(&clk_provider->node, &probed_clks);
is_init_done = true;
}
}
@@ -624,8 +1003,10 @@ int of_clk_init(struct device_node *root, const struct of_device_id *matches)
static const char *clk_hw_stat(struct clk *clk)
{
+ struct clk_hw *hw = clk_to_clk_hw(clk);
+
if (clk->ops->is_enabled) {
- if (clk->ops->is_enabled(clk))
+ if (clk->ops->is_enabled(hw))
return "enabled";
else
return "disabled";
@@ -637,9 +1018,17 @@ static const char *clk_hw_stat(struct clk *clk)
return "unknown";
}
+static const char *clk_parent_name_by_index(struct clk *clk, u8 idx)
+{
+ if (clk->parent_names)
+ return clk->parent_names[idx];
+ if (clk->parents[idx])
+ return clk->parents[idx]->name;
+ return "unknown";
+}
+
static void dump_one(struct clk *clk, int verbose, int indent)
{
- struct clk *c;
int enabled = clk_is_enabled(clk);
const char *hwstat, *stat;
@@ -662,17 +1051,23 @@ static void dump_one(struct clk *clk, int verbose, int indent)
int i;
printf("%*s`---- possible parents: ", indent * 4, "");
for (i = 0; i < clk->num_parents; i++)
- printf("%s ", clk->parent_names[i]);
+ printf("%s ", clk_parent_name_by_index(clk, i));
printf("\n");
}
}
+}
+
+static void dump_subtree(struct clk *clk, int verbose, int indent)
+{
+ struct clk *c;
+
+ dump_one(clk, verbose, indent);
list_for_each_entry(c, &clks, list) {
struct clk *parent = clk_get_parent(c);
- if (parent == clk) {
- dump_one(c, verbose, indent + 1);
- }
+ if (parent == clk)
+ dump_subtree(c, verbose, indent + 1);
}
}
@@ -684,7 +1079,42 @@ void clk_dump(int verbose)
struct clk *parent = clk_get_parent(c);
if (IS_ERR_OR_NULL(parent))
- dump_one(c, verbose, 0);
+ dump_subtree(c, verbose, 0);
+ }
+}
+
+static int clk_print_parent(struct clk *clk, int verbose)
+{
+ struct clk *c;
+ int indent;
+
+ c = clk_get_parent(clk);
+ if (IS_ERR_OR_NULL(c))
+ return 0;
+
+ indent = clk_print_parent(c, verbose);
+
+ dump_one(c, verbose, indent);
+
+ return indent + 1;
+}
+
+void clk_dump_one(struct clk *clk, int verbose)
+{
+ int indent;
+ struct clk *c;
+
+ indent = clk_print_parent(clk, verbose);
+
+ printf("\033[1m");
+ dump_one(clk, verbose, indent);
+ printf("\033[0m");
+
+ list_for_each_entry(c, &clks, list) {
+ struct clk *parent = clk_get_parent(c);
+
+ if (parent == clk)
+ dump_subtree(c, verbose, indent + 1);
}
}
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 462a7e16ef..dbe998b6af 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -70,8 +70,8 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
if (!IS_ERR(clk))
break;
else if (name && index >= 0) {
- pr_err("ERROR: could not get clock %s:%s(%i)\n",
- np->full_name, name ? name : "", index);
+ pr_err("ERROR: could not get clock %pOF:%s(%i)\n",
+ np, name ? name : "", index);
return clk;
}
@@ -129,7 +129,7 @@ static struct clk *clk_find(const char *dev_id, const char *con_id)
return clk;
}
-static struct clk *clk_find_physbase(struct device_d *dev, const char *con_id)
+static struct clk *clk_find_physbase(struct device *dev, const char *con_id)
{
struct clk_lookup *p;
unsigned long start;
@@ -167,7 +167,7 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id)
}
EXPORT_SYMBOL(clk_get_sys);
-struct clk *clk_get(struct device_d *dev, const char *con_id)
+struct clk *clk_get(struct device *dev, const char *con_id)
{
const char *dev_id = dev ? dev_name(dev) : NULL;
struct clk *clk;
@@ -176,9 +176,9 @@ struct clk *clk_get(struct device_d *dev, const char *con_id)
if (!IS_ERR(clk))
return clk;
- if (dev) {
- clk = of_clk_get_by_name(dev->device_node, con_id);
- if (!IS_ERR(clk) || PTR_ERR(clk) != -ENOENT)
+ if (dev && dev->of_node) {
+ clk = of_clk_get_by_name(dev->of_node, con_id);
+ if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
return clk;
}
@@ -265,7 +265,7 @@ int clk_register_clkdev(struct clk *clk, const char *con_id,
}
int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
- struct device_d *dev)
+ struct device *dev)
{
struct clk *r = clk_get(dev, id);
struct clk_lookup *l;
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index b1ce9d3d3e..eb9f8334c3 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -28,6 +28,11 @@ obj-$(CONFIG_ARCH_IMX6SL) += clk-imx6sl.o
obj-$(CONFIG_ARCH_IMX6UL) += clk-imx6ul.o
obj-$(CONFIG_ARCH_IMX7) += clk-imx7.o
pbl-$(CONFIG_ARCH_IMX8MM) += clk-pll14xx.o
+pbl-$(CONFIG_ARCH_IMX8MN) += clk-pll14xx.o
+pbl-$(CONFIG_ARCH_IMX8MP) += clk-pll14xx.o
obj-$(CONFIG_ARCH_IMX8MM) += clk-imx8mm.o
+obj-$(CONFIG_ARCH_IMX8MN) += clk-imx8mn.o
+obj-$(CONFIG_ARCH_IMX8MP) += clk-imx8mp.o
obj-$(CONFIG_ARCH_IMX8MQ) += clk-imx8mq.o
+obj-$(CONFIG_ARCH_IMX93) += clk-imx93.o clk-composite-93.o clk-gate-93.o clk-fracn-gppll.o
obj-$(CONFIG_ARCH_VF610) += clk-vf610.o
diff --git a/drivers/clk/imx/clk-composite-8m.c b/drivers/clk/imx/clk-composite-8m.c
index 0cd52b5b46..72534117f2 100644
--- a/drivers/clk/imx/clk-composite-8m.c
+++ b/drivers/clk/imx/clk-composite-8m.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2018 NXP
*/
@@ -15,6 +15,7 @@
#define PCG_PREDIV_MAX 8
#define PCG_DIV_SHIFT 0
+#define PCG_CORE_DIV_WIDTH 3
#define PCG_DIV_WIDTH 6
#define PCG_DIV_MAX 64
@@ -25,10 +26,11 @@
#define clk_div_mask(width) ((1 << (width)) - 1)
-static unsigned long imx8m_clk_composite_divider_recalc_rate(struct clk *clk,
+static unsigned long imx8m_clk_composite_divider_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_divider *divider = container_of(clk, struct clk_divider, clk);
+ struct clk_divider *divider = container_of(hw, struct clk_divider, hw);
+ struct clk *clk = clk_hw_to_clk(hw);
unsigned long prediv_rate;
unsigned int prediv_value;
unsigned int div_value;
@@ -73,7 +75,7 @@ static int imx8m_clk_composite_compute_dividers(unsigned long rate,
return ret;
}
-static long imx8m_clk_composite_divider_round_rate(struct clk *clk,
+static long imx8m_clk_composite_divider_round_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long *prate)
{
@@ -88,11 +90,11 @@ static long imx8m_clk_composite_divider_round_rate(struct clk *clk,
}
-static int imx8m_clk_composite_divider_set_rate(struct clk *clk,
+static int imx8m_clk_composite_divider_set_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long parent_rate)
{
- struct clk_divider *divider = container_of(clk, struct clk_divider, clk);
+ struct clk_divider *divider = container_of(hw, struct clk_divider, hw);
int prediv_value;
int div_value;
int ret;
@@ -113,6 +115,29 @@ static int imx8m_clk_composite_divider_set_rate(struct clk *clk,
return ret;
}
+static int imx8m_clk_composite_mux_get_parent(struct clk_hw *hw)
+{
+ return clk_mux_ops.get_parent(hw);
+}
+
+static int imx8m_clk_composite_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct clk_mux *m = container_of(hw, struct clk_mux, hw);
+ u32 val;
+
+ val = readl(m->reg);
+ val &= ~(((1 << m->width) - 1) << m->shift);
+ val |= index << m->shift;
+
+ /*
+ * write twice to make sure non-target interface
+ * SEL_A/B point the same clk input.
+ */
+ writel(val, m->reg);
+ writel(val, m->reg);
+
+ return 0;
+}
static const struct clk_ops imx8m_clk_composite_divider_ops = {
.recalc_rate = imx8m_clk_composite_divider_recalc_rate,
@@ -120,15 +145,24 @@ static const struct clk_ops imx8m_clk_composite_divider_ops = {
.set_rate = imx8m_clk_composite_divider_set_rate,
};
+static const struct clk_ops imx8m_clk_composite_mux_ops = {
+ .get_parent = imx8m_clk_composite_mux_get_parent,
+ .set_parent = imx8m_clk_composite_mux_set_parent,
+ .set_rate = clk_parent_set_rate,
+ .round_rate = clk_parent_round_rate,
+};
+
struct clk *imx8m_clk_composite_flags(const char *name,
- const char **parent_names,
+ const char * const *parent_names,
int num_parents, void __iomem *reg,
+ u32 composite_flags,
unsigned long flags)
{
struct clk *comp = ERR_PTR(-ENOMEM);
struct clk_divider *div = NULL;
struct clk_gate *gate = NULL;
struct clk_mux *mux = NULL;
+ const struct clk_ops *mux_ops;
mux = kzalloc(sizeof(*mux), GFP_KERNEL);
if (!mux)
@@ -137,16 +171,29 @@ struct clk *imx8m_clk_composite_flags(const char *name,
mux->reg = reg;
mux->shift = PCG_PCS_SHIFT;
mux->width = PCG_PCS_WIDTH;
- mux->clk.ops = &clk_mux_ops;
+ mux->hw.clk.ops = &clk_mux_ops;
div = kzalloc(sizeof(*div), GFP_KERNEL);
if (!div)
goto fail;
div->reg = reg;
- div->shift = PCG_PREDIV_SHIFT;
- div->width = PCG_PREDIV_WIDTH;
- div->clk.ops = &imx8m_clk_composite_divider_ops;
+ if (composite_flags & IMX_COMPOSITE_CORE) {
+ div->shift = PCG_DIV_SHIFT;
+ div->width = PCG_CORE_DIV_WIDTH;
+ div->hw.clk.ops = &clk_divider_ops;
+ mux_ops = &imx8m_clk_composite_mux_ops;
+ } else if (composite_flags & IMX_COMPOSITE_BUS) {
+ div->shift = PCG_PREDIV_SHIFT;
+ div->width = PCG_PREDIV_WIDTH;
+ div->hw.clk.ops = &imx8m_clk_composite_divider_ops;
+ mux_ops = &imx8m_clk_composite_mux_ops;
+ } else {
+ div->shift = PCG_PREDIV_SHIFT;
+ div->width = PCG_PREDIV_WIDTH;
+ div->hw.clk.ops = &imx8m_clk_composite_divider_ops;
+ mux_ops = &clk_mux_ops;
+ }
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
if (!gate)
@@ -154,10 +201,10 @@ struct clk *imx8m_clk_composite_flags(const char *name,
gate->reg = reg;
gate->shift = PCG_CGC_SHIFT;
- gate->clk.ops = &clk_gate_ops;
+ gate->hw.clk.ops = &clk_gate_ops;
comp = clk_register_composite(name, parent_names, num_parents,
- &mux->clk, &div->clk, &gate->clk, flags);
+ &mux->hw.clk, &div->hw.clk, &gate->hw.clk, flags);
if (IS_ERR(comp))
goto fail;
diff --git a/drivers/clk/imx/clk-composite-93.c b/drivers/clk/imx/clk-composite-93.c
new file mode 100644
index 0000000000..2b3753d569
--- /dev/null
+++ b/drivers/clk/imx/clk-composite-93.c
@@ -0,0 +1,216 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 NXP
+ *
+ * Peng Fan <peng.fan@nxp.com>
+ */
+
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <of_address.h>
+#include <linux/iopoll.h>
+
+#include "clk.h"
+
+#define TIMEOUT_US 500U
+
+#define CCM_DIV_SHIFT 0
+#define CCM_DIV_WIDTH 8
+#define CCM_MUX_SHIFT 8
+#define CCM_MUX_MASK 3
+#define CCM_OFF_SHIFT 24
+#define CCM_BUSY_SHIFT 28
+
+#define STAT_OFFSET 0x4
+#define AUTHEN_OFFSET 0x30
+#define TZ_NS_SHIFT 9
+#define TZ_NS_MASK BIT(9)
+
+#define WHITE_LIST_SHIFT 16
+
+static int imx93_clk_composite_wait_ready(struct clk_hw *hw, void __iomem *reg)
+{
+ int ret;
+ u32 val;
+
+ ret = readl_poll_timeout(reg + STAT_OFFSET, val, !(val & BIT(CCM_BUSY_SHIFT)),
+ TIMEOUT_US);
+ if (ret)
+ pr_err("Slice[%s] busy timeout\n", clk_hw_get_name(hw));
+
+ return ret;
+}
+
+static void imx93_clk_composite_gate_endisable(struct clk_hw *hw, int enable)
+{
+ struct clk_gate *gate = to_clk_gate(hw);
+ u32 reg;
+
+ reg = readl(gate->reg);
+
+ if (enable)
+ reg &= ~BIT(gate->shift);
+ else
+ reg |= BIT(gate->shift);
+
+ writel(reg, gate->reg);
+
+ imx93_clk_composite_wait_ready(hw, gate->reg);
+}
+
+static int imx93_clk_composite_gate_enable(struct clk_hw *hw)
+{
+ imx93_clk_composite_gate_endisable(hw, 1);
+
+ return 0;
+}
+
+static void imx93_clk_composite_gate_disable(struct clk_hw *hw)
+{
+ imx93_clk_composite_gate_endisable(hw, 0);
+}
+
+static const struct clk_ops imx93_clk_composite_gate_ops = {
+ .enable = imx93_clk_composite_gate_enable,
+ .disable = imx93_clk_composite_gate_disable,
+ .is_enabled = clk_gate_is_enabled,
+};
+
+static unsigned long
+imx93_clk_composite_divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+ return clk_divider_ops.recalc_rate(hw, parent_rate);
+}
+
+static long
+imx93_clk_composite_divider_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate)
+{
+ return clk_divider_ops.round_rate(hw, rate, prate);
+}
+
+static int imx93_clk_composite_divider_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_divider *divider = to_clk_divider(hw);
+ int value;
+ u32 val;
+ int ret;
+
+ value = divider_get_val(rate, parent_rate, divider->table, divider->width, divider->flags);
+ if (value < 0)
+ return value;
+
+ val = readl(divider->reg);
+ val &= ~(clk_div_mask(divider->width) << divider->shift);
+ val |= (u32)value << divider->shift;
+ writel(val, divider->reg);
+
+ ret = imx93_clk_composite_wait_ready(hw, divider->reg);
+
+ return ret;
+}
+
+static const struct clk_ops imx93_clk_composite_divider_ops = {
+ .recalc_rate = imx93_clk_composite_divider_recalc_rate,
+ .round_rate = imx93_clk_composite_divider_round_rate,
+ .set_rate = imx93_clk_composite_divider_set_rate,
+};
+
+static int imx93_clk_composite_mux_get_parent(struct clk_hw *hw)
+{
+ return clk_mux_ops.get_parent(hw);
+}
+
+static int imx93_clk_composite_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct clk_mux *mux = to_clk_mux(hw);
+ u32 val = clk_mux_index_to_val(mux->table, mux->flags, index);
+ u32 reg;
+ int ret;
+
+ reg = readl(mux->reg);
+ reg &= ~(((1 << mux->width) - 1) << mux->shift);
+ val = val << mux->shift;
+ reg |= val;
+ writel(reg, mux->reg);
+
+ ret = imx93_clk_composite_wait_ready(hw, mux->reg);
+
+ return ret;
+}
+
+static const struct clk_ops imx93_clk_composite_mux_ops = {
+ .get_parent = imx93_clk_composite_mux_get_parent,
+ .set_parent = imx93_clk_composite_mux_set_parent,
+};
+
+struct clk *imx93_clk_composite_flags(const char *name, const char * const *parent_names,
+ int num_parents, void __iomem *reg, u32 domain_id,
+ unsigned long flags)
+{
+ struct clk_hw *hw = ERR_PTR(-ENOMEM), *mux_hw;
+ struct clk_hw *div_hw, *gate_hw;
+ struct clk_divider *div = NULL;
+ struct clk_gate *gate = NULL;
+ struct clk_mux *mux = NULL;
+ bool clk_ro = false;
+ u32 authen;
+
+ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+ if (!mux)
+ goto fail;
+
+ mux_hw = &mux->hw;
+ mux->reg = reg;
+ mux->shift = CCM_MUX_SHIFT;
+ mux->width = 2;
+
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div)
+ goto fail;
+
+ div_hw = &div->hw;
+ div->reg = reg;
+ div->shift = CCM_DIV_SHIFT;
+ div->width = CCM_DIV_WIDTH;
+// div->flags = CLK_DIVIDER_ROUND_CLOSEST;
+
+ authen = readl(reg + AUTHEN_OFFSET);
+ if (!(authen & TZ_NS_MASK) || !(authen & BIT(WHITE_LIST_SHIFT + domain_id)))
+ clk_ro = true;
+
+ if (clk_ro) {
+ hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
+ mux_hw, &clk_mux_ro_ops, div_hw,
+ &clk_divider_ro_ops, NULL, NULL, flags);
+ } else {
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate)
+ goto fail;
+
+ gate_hw = &gate->hw;
+ gate->reg = reg;
+ gate->shift = CCM_OFF_SHIFT;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+
+ hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
+ mux_hw, &imx93_clk_composite_mux_ops, div_hw,
+ &imx93_clk_composite_divider_ops, gate_hw,
+ &imx93_clk_composite_gate_ops,
+ flags | CLK_SET_RATE_NO_REPARENT);
+ }
+
+ if (IS_ERR(hw))
+ goto fail;
+
+ return &hw->clk;
+
+fail:
+ kfree(gate);
+ kfree(div);
+ kfree(mux);
+ return ERR_CAST(hw);
+}
+EXPORT_SYMBOL_GPL(imx93_clk_composite_flags);
diff --git a/drivers/clk/imx/clk-cpu.c b/drivers/clk/imx/clk-cpu.c
index 13b2dfc9ad..0ca5dd63c5 100644
--- a/drivers/clk/imx/clk-cpu.c
+++ b/drivers/clk/imx/clk-cpu.c
@@ -16,38 +16,38 @@
#include "clk.h"
struct clk_cpu {
- struct clk clk;
+ struct clk_hw hw;
struct clk *div;
struct clk *mux;
struct clk *pll;
struct clk *step;
};
-static inline struct clk_cpu *to_clk_cpu(struct clk *clk)
+static inline struct clk_cpu *to_clk_cpu(struct clk_hw *hw)
{
- return container_of(clk, struct clk_cpu, clk);
+ return container_of(hw, struct clk_cpu, hw);
}
-static unsigned long clk_cpu_recalc_rate(struct clk *clk,
+static unsigned long clk_cpu_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_cpu *cpu = to_clk_cpu(clk);
+ struct clk_cpu *cpu = to_clk_cpu(hw);
return clk_get_rate(cpu->div);
}
-static long clk_cpu_round_rate(struct clk *clk, unsigned long rate,
+static long clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
- struct clk_cpu *cpu = to_clk_cpu(clk);
+ struct clk_cpu *cpu = to_clk_cpu(hw);
return clk_round_rate(cpu->pll, rate);
}
-static int clk_cpu_set_rate(struct clk *clk, unsigned long rate,
+static int clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_cpu *cpu = to_clk_cpu(clk);
+ struct clk_cpu *cpu = to_clk_cpu(hw);
int ret;
/* switch to PLL bypass clock */
@@ -98,17 +98,17 @@ struct clk *imx_clk_cpu(const char *name, const char *parent_name,
cpu->pll = pll;
cpu->step = step;
- cpu->clk.name = name;
- cpu->clk.ops = &clk_cpu_ops;
- cpu->clk.flags = 0;
- cpu->clk.parent_names = &icpu->parent_name;
- cpu->clk.num_parents = 1;
+ cpu->hw.clk.name = name;
+ cpu->hw.clk.ops = &clk_cpu_ops;
+ cpu->hw.clk.flags = CLK_IS_CRITICAL;
+ cpu->hw.clk.parent_names = &icpu->parent_name;
+ cpu->hw.clk.num_parents = 1;
- ret = clk_register(&cpu->clk);
+ ret = bclk_register(&cpu->hw.clk);
if (ret) {
free(cpu);
return NULL;
}
- return &cpu->clk;
+ return &cpu->hw.clk;
}
diff --git a/drivers/clk/imx/clk-frac-pll.c b/drivers/clk/imx/clk-frac-pll.c
index b3d665cff9..d3fc760717 100644
--- a/drivers/clk/imx/clk-frac-pll.c
+++ b/drivers/clk/imx/clk-frac-pll.c
@@ -8,7 +8,7 @@
#include <malloc.h>
#include <linux/clk.h>
#include <linux/err.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
@@ -26,12 +26,12 @@
#define PLL_FRAC_DENOM 0x1000000
struct clk_frac_pll {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *base;
const char *parent;
};
-#define to_clk_frac_pll(_clk) container_of(_clk, struct clk_frac_pll, clk)
+#define to_clk_frac_pll(_hw) container_of(_hw, struct clk_frac_pll, hw)
static int clk_wait_lock(struct clk_frac_pll *pll)
{
@@ -63,9 +63,9 @@ static int clk_wait_ack(struct clk_frac_pll *pll)
return readl(pll->base) & PLL_NEWDIV_ACK ? 0 : ETIMEDOUT;
}
-static int clk_pll_enable(struct clk *clk)
+static int clk_pll_enable(struct clk_hw *hw)
{
- struct clk_frac_pll *pll = to_clk_frac_pll(clk);
+ struct clk_frac_pll *pll = to_clk_frac_pll(hw);
u32 val;
val = readl(pll->base + PLL_CFG0);
@@ -75,9 +75,9 @@ static int clk_pll_enable(struct clk *clk)
return clk_wait_lock(pll);
}
-static void clk_pll_disable(struct clk *clk)
+static void clk_pll_disable(struct clk_hw *hw)
{
- struct clk_frac_pll *pll = to_clk_frac_pll(clk);
+ struct clk_frac_pll *pll = to_clk_frac_pll(hw);
u32 val;
val = readl(pll->base + PLL_CFG0);
@@ -85,19 +85,19 @@ static void clk_pll_disable(struct clk *clk)
writel(val, pll->base + PLL_CFG0);
}
-static int clk_pll_is_enabled(struct clk *clk)
+static int clk_pll_is_enabled(struct clk_hw *hw)
{
- struct clk_frac_pll *pll = to_clk_frac_pll(clk);
+ struct clk_frac_pll *pll = to_clk_frac_pll(hw);
u32 val;
val = readl(pll->base + PLL_CFG0);
return (val & (1 << PLL_PD)) ? 0 : 1;
}
-static unsigned long clk_pll_recalc_rate(struct clk *clk,
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_frac_pll *pll = to_clk_frac_pll(clk);
+ struct clk_frac_pll *pll = to_clk_frac_pll(hw);
u32 val, divff, divfi, divq;
u64 temp64;
@@ -110,12 +110,12 @@ static unsigned long clk_pll_recalc_rate(struct clk *clk,
temp64 = (u64)parent_rate * 8;
temp64 *= divff;
do_div(temp64, PLL_FRAC_DENOM);
- temp64 /= divq;
+ do_div(temp64, divq);
return parent_rate * 8 * (divfi + 1) / divq + (unsigned long)temp64;
}
-static long clk_pll_round_rate(struct clk *clk, unsigned long rate,
+static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
u32 divff, divfi;
@@ -144,10 +144,10 @@ static long clk_pll_round_rate(struct clk *clk, unsigned long rate,
* pllout = parent_rate * 8 / 2 * DIVF_VAL;
* where DIVF_VAL = 1 + DIVFI + DIVFF / 2^24.
*/
-static int clk_pll_set_rate(struct clk *clk, unsigned long rate,
+static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_frac_pll *pll = to_clk_frac_pll(clk);
+ struct clk_frac_pll *pll = to_clk_frac_pll(hw);
u32 val, divfi, divff;
u64 temp64;
int ret;
@@ -205,16 +205,16 @@ struct clk *imx_clk_frac_pll(const char *name, const char *parent,
pll->base = base;
pll->parent = parent;
- pll->clk.ops = &clk_frac_pll_ops;
- pll->clk.name = name;
- pll->clk.parent_names = &pll->parent;
- pll->clk.num_parents = 1;
+ pll->hw.clk.ops = &clk_frac_pll_ops;
+ pll->hw.clk.name = name;
+ pll->hw.clk.parent_names = &pll->parent;
+ pll->hw.clk.num_parents = 1;
- ret = clk_register(&pll->clk);
+ ret = bclk_register(&pll->hw.clk);
if (ret) {
free(pll);
return ERR_PTR(ret);
}
- return &pll->clk;
+ return &pll->hw.clk;
}
diff --git a/drivers/clk/imx/clk-fracn-gppll.c b/drivers/clk/imx/clk-fracn-gppll.c
new file mode 100644
index 0000000000..24e66fd65f
--- /dev/null
+++ b/drivers/clk/imx/clk-fracn-gppll.c
@@ -0,0 +1,297 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2021 NXP
+ */
+
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <of_address.h>
+#include <linux/iopoll.h>
+#include <linux/bitfield.h>
+#include <soc/imx/clk-fracn-gppll.h>
+
+#include "clk.h"
+
+#define PLL_FRACN_GP(_rate, _mfi, _mfn, _mfd, _rdiv, _odiv) \
+ { \
+ .rate = (_rate), \
+ .mfi = (_mfi), \
+ .mfn = (_mfn), \
+ .mfd = (_mfd), \
+ .rdiv = (_rdiv), \
+ .odiv = (_odiv), \
+ }
+
+#define PLL_FRACN_GP_INTEGER(_rate, _mfi, _rdiv, _odiv) \
+ { \
+ .rate = (_rate), \
+ .mfi = (_mfi), \
+ .mfn = 0, \
+ .mfd = 0, \
+ .rdiv = (_rdiv), \
+ .odiv = (_odiv), \
+ }
+
+struct clk_fracn_gppll {
+ struct clk_hw hw;
+ void __iomem *base;
+ const struct imx_fracn_gppll_rate_table *rate_table;
+ int rate_count;
+ u32 flags;
+};
+
+/*
+ * Fvco = (Fref / rdiv) * (MFI + MFN / MFD)
+ * Fout = Fvco / odiv
+ * The (Fref / rdiv) should be in range 20MHz to 40MHz
+ * The Fvco should be in range 2.5Ghz to 5Ghz
+ */
+static const struct imx_fracn_gppll_rate_table fracn_tbl[] = {
+ PLL_FRACN_GP(650000000U, 162, 50, 100, 0, 6),
+ PLL_FRACN_GP(594000000U, 198, 0, 1, 0, 8),
+ PLL_FRACN_GP(560000000U, 140, 0, 1, 0, 6),
+ PLL_FRACN_GP(519750000U, 173, 25, 100, 1, 8),
+ PLL_FRACN_GP(498000000U, 166, 0, 1, 0, 8),
+ PLL_FRACN_GP(484000000U, 121, 0, 1, 0, 6),
+ PLL_FRACN_GP(445333333U, 167, 0, 1, 0, 9),
+ PLL_FRACN_GP(400000000U, 200, 0, 1, 0, 12),
+ PLL_FRACN_GP(393216000U, 163, 84, 100, 0, 10),
+ PLL_FRACN_GP(300000000U, 150, 0, 1, 0, 12)
+};
+
+struct imx_fracn_gppll_clk imx_fracn_gppll = {
+ .rate_table = fracn_tbl,
+ .rate_count = ARRAY_SIZE(fracn_tbl),
+};
+EXPORT_SYMBOL_GPL(imx_fracn_gppll);
+
+/*
+ * Fvco = (Fref / rdiv) * MFI
+ * Fout = Fvco / odiv
+ * The (Fref / rdiv) should be in range 20MHz to 40MHz
+ * The Fvco should be in range 2.5Ghz to 5Ghz
+ */
+static const struct imx_fracn_gppll_rate_table int_tbl[] = {
+ PLL_FRACN_GP_INTEGER(1700000000U, 141, 1, 2),
+ PLL_FRACN_GP_INTEGER(1400000000U, 175, 1, 3),
+ PLL_FRACN_GP_INTEGER(900000000U, 150, 1, 4),
+};
+
+struct imx_fracn_gppll_clk imx_fracn_gppll_integer = {
+ .rate_table = int_tbl,
+ .rate_count = ARRAY_SIZE(int_tbl),
+};
+EXPORT_SYMBOL_GPL(imx_fracn_gppll_integer);
+
+static inline struct clk_fracn_gppll *to_clk_fracn_gppll(struct clk_hw *hw)
+{
+ return container_of(hw, struct clk_fracn_gppll, hw);
+}
+
+static long clk_fracn_gppll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
+ const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table;
+ int i;
+
+ /* Assuming rate_table is in descending order */
+ for (i = 0; i < pll->rate_count; i++)
+ if (rate >= rate_table[i].rate)
+ return rate_table[i].rate;
+
+ /* return minimum supported value */
+ return rate_table[pll->rate_count - 1].rate;
+}
+
+static unsigned long clk_fracn_gppll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+ struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
+ const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table;
+ u32 pll_numerator, pll_denominator, pll_div;
+ u32 mfi, mfn, mfd, rdiv, odiv;
+ u64 fvco = parent_rate;
+ long rate = 0;
+ int i;
+
+ pll_numerator = readl_relaxed(pll->base + GPPLL_NUMERATOR);
+ mfn = FIELD_GET(GPPLL_MFN_MASK, pll_numerator);
+
+ pll_denominator = readl_relaxed(pll->base + GPPLL_DENOMINATOR);
+ mfd = FIELD_GET(GPPLL_MFD_MASK, pll_denominator);
+
+ pll_div = readl_relaxed(pll->base + GPPLL_DIV);
+ mfi = FIELD_GET(GPPLL_MFI_MASK, pll_div);
+
+ rdiv = FIELD_GET(GPPLL_RDIV_MASK, pll_div);
+ odiv = FIELD_GET(GPPLL_ODIV_MASK, pll_div);
+
+ /*
+ * Sometimes, the recalculated rate has deviation due to
+ * the frac part. So find the accurate pll rate from the table
+ * first, if no match rate in the table, use the rate calculated
+ * from the equation below.
+ */
+ for (i = 0; i < pll->rate_count; i++) {
+ if (rate_table[i].mfn == mfn && rate_table[i].mfi == mfi &&
+ rate_table[i].mfd == mfd && rate_table[i].rdiv == rdiv &&
+ rate_table[i].odiv == odiv)
+ rate = rate_table[i].rate;
+ }
+
+ if (rate)
+ return (unsigned long)rate;
+
+ if (!rdiv)
+ rdiv = rdiv + 1;
+
+ switch (odiv) {
+ case 0:
+ odiv = 2;
+ break;
+ case 1:
+ odiv = 3;
+ break;
+ default:
+ break;
+ }
+
+ if (pll->flags & CLK_FRACN_GPPLL_INTEGER) {
+ /* Fvco = (Fref / rdiv) * MFI */
+ fvco = fvco * mfi;
+ do_div(fvco, rdiv * odiv);
+ } else {
+ /* Fvco = (Fref / rdiv) * (MFI + MFN / MFD) */
+ fvco = fvco * mfi * mfd + fvco * mfn;
+ do_div(fvco, mfd * rdiv * odiv);
+ }
+
+ return (unsigned long)fvco;
+}
+
+static int clk_fracn_gppll_wait_lock(struct clk_fracn_gppll *pll)
+{
+ return fracn_gppll_wait_lock(pll->base);
+}
+
+static int clk_fracn_gppll_set_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long prate)
+{
+ struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
+
+ return fracn_gppll_set_rate(pll->base, pll->flags, pll->rate_table,
+ pll->rate_count, drate);
+}
+
+static int clk_fracn_gppll_prepare(struct clk_hw *hw)
+{
+ struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
+ u32 val;
+ int ret;
+
+ val = readl_relaxed(pll->base + GPPLL_CTRL);
+ if (val & POWERUP_MASK)
+ return 0;
+
+ val |= CLKMUX_BYPASS;
+ writel_relaxed(val, pll->base + GPPLL_CTRL);
+
+ val |= POWERUP_MASK;
+ writel_relaxed(val, pll->base + GPPLL_CTRL);
+
+ val |= CLKMUX_EN;
+ writel_relaxed(val, pll->base + GPPLL_CTRL);
+
+ ret = clk_fracn_gppll_wait_lock(pll);
+ if (ret)
+ return ret;
+
+ val &= ~CLKMUX_BYPASS;
+ writel_relaxed(val, pll->base + GPPLL_CTRL);
+
+ return 0;
+}
+
+static int clk_fracn_gppll_is_prepared(struct clk_hw *hw)
+{
+ struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
+ u32 val;
+
+ val = readl_relaxed(pll->base + GPPLL_CTRL);
+
+ return (val & POWERUP_MASK) ? 1 : 0;
+}
+
+static void clk_fracn_gppll_unprepare(struct clk_hw *hw)
+{
+ struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw);
+ u32 val;
+
+ val = readl_relaxed(pll->base + GPPLL_CTRL);
+ val &= ~POWERUP_MASK;
+ writel_relaxed(val, pll->base + GPPLL_CTRL);
+}
+
+static const struct clk_ops clk_fracn_gppll_ops = {
+ .enable = clk_fracn_gppll_prepare,
+ .disable = clk_fracn_gppll_unprepare,
+ .is_enabled = clk_fracn_gppll_is_prepared,
+ .recalc_rate = clk_fracn_gppll_recalc_rate,
+ .round_rate = clk_fracn_gppll_round_rate,
+ .set_rate = clk_fracn_gppll_set_rate,
+};
+
+static struct clk *_imx_clk_fracn_gppll(const char *name, const char *parent_name,
+ void __iomem *base,
+ const struct imx_fracn_gppll_clk *pll_clk,
+ u32 pll_flags)
+{
+ struct clk_fracn_gppll *pll;
+ struct clk_hw *hw;
+ struct clk_init_data init;
+ int ret;
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.flags = pll_clk->flags;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+ init.ops = &clk_fracn_gppll_ops;
+
+ pll->base = base;
+ pll->hw.init = &init;
+ pll->rate_table = pll_clk->rate_table;
+ pll->rate_count = pll_clk->rate_count;
+ pll->flags = pll_flags;
+
+ hw = &pll->hw;
+
+ ret = clk_hw_register(NULL, hw);
+ if (ret) {
+ pr_err("%s: failed to register pll %s %d\n", __func__, name, ret);
+ kfree(pll);
+ return ERR_PTR(ret);
+ }
+
+ return &hw->clk;
+}
+
+struct clk *imx_clk_fracn_gppll(const char *name, const char *parent_name, void __iomem *base,
+ const struct imx_fracn_gppll_clk *pll_clk)
+{
+ return _imx_clk_fracn_gppll(name, parent_name, base, pll_clk, CLK_FRACN_GPPLL_FRACN);
+}
+EXPORT_SYMBOL_GPL(imx_clk_fracn_gppll);
+
+struct clk *imx_clk_fracn_gppll_integer(const char *name, const char *parent_name,
+ void __iomem *base,
+ const struct imx_fracn_gppll_clk *pll_clk)
+{
+ return _imx_clk_fracn_gppll(name, parent_name, base, pll_clk, CLK_FRACN_GPPLL_INTEGER);
+}
+EXPORT_SYMBOL_GPL(imx_clk_fracn_gppll_integer);
diff --git a/drivers/clk/imx/clk-gate-93.c b/drivers/clk/imx/clk-gate-93.c
new file mode 100644
index 0000000000..ed2714a03c
--- /dev/null
+++ b/drivers/clk/imx/clk-gate-93.c
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2022 NXP
+ *
+ * Peng Fan <peng.fan@nxp.com>
+ */
+
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <of_address.h>
+#include <linux/iopoll.h>
+
+#include "clk.h"
+
+#define DIRECT_OFFSET 0x0
+
+/*
+ * 0b000 - LPCG will be OFF in any CPU mode.
+ * 0b100 - LPCG will be ON in any CPU mode.
+ */
+#define LPM_SETTING_OFF 0x0
+#define LPM_SETTING_ON 0x4
+
+#define LPM_CUR_OFFSET 0x1c
+
+#define AUTHEN_OFFSET 0x30
+#define CPULPM_EN BIT(2)
+#define TZ_NS_SHIFT 9
+#define TZ_NS_MASK BIT(9)
+
+#define WHITE_LIST_SHIFT 16
+
+struct imx93_clk_gate {
+ struct clk_hw hw;
+ void __iomem *reg;
+ u32 bit_idx;
+ u32 val;
+ u32 mask;
+ spinlock_t *lock;
+ unsigned int *share_count;
+};
+
+#define to_imx93_clk_gate(_hw) container_of(_hw, struct imx93_clk_gate, hw)
+
+static void imx93_clk_gate_do_hardware(struct clk_hw *hw, bool enable)
+{
+ struct imx93_clk_gate *gate = to_imx93_clk_gate(hw);
+ u32 val;
+
+ val = readl(gate->reg + AUTHEN_OFFSET);
+ if (val & CPULPM_EN) {
+ val = enable ? LPM_SETTING_ON : LPM_SETTING_OFF;
+ writel(val, gate->reg + LPM_CUR_OFFSET);
+ } else {
+ val = readl(gate->reg + DIRECT_OFFSET);
+ val &= ~(gate->mask << gate->bit_idx);
+ if (enable)
+ val |= (gate->val & gate->mask) << gate->bit_idx;
+ writel(val, gate->reg + DIRECT_OFFSET);
+ }
+}
+
+static int imx93_clk_gate_enable(struct clk_hw *hw)
+{
+ struct imx93_clk_gate *gate = to_imx93_clk_gate(hw);
+ unsigned long flags;
+
+ spin_lock_irqsave(gate->lock, flags);
+
+ if (gate->share_count && (*gate->share_count)++ > 0)
+ goto out;
+
+ imx93_clk_gate_do_hardware(hw, true);
+out:
+ spin_unlock_irqrestore(gate->lock, flags);
+
+ return 0;
+}
+
+static void imx93_clk_gate_disable(struct clk_hw *hw)
+{
+ struct imx93_clk_gate *gate = to_imx93_clk_gate(hw);
+ unsigned long flags;
+
+ spin_lock_irqsave(gate->lock, flags);
+
+ if (gate->share_count) {
+ if (WARN_ON(*gate->share_count == 0))
+ goto out;
+ else if (--(*gate->share_count) > 0)
+ goto out;
+ }
+
+ imx93_clk_gate_do_hardware(hw, false);
+out:
+ spin_unlock_irqrestore(gate->lock, flags);
+}
+
+static int imx93_clk_gate_reg_is_enabled(struct imx93_clk_gate *gate)
+{
+ u32 val = readl(gate->reg + AUTHEN_OFFSET);
+
+ if (val & CPULPM_EN) {
+ val = readl(gate->reg + LPM_CUR_OFFSET);
+ if (val == LPM_SETTING_ON)
+ return 1;
+ } else {
+ val = readl(gate->reg);
+ if (((val >> gate->bit_idx) & gate->mask) == gate->val)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int imx93_clk_gate_is_enabled(struct clk_hw *hw)
+{
+ struct imx93_clk_gate *gate = to_imx93_clk_gate(hw);
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(gate->lock, flags);
+
+ ret = imx93_clk_gate_reg_is_enabled(gate);
+
+ spin_unlock_irqrestore(gate->lock, flags);
+
+ return ret;
+}
+
+static const struct clk_ops imx93_clk_gate_ops = {
+ .set_rate = clk_parent_set_rate,
+ .round_rate = clk_parent_round_rate,
+ .enable = imx93_clk_gate_enable,
+ .disable = imx93_clk_gate_disable,
+ .is_enabled = imx93_clk_gate_is_enabled,
+};
+
+static const struct clk_ops imx93_clk_gate_ro_ops = {
+ .is_enabled = imx93_clk_gate_is_enabled,
+};
+
+struct clk *imx93_clk_gate(struct device *dev, const char *name, const char *parent_name,
+ unsigned long flags, void __iomem *reg, u32 bit_idx, u32 val,
+ u32 mask, u32 domain_id, unsigned int *share_count)
+{
+ struct imx93_clk_gate *gate;
+ struct clk_hw *hw;
+ struct clk_init_data init;
+ int ret;
+ u32 authen;
+
+ gate = kzalloc(sizeof(struct imx93_clk_gate), GFP_KERNEL);
+ if (!gate)
+ return ERR_PTR(-ENOMEM);
+
+ gate->reg = reg;
+ gate->bit_idx = bit_idx;
+ gate->val = val;
+ gate->mask = mask;
+ gate->share_count = share_count;
+
+ init.name = name;
+ init.ops = &imx93_clk_gate_ops;
+ init.flags = flags | CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE;
+ init.parent_names = parent_name ? &parent_name : NULL;
+ init.num_parents = parent_name ? 1 : 0;
+
+ gate->hw.init = &init;
+ hw = &gate->hw;
+
+ authen = readl(reg + AUTHEN_OFFSET);
+ if (!(authen & TZ_NS_MASK) || !(authen & BIT(WHITE_LIST_SHIFT + domain_id)))
+ init.ops = &imx93_clk_gate_ro_ops;
+
+ ret = clk_hw_register(dev, hw);
+ if (ret) {
+ kfree(gate);
+ return ERR_PTR(ret);
+ }
+
+ return &hw->clk;
+}
+EXPORT_SYMBOL_GPL(imx93_clk_gate);
diff --git a/drivers/clk/imx/clk-gate-exclusive.c b/drivers/clk/imx/clk-gate-exclusive.c
index 4bf4de8bd3..473249a356 100644
--- a/drivers/clk/imx/clk-gate-exclusive.c
+++ b/drivers/clk/imx/clk-gate-exclusive.c
@@ -24,17 +24,21 @@
* register is mutually exclusive to this gate clock.
*/
struct clk_gate_exclusive {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *reg;
int shift;
const char *parent;
u32 exclusive_mask;
};
-static int clk_gate_exclusive_enable(struct clk *clk)
+static inline struct clk_gate_exclusive *to_clk_gate_exclusive(struct clk_hw *hw)
{
- struct clk_gate_exclusive *exgate = container_of(clk,
- struct clk_gate_exclusive, clk);
+ return container_of(hw, struct clk_gate_exclusive, hw);
+}
+
+static int clk_gate_exclusive_enable(struct clk_hw *hw)
+{
+ struct clk_gate_exclusive *exgate = to_clk_gate_exclusive(hw);
u32 val = readl(exgate->reg);
if (val & exgate->exclusive_mask)
@@ -47,10 +51,9 @@ static int clk_gate_exclusive_enable(struct clk *clk)
return 0;
}
-static void clk_gate_exclusive_disable(struct clk *clk)
+static void clk_gate_exclusive_disable(struct clk_hw *hw)
{
- struct clk_gate_exclusive *exgate = container_of(clk,
- struct clk_gate_exclusive, clk);
+ struct clk_gate_exclusive *exgate = to_clk_gate_exclusive(hw);
u32 val = readl(exgate->reg);
val &= ~(1 << exgate->shift);
@@ -58,10 +61,9 @@ static void clk_gate_exclusive_disable(struct clk *clk)
writel(val, exgate->reg);
}
-static int clk_gate_exclusive_is_enabled(struct clk *clk)
+static int clk_gate_exclusive_is_enabled(struct clk_hw *hw)
{
- struct clk_gate_exclusive *exgate = container_of(clk,
- struct clk_gate_exclusive, clk);
+ struct clk_gate_exclusive *exgate = to_clk_gate_exclusive(hw);
return readl(exgate->reg) & (1 << exgate->shift);
}
@@ -80,21 +82,21 @@ struct clk *imx_clk_gate_exclusive(const char *name, const char *parent,
exgate = xzalloc(sizeof(*exgate));
exgate->parent = parent;
- exgate->clk.name = name;
- exgate->clk.ops = &clk_gate_exclusive_ops;
- exgate->clk.flags = CLK_SET_RATE_PARENT;
- exgate->clk.parent_names = &exgate->parent;
- exgate->clk.num_parents = 1;
+ exgate->hw.clk.name = name;
+ exgate->hw.clk.ops = &clk_gate_exclusive_ops;
+ exgate->hw.clk.flags = CLK_SET_RATE_PARENT;
+ exgate->hw.clk.parent_names = &exgate->parent;
+ exgate->hw.clk.num_parents = 1;
exgate->reg = reg;
exgate->shift = shift;
exgate->exclusive_mask = exclusive_mask;
- ret = clk_register(&exgate->clk);
+ ret = bclk_register(&exgate->hw.clk);
if (ret) {
free(exgate);
return ERR_PTR(ret);
}
- return &exgate->clk;
+ return &exgate->hw.clk;
}
diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c
index 88eaae8db3..af83e93b12 100644
--- a/drivers/clk/imx/clk-gate2.c
+++ b/drivers/clk/imx/clk-gate2.c
@@ -13,25 +13,27 @@
struct clk_gate2 {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *reg;
int shift;
u8 cgr_val;
const char *parent;
-#define CLK_GATE_INVERTED (1 << 0)
unsigned flags;
};
-#define to_clk_gate2(_clk) container_of(_clk, struct clk_gate2, clk)
+static inline struct clk_gate2 *to_clk_gate2(struct clk_hw *hw)
+{
+ return container_of(hw, struct clk_gate2, hw);
+}
-static int clk_gate2_enable(struct clk *clk)
+static int clk_gate2_enable(struct clk_hw *hw)
{
- struct clk_gate2 *g = to_clk_gate2(clk);
+ struct clk_gate2 *g = to_clk_gate2(hw);
u32 val;
val = readl(g->reg);
- if (g->flags & CLK_GATE_INVERTED)
+ if (g->flags & CLK_GATE_SET_TO_DISABLE)
val &= ~(3 << g->shift);
else
val |= g->cgr_val << g->shift;
@@ -41,14 +43,14 @@ static int clk_gate2_enable(struct clk *clk)
return 0;
}
-static void clk_gate2_disable(struct clk *clk)
+static void clk_gate2_disable(struct clk_hw *hw)
{
- struct clk_gate2 *g = to_clk_gate2(clk);
+ struct clk_gate2 *g = to_clk_gate2(hw);
u32 val;
val = readl(g->reg);
- if (g->flags & CLK_GATE_INVERTED)
+ if (g->flags & CLK_GATE_SET_TO_DISABLE)
val |= 3 << g->shift;
else
val &= ~(3 << g->shift);
@@ -56,17 +58,17 @@ static void clk_gate2_disable(struct clk *clk)
writel(val, g->reg);
}
-static int clk_gate2_is_enabled(struct clk *clk)
+static int clk_gate2_is_enabled(struct clk_hw *hw)
{
- struct clk_gate2 *g = to_clk_gate2(clk);
+ struct clk_gate2 *g = to_clk_gate2(hw);
u32 val;
val = readl(g->reg);
if (val & (1 << g->shift))
- return g->flags & CLK_GATE_INVERTED ? 0 : 1;
+ return g->flags & CLK_GATE_SET_TO_DISABLE ? 0 : 1;
else
- return g->flags & CLK_GATE_INVERTED ? 1 : 0;
+ return g->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
}
static struct clk_ops clk_gate2_ops = {
@@ -87,13 +89,13 @@ static struct clk *clk_gate2_alloc(const char *name, const char *parent,
g->reg = reg;
g->cgr_val = cgr_val;
g->shift = shift;
- g->clk.ops = &clk_gate2_ops;
- g->clk.name = name;
- g->clk.parent_names = &g->parent;
- g->clk.num_parents = 1;
- g->clk.flags = CLK_SET_RATE_PARENT | flags;
+ g->hw.clk.ops = &clk_gate2_ops;
+ g->hw.clk.name = name;
+ g->hw.clk.parent_names = &g->parent;
+ g->hw.clk.num_parents = 1;
+ g->hw.clk.flags = CLK_SET_RATE_PARENT | flags;
- return &g->clk;
+ return &g->hw.clk;
}
struct clk *clk_gate2(const char *name, const char *parent, void __iomem *reg,
@@ -104,9 +106,10 @@ struct clk *clk_gate2(const char *name, const char *parent, void __iomem *reg,
g = clk_gate2_alloc(name , parent, reg, shift, cgr_val, flags);
- ret = clk_register(g);
+ ret = bclk_register(g);
if (ret) {
- free(to_clk_gate2(g));
+ struct clk_hw *hw = clk_to_clk_hw(g);
+ free(to_clk_gate2(hw));
return ERR_PTR(ret);
}
diff --git a/drivers/clk/imx/clk-imx1.c b/drivers/clk/imx/clk-imx1.c
index 258b9dd582..3b97fbcc6d 100644
--- a/drivers/clk/imx/clk-imx1.c
+++ b/drivers/clk/imx/clk-imx1.c
@@ -10,7 +10,7 @@
#include <io.h>
#include <linux/clkdev.h>
#include <linux/err.h>
-#include <mach/imx1-regs.h>
+#include <mach/imx/imx1-regs.h>
#include "clk.h"
@@ -73,7 +73,7 @@ static int __init mx1_clocks_init(void __iomem *regs, unsigned long fref)
return 0;
}
-static int imx1_ccm_probe(struct device_d *dev)
+static int imx1_ccm_probe(struct device *dev)
{
struct resource *iores;
void __iomem *regs;
@@ -95,15 +95,12 @@ static __maybe_unused struct of_device_id imx1_ccm_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, imx1_ccm_dt_ids);
-static struct driver_d imx1_ccm_driver = {
+static struct driver imx1_ccm_driver = {
.probe = imx1_ccm_probe,
.name = "imx1-ccm",
.of_compatible = DRV_OF_COMPAT(imx1_ccm_dt_ids),
};
-static int imx1_ccm_init(void)
-{
- return platform_driver_register(&imx1_ccm_driver);
-}
-core_initcall(imx1_ccm_init);
+core_platform_driver(imx1_ccm_driver);
diff --git a/drivers/clk/imx/clk-imx21.c b/drivers/clk/imx/clk-imx21.c
index 0026a55f86..6f2386e7d2 100644
--- a/drivers/clk/imx/clk-imx21.c
+++ b/drivers/clk/imx/clk-imx21.c
@@ -12,7 +12,7 @@
#include <io.h>
#include <linux/clkdev.h>
#include <linux/err.h>
-#include <mach/imx21-regs.h>
+#include <mach/imx/imx21-regs.h>
#include "clk.h"
@@ -92,7 +92,7 @@ static const char *spll_sel_clks[] = {
"ckih",
};
-static int imx21_ccm_probe(struct device_d *dev)
+static int imx21_ccm_probe(struct device *dev)
{
struct resource *iores;
void __iomem *base;
@@ -169,15 +169,12 @@ static __maybe_unused struct of_device_id imx21_ccm_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, imx21_ccm_dt_ids);
-static struct driver_d imx21_ccm_driver = {
+static struct driver imx21_ccm_driver = {
.probe = imx21_ccm_probe,
.name = "imx21-ccm",
.of_compatible = DRV_OF_COMPAT(imx21_ccm_dt_ids),
};
-static int imx21_ccm_init(void)
-{
- return platform_driver_register(&imx21_ccm_driver);
-}
-core_initcall(imx21_ccm_init);
+core_platform_driver(imx21_ccm_driver);
diff --git a/drivers/clk/imx/clk-imx25.c b/drivers/clk/imx/clk-imx25.c
index 7c2140c215..cbaca348e2 100644
--- a/drivers/clk/imx/clk-imx25.c
+++ b/drivers/clk/imx/clk-imx25.c
@@ -10,7 +10,7 @@
#include <io.h>
#include <linux/clkdev.h>
#include <linux/err.h>
-#include <mach/imx25-regs.h>
+#include <mach/imx/imx25-regs.h>
#include "clk.h"
@@ -37,25 +37,25 @@
#define CCM_MCR 0x64
enum mx25_clks {
- dummy, osc, mpll, upll, mpll_cpu_3_4, cpu_sel, cpu, ahb, usb_div, ipg,
- per0_sel, per1_sel, per2_sel, per3_sel, per4_sel, per5_sel, per6_sel,
- per7_sel, per8_sel, per9_sel, per10_sel, per11_sel, per12_sel,
- per13_sel, per14_sel, per15_sel, per0, per1, per2, per3, per4, per5,
- per6, per7, per8, per9, per10, per11, per12, per13, per14, per15,
- csi_ipg_per, epit_ipg_per, esai_ipg_per, esdhc1_ipg_per, esdhc2_ipg_per,
- gpt_ipg_per, i2c_ipg_per, lcdc_ipg_per, nfc_ipg_per, owire_ipg_per,
- pwm_ipg_per, sim1_ipg_per, sim2_ipg_per, ssi1_ipg_per, ssi2_ipg_per,
- uart_ipg_per, ata_ahb, reserved1, csi_ahb, emi_ahb, esai_ahb, esdhc1_ahb,
- esdhc2_ahb, fec_ahb, lcdc_ahb, rtic_ahb, sdma_ahb, slcdc_ahb, usbotg_ahb,
- reserved2, reserved3, reserved4, reserved5, can1_ipg, can2_ipg, csi_ipg,
- cspi1_ipg, cspi2_ipg, cspi3_ipg, dryice_ipg, ect_ipg, epit1_ipg, epit2_ipg,
- reserved6, esdhc1_ipg, esdhc2_ipg, fec_ipg, reserved7, reserved8, reserved9,
- gpt1_ipg, gpt2_ipg, gpt3_ipg, gpt4_ipg, reserved10, reserved11, reserved12,
- iim_ipg, reserved13, reserved14, kpp_ipg, lcdc_ipg, reserved15, pwm1_ipg,
- pwm2_ipg, pwm3_ipg, pwm4_ipg, rngb_ipg, reserved16, scc_ipg, sdma_ipg,
- sim1_ipg, sim2_ipg, slcdc_ipg, spba_ipg, ssi1_ipg, ssi2_ipg, tsc_ipg,
- uart1_ipg, uart2_ipg, uart3_ipg, uart4_ipg, uart5_ipg, reserved17,
- wdt_ipg, clk_max
+ /* 0 */ dummy, osc, mpll, upll, mpll_cpu_3_4, cpu_sel, cpu, ahb, usb_div, ipg,
+ /* 10 */ per0_sel, per1_sel, per2_sel, per3_sel, per4_sel, per5_sel, per6_sel,
+ /* 17 */ per7_sel, per8_sel, per9_sel, per10_sel, per11_sel, per12_sel,
+ /* 23 */ per13_sel, per14_sel, per15_sel, per0, per1, per2, per3, per4, per5,
+ /* 32 */ per6, per7, per8, per9, per10, per11, per12, per13, per14, per15,
+ /* 42 */ csi_ipg_per, epit_ipg_per, esai_ipg_per, esdhc1_ipg_per, esdhc2_ipg_per,
+ /* 47 */ gpt_ipg_per, i2c_ipg_per, lcdc_ipg_per, nfc_ipg_per, owire_ipg_per,
+ /* 52 */ pwm_ipg_per, sim1_ipg_per, sim2_ipg_per, ssi1_ipg_per, ssi2_ipg_per,
+ /* 57 */ uart_ipg_per, ata_ahb, reserved1, csi_ahb, emi_ahb, esai_ahb, esdhc1_ahb,
+ /* 64 */ esdhc2_ahb, fec_ahb, lcdc_ahb, rtic_ahb, sdma_ahb, slcdc_ahb, usbotg_ahb,
+ /* 71 */ reserved2, reserved3, reserved4, reserved5, can1_ipg, can2_ipg, csi_ipg,
+ /* 78 */ cspi1_ipg, cspi2_ipg, cspi3_ipg, dryice_ipg, ect_ipg, epit1_ipg, epit2_ipg,
+ /* 85 */ reserved6, esdhc1_ipg, esdhc2_ipg, fec_ipg, reserved7, reserved8, reserved9,
+ /* 92 */ gpt1_ipg, gpt2_ipg, gpt3_ipg, gpt4_ipg, reserved10, reserved11, reserved12,
+ /* 99 */ iim_ipg, reserved13, reserved14, kpp_ipg, lcdc_ipg, reserved15, pwm1_ipg,
+ /* 106 */ pwm2_ipg, pwm3_ipg, pwm4_ipg, rngb_ipg, reserved16, scc_ipg, sdma_ipg,
+ /* 113 */ sim1_ipg, sim2_ipg, slcdc_ipg, spba_ipg, ssi1_ipg, ssi2_ipg, tsc_ipg,
+ /* 120 */ uart1_ipg, uart2_ipg, uart3_ipg, uart4_ipg, uart5_ipg, reserved17,
+ /* 126 */ wdt_ipg, clk_max
};
static struct clk *clks[clk_max];
@@ -70,7 +70,7 @@ static const char *per_sel_clks[] = {
"upll",
};
-static int imx25_ccm_probe(struct device_d *dev)
+static int imx25_ccm_probe(struct device *dev)
{
struct resource *iores;
void __iomem *base;
@@ -143,6 +143,9 @@ static int imx25_ccm_probe(struct device_d *dev)
clks[rngb_ipg] = imx_clk_gate("rngb_ipg", "ipg", base + CCM_CGCR2, 3);
clks[dryice_ipg] = imx_clk_gate("dryice_ipg", "ipg", base + CCM_CGCR1, 8);
+ /* reserved in datasheet, but used as wdt in FSL kernel */
+ clks[wdt_ipg] = imx_clk_gate("wdt_ipg", "ipg", base + CCM_CGCR2, 19);
+
clkdev_add_physbase(clks[per15], MX25_UART1_BASE_ADDR, NULL);
clkdev_add_physbase(clks[per15], MX25_UART2_BASE_ADDR, NULL);
clkdev_add_physbase(clks[per15], MX25_UART3_BASE_ADDR, NULL);
@@ -168,6 +171,7 @@ static int imx25_ccm_probe(struct device_d *dev)
clkdev_add_physbase(clks[scc_ipg], MX25_SCC_BASE_ADDR, "ipg");
clkdev_add_physbase(clks[rngb_ipg], MX25_RNGB_BASE_ADDR, "ipg");
clkdev_add_physbase(clks[dryice_ipg], MX25_DRYICE_BASE_ADDR, NULL);
+ clkdev_add_physbase(clks[wdt_ipg], MX25_WATCHDOG_BASE_ADDR, NULL);
return 0;
}
@@ -179,15 +183,12 @@ static __maybe_unused struct of_device_id imx25_ccm_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, imx25_ccm_dt_ids);
-static struct driver_d imx25_ccm_driver = {
+static struct driver imx25_ccm_driver = {
.probe = imx25_ccm_probe,
.name = "imx25-ccm",
.of_compatible = DRV_OF_COMPAT(imx25_ccm_dt_ids),
};
-static int imx25_ccm_init(void)
-{
- return platform_driver_register(&imx25_ccm_driver);
-}
-core_initcall(imx25_ccm_init);
+core_platform_driver(imx25_ccm_driver);
diff --git a/drivers/clk/imx/clk-imx27.c b/drivers/clk/imx/clk-imx27.c
index cba655c6fe..083d87fb34 100644
--- a/drivers/clk/imx/clk-imx27.c
+++ b/drivers/clk/imx/clk-imx27.c
@@ -6,9 +6,9 @@
#include <io.h>
#include <linux/clkdev.h>
#include <linux/err.h>
-#include <mach/imx27-regs.h>
-#include <mach/generic.h>
-#include <mach/revision.h>
+#include <mach/imx/imx27-regs.h>
+#include <mach/imx/generic.h>
+#include <mach/imx/revision.h>
#include "clk.h"
@@ -155,7 +155,7 @@ static const char *clko_sel_clks[] = {
NULL,
};
-static int imx27_ccm_probe(struct device_d *dev)
+static int imx27_ccm_probe(struct device *dev)
{
struct resource *iores;
void __iomem *base;
@@ -257,15 +257,12 @@ static __maybe_unused struct of_device_id imx27_ccm_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, imx27_ccm_dt_ids);
-static struct driver_d imx27_ccm_driver = {
+static struct driver imx27_ccm_driver = {
.probe = imx27_ccm_probe,
.name = "imx27-ccm",
.of_compatible = DRV_OF_COMPAT(imx27_ccm_dt_ids),
};
-static int imx27_ccm_init(void)
-{
- return platform_driver_register(&imx27_ccm_driver);
-}
-core_initcall(imx27_ccm_init);
+core_platform_driver(imx27_ccm_driver);
diff --git a/drivers/clk/imx/clk-imx31.c b/drivers/clk/imx/clk-imx31.c
index 5fded58b11..47189f7814 100644
--- a/drivers/clk/imx/clk-imx31.c
+++ b/drivers/clk/imx/clk-imx31.c
@@ -10,7 +10,7 @@
#include <io.h>
#include <linux/clkdev.h>
#include <linux/err.h>
-#include <mach/imx31-regs.h>
+#include <mach/imx/imx31-regs.h>
#include "clk.h"
@@ -79,7 +79,7 @@ static const char *per_sel[] = {
"ipg",
};
-static int imx31_ccm_probe(struct device_d *dev)
+static int imx31_ccm_probe(struct device *dev)
{
struct resource *iores;
void __iomem *base;
@@ -138,15 +138,12 @@ static __maybe_unused struct of_device_id imx31_ccm_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, imx31_ccm_dt_ids);
-static struct driver_d imx31_ccm_driver = {
+static struct driver imx31_ccm_driver = {
.probe = imx31_ccm_probe,
.name = "imx31-ccm",
.of_compatible = DRV_OF_COMPAT(imx31_ccm_dt_ids),
};
-static int imx31_ccm_init(void)
-{
- return platform_driver_register(&imx31_ccm_driver);
-}
-core_initcall(imx31_ccm_init);
+core_platform_driver(imx31_ccm_driver);
diff --git a/drivers/clk/imx/clk-imx35.c b/drivers/clk/imx/clk-imx35.c
index 17e2ae5e69..7ea823c6c9 100644
--- a/drivers/clk/imx/clk-imx35.c
+++ b/drivers/clk/imx/clk-imx35.c
@@ -9,7 +9,7 @@
#include <io.h>
#include <linux/clkdev.h>
#include <linux/err.h>
-#include <mach/imx35-regs.h>
+#include <mach/imx/imx35-regs.h>
#include <reset_source.h>
#include "clk.h"
@@ -85,7 +85,7 @@ static const char *ipg_per_sel[] = {
"arm_per_div",
};
-static int imx35_ccm_probe(struct device_d *dev)
+static int imx35_ccm_probe(struct device *dev)
{
struct resource *iores;
u32 pdr0, consumer_sel, hsp_sel;
@@ -201,15 +201,12 @@ static __maybe_unused struct of_device_id imx35_ccm_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, imx35_ccm_dt_ids);
-static struct driver_d imx35_ccm_driver = {
+static struct driver imx35_ccm_driver = {
.probe = imx35_ccm_probe,
.name = "imx35-ccm",
.of_compatible = DRV_OF_COMPAT(imx35_ccm_dt_ids),
};
-static int imx35_ccm_init(void)
-{
- return platform_driver_register(&imx35_ccm_driver);
-}
-core_initcall(imx35_ccm_init);
+core_platform_driver(imx35_ccm_driver);
diff --git a/drivers/clk/imx/clk-imx5.c b/drivers/clk/imx/clk-imx5.c
index 6a07816427..b78611b0d4 100644
--- a/drivers/clk/imx/clk-imx5.c
+++ b/drivers/clk/imx/clk-imx5.c
@@ -10,9 +10,9 @@
#include <of.h>
#include <linux/clkdev.h>
#include <linux/err.h>
-#include <mach/imx50-regs.h>
-#include <mach/imx51-regs.h>
-#include <mach/imx53-regs.h>
+#include <mach/imx/imx50-regs.h>
+#include <mach/imx/imx51-regs.h>
+#include <mach/imx/imx53-regs.h>
#include <dt-bindings/clock/imx5-clock.h>
#include "clk.h"
@@ -194,7 +194,8 @@ static const char *ipu_sel[] = {
"ahb",
};
-static void __init mx5_clocks_common_init(struct device_d *dev, void __iomem *base)
+static void __init mx5_clocks_common_init(struct device *dev,
+ void __iomem *base)
{
writel(0xffffffff, base + CCM_CCGR0);
writel(0xffffffff, base + CCM_CCGR1);
@@ -205,7 +206,9 @@ static void __init mx5_clocks_common_init(struct device_d *dev, void __iomem *ba
writel(0xffffffff, base + CCM_CCGR6);
writel(0xffffffff, base + CCM_CCGR7);
- if (!IS_ENABLED(CONFIG_COMMON_CLK_OF_PROVIDER) || !dev->device_node) {
+ clks[IMX5_CLK_DUMMY] = clk_fixed("dummy", 0);
+
+ if (!IS_ENABLED(CONFIG_COMMON_CLK_OF_PROVIDER) || !dev->of_node) {
clks[IMX5_CLK_CKIL] = clk_fixed("ckil", 32768);
clks[IMX5_CLK_OSC] = clk_fixed("osc", 24000000);
}
@@ -277,7 +280,7 @@ static void mx5_clocks_ipu_init(void __iomem *regs)
clks[IMX5_CLK_IPU_SEL] = imx_clk_mux("ipu_sel", regs + CCM_CBCMR, 6, 2, ipu_sel, ARRAY_SIZE(ipu_sel));
}
-static int __init mx50_clocks_init(struct device_d *dev, void __iomem *regs)
+static int __init mx50_clocks_init(struct device *dev, void __iomem *regs)
{
clks[IMX5_CLK_PLL1_SW] = imx_clk_pllv2("pll1_sw", "osc",
(void *)MX50_PLL1_BASE_ADDR);
@@ -312,11 +315,12 @@ static int __init mx50_clocks_init(struct device_d *dev, void __iomem *regs)
clkdev_add_physbase(clks[IMX5_CLK_PER_ROOT], MX50_PWM1_BASE_ADDR, "per");
clkdev_add_physbase(clks[IMX5_CLK_PER_ROOT], MX50_PWM2_BASE_ADDR, "per");
clkdev_add_physbase(clks[IMX5_CLK_AHB], MX50_OTG_BASE_ADDR, NULL);
+ clkdev_add_physbase(clks[IMX5_CLK_DUMMY], MX50_WDOG1_BASE_ADDR, NULL);
return 0;
}
-static int imx50_ccm_probe(struct device_d *dev)
+static int imx50_ccm_probe(struct device *dev)
{
struct resource *iores;
void __iomem *regs;
@@ -338,8 +342,9 @@ static __maybe_unused struct of_device_id imx50_ccm_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, imx50_ccm_dt_ids);
-static struct driver_d imx50_ccm_driver = {
+static __maybe_unused struct driver imx50_ccm_driver = {
.probe = imx50_ccm_probe,
.name = "imx50-ccm",
.of_compatible = DRV_OF_COMPAT(imx50_ccm_dt_ids),
@@ -366,7 +371,7 @@ static void mx51_clocks_ipu_init(void __iomem *regs)
clkdev_add_physbase(clks[IMX5_CLK_IPU_DI1_SEL], MX51_IPU_BASE_ADDR, "di1");
}
-static int __init mx51_clocks_init(struct device_d *dev, void __iomem *regs)
+static int __init mx51_clocks_init(struct device *dev, void __iomem *regs)
{
clks[IMX5_CLK_PLL1_SW] = imx_clk_pllv2("pll1_sw", "osc", (void *)MX51_PLL1_BASE_ADDR);
clks[IMX5_CLK_PLL2_SW] = imx_clk_pllv2("pll2_sw", "osc", (void *)MX51_PLL2_BASE_ADDR);
@@ -392,6 +397,8 @@ static int __init mx51_clocks_init(struct device_d *dev, void __iomem *regs)
clkdev_add_physbase(clks[IMX5_CLK_IPG], MX51_ATA_BASE_ADDR, NULL);
clkdev_add_physbase(clks[IMX5_CLK_PER_ROOT], MX51_PWM1_BASE_ADDR, "per");
clkdev_add_physbase(clks[IMX5_CLK_PER_ROOT], MX51_PWM2_BASE_ADDR, "per");
+ clkdev_add_physbase(clks[IMX5_CLK_DUMMY], MX51_WDOG_BASE_ADDR, NULL);
+ clkdev_add_physbase(clks[IMX5_CLK_DUMMY], MX51_WDOG2_BASE_ADDR, NULL);
if (IS_ENABLED(CONFIG_DRIVER_VIDEO_IMX_IPUV3))
mx51_clocks_ipu_init(regs);
@@ -399,7 +406,7 @@ static int __init mx51_clocks_init(struct device_d *dev, void __iomem *regs)
return 0;
}
-static int imx51_ccm_probe(struct device_d *dev)
+static int imx51_ccm_probe(struct device *dev)
{
struct resource *iores;
void __iomem *regs;
@@ -413,7 +420,7 @@ static int imx51_ccm_probe(struct device_d *dev)
clk_data.clks = clks;
clk_data.clk_num = IMX5_CLK_END;
- of_clk_add_provider(dev->device_node, of_clk_src_onecell_get, &clk_data);
+ of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, &clk_data);
return 0;
}
@@ -425,8 +432,9 @@ static __maybe_unused struct of_device_id imx51_ccm_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, imx51_ccm_dt_ids);
-static struct driver_d imx51_ccm_driver = {
+static __maybe_unused struct driver imx51_ccm_driver = {
.probe = imx51_ccm_probe,
.name = "imx51-ccm",
.of_compatible = DRV_OF_COMPAT(imx51_ccm_dt_ids),
@@ -458,7 +466,7 @@ static void mx53_clocks_ipu_init(void __iomem *regs)
clkdev_add_physbase(clks[IMX5_CLK_IPU_DI1_SEL], MX53_IPU_BASE_ADDR, "di1");
}
-static int __init mx53_clocks_init(struct device_d *dev, void __iomem *regs)
+static int __init mx53_clocks_init(struct device *dev, void __iomem *regs)
{
clks[IMX5_CLK_PLL1_SW] = imx_clk_pllv2("pll1_sw", "osc", (void *)MX53_PLL1_BASE_ADDR);
clks[IMX5_CLK_PLL2_SW] = imx_clk_pllv2("pll2_sw", "osc", (void *)MX53_PLL2_BASE_ADDR);
@@ -488,6 +496,8 @@ static int __init mx53_clocks_init(struct device_d *dev, void __iomem *regs)
clkdev_add_physbase(clks[IMX5_CLK_AHB], MX53_SATA_BASE_ADDR, NULL);
clkdev_add_physbase(clks[IMX5_CLK_PER_ROOT], MX53_PWM1_BASE_ADDR, "per");
clkdev_add_physbase(clks[IMX5_CLK_PER_ROOT], MX53_PWM2_BASE_ADDR, "per");
+ clkdev_add_physbase(clks[IMX5_CLK_DUMMY], MX53_WDOG1_BASE_ADDR, NULL);
+ clkdev_add_physbase(clks[IMX5_CLK_DUMMY], MX53_WDOG2_BASE_ADDR, NULL);
if (IS_ENABLED(CONFIG_DRIVER_VIDEO_IMX_IPUV3))
mx53_clocks_ipu_init(regs);
@@ -495,7 +505,7 @@ static int __init mx53_clocks_init(struct device_d *dev, void __iomem *regs)
return 0;
}
-static int imx53_ccm_probe(struct device_d *dev)
+static int imx53_ccm_probe(struct device *dev)
{
struct resource *iores;
void __iomem *regs;
@@ -509,7 +519,7 @@ static int imx53_ccm_probe(struct device_d *dev)
clk_data.clks = clks;
clk_data.clk_num = IMX5_CLK_END;
- of_clk_add_provider(dev->device_node, of_clk_src_onecell_get, &clk_data);
+ of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, &clk_data);
return 0;
}
@@ -521,22 +531,20 @@ static __maybe_unused struct of_device_id imx53_ccm_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, imx53_ccm_dt_ids);
-static struct driver_d imx53_ccm_driver = {
+static __maybe_unused struct driver imx53_ccm_driver = {
.probe = imx53_ccm_probe,
.name = "imx53-ccm",
.of_compatible = DRV_OF_COMPAT(imx53_ccm_dt_ids),
};
-static int imx5_ccm_init(void)
-{
- if (IS_ENABLED(CONFIG_ARCH_IMX50))
- platform_driver_register(&imx50_ccm_driver);
- if (IS_ENABLED(CONFIG_ARCH_IMX51))
- platform_driver_register(&imx51_ccm_driver);
- if (IS_ENABLED(CONFIG_ARCH_IMX53))
- platform_driver_register(&imx53_ccm_driver);
-
- return 0;
-}
-core_initcall(imx5_ccm_init);
+#if IS_ENABLED(CONFIG_ARCH_IMX50)
+core_platform_driver(imx50_ccm_driver);
+#endif
+#if IS_ENABLED(CONFIG_ARCH_IMX51)
+core_platform_driver(imx51_ccm_driver);
+#endif
+#if IS_ENABLED(CONFIG_ARCH_IMX53)
+core_platform_driver(imx53_ccm_driver);
+#endif
diff --git a/drivers/clk/imx/clk-imx6.c b/drivers/clk/imx/clk-imx6.c
index b8b37a0c68..bac0c73d21 100644
--- a/drivers/clk/imx/clk-imx6.c
+++ b/drivers/clk/imx/clk-imx6.c
@@ -12,9 +12,9 @@
#include <of.h>
#include <linux/clkdev.h>
#include <linux/err.h>
-#include <mach/imx6-regs.h>
-#include <mach/revision.h>
-#include <mach/imx6.h>
+#include <mach/imx/imx6-regs.h>
+#include <mach/imx/revision.h>
+#include <mach/imx/imx6.h>
#include <dt-bindings/clock/imx6qdl-clock.h>
#include "clk.h"
@@ -60,8 +60,8 @@ static inline int cpu_mx6_is_plus(void)
/* Audio/Video PLL post dividers don't work on i.MX6q revision 1.0 */
static inline int cpu_has_working_video_pll_post_div(void) {
- return !((cpu_is_mx6q() || cpu_is_mx6d()) &&
- imx_silicon_revision() == IMX_CHIP_REV_1_0);
+ return !((cpu_mx6_is_mx6q() || cpu_mx6_is_mx6d()) &&
+ __imx6_cpu_revision() == IMX_CHIP_REV_1_0);
}
/* i.MX6 Quad/Dual/DualLite/Solo are all affected */
@@ -91,6 +91,13 @@ static const char *periph_pre_sels[] = {
static const char *periph_clk2_sels[] = {
"pll3_usb_otg",
"osc",
+ "osc",
+ "dummy",
+};
+
+static const char *periph2_clk2_sels[] = {
+ "pll3_usb_otg",
+ "pll2_bus",
};
static const char *periph_sels[] = {
@@ -106,6 +113,7 @@ static const char *periph2_sels[] = {
static const char *axi_sels[] = {
"periph",
"pll2_pfd2_396m",
+ "periph",
"pll3_pfd1_540m",
};
@@ -131,6 +139,13 @@ static const char *enfc_sels_plus[] = {
};
static const char *eim_sels[] = {
+ "pll2_pfd2_396m",
+ "pll3_usb_otg",
+ "axi",
+ "pll2_pfd0_352m",
+};
+
+static const char *eim_slow_sels[] = {
"axi",
"pll3_usb_otg",
"pll2_pfd2_396m",
@@ -151,8 +166,8 @@ static const char *cko1_sels[] = {
"pll3_usb_otg",
"pll2_bus",
"pll1_sys",
- "pll5_video",
- "dummy",
+ "pll5_video_div",
+ "video_27m",
"axi",
"enfc",
"ipu1_di0",
@@ -163,7 +178,7 @@ static const char *cko1_sels[] = {
"ipg",
"ipg_per",
"ckil",
- "pll4_audio",
+ "pll4_audio_div",
};
static const char *cko2_sels[] = {
@@ -482,9 +497,9 @@ static void init_ldb_clks(struct device_node *np, void __iomem *ccm_base)
of_assigned_ldb_sels(np, &sel[0][3], &sel[1][3]);
for (i = 0; i < 2; i++) {
- /* Warn if a glitch might have been introduced already */
+ /* log if a glitch might have been introduced already */
if (sel[i][0] != LDB_DI_SEL_MMDC_CH1_AXI) {
- pr_warn("ccm: ldb_di%d_sel already changed from reset value: %d\n",
+ pr_debug("ccm: ldb_di%d_sel already changed from reset value: %d\n",
i, sel[i][0]);
}
@@ -573,10 +588,6 @@ static void imx6_add_video_clks(void __iomem *anab, void __iomem *cb, struct dev
clks[IMX6QDL_CLK_IPU1_SEL] = imx_clk_mux("ipu1_sel", cb + 0x3c, 9, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
clks[IMX6QDL_CLK_IPU2_SEL] = imx_clk_mux("ipu2_sel", cb + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
- disable_anatop_clocks(anab);
-
- imx6q_mmdc_ch1_mask_handshake(cb);
-
if (cpu_mx6_has_err009219()) {
/*
* The LDB_DI0/1_SEL muxes should be read-only due to a hardware
@@ -612,6 +623,8 @@ static void imx6_add_video_clks(void __iomem *anab, void __iomem *cb, struct dev
clks[IMX6QDL_CLK_IPU2_DI0_PRE] = imx_clk_divider("ipu2_di0_pre", "ipu2_di0_pre_sel", cb + 0x38, 3, 3);
clks[IMX6QDL_CLK_IPU2_DI1_PRE] = imx_clk_divider("ipu2_di1_pre", "ipu2_di1_pre_sel", cb + 0x38, 12, 3);
+ clks[IMX6QDL_CLK_HDMI_IAHB] = imx_clk_gate2("hdmi_iahb", "ahb", cb + 0x70, 0);
+ clks[IMX6QDL_CLK_HDMI_ISFR] = imx_clk_gate2("hdmi_isfr", "mipi_core_cfg", cb + 0x70, 4);
clks[IMX6QDL_CLK_IPU1] = imx_clk_gate2("ipu1", "ipu1_podf", cb + 0x74, 0);
clks[IMX6QDL_CLK_IPU1_DI0] = imx_clk_gate2("ipu1_di0", "ipu1_di0_sel", cb + 0x74, 2);
clks[IMX6QDL_CLK_IPU1_DI1] = imx_clk_gate2("ipu1_di1", "ipu1_di1_sel", cb + 0x74, 4);
@@ -620,6 +633,8 @@ static void imx6_add_video_clks(void __iomem *anab, void __iomem *cb, struct dev
clks[IMX6QDL_CLK_LDB_DI0] = imx_clk_gate2("ldb_di0", "ldb_di0_podf", cb + 0x74, 12);
clks[IMX6QDL_CLK_LDB_DI1] = imx_clk_gate2("ldb_di1", "ldb_di1_podf", cb + 0x74, 14);
clks[IMX6QDL_CLK_IPU2_DI1] = imx_clk_gate2("ipu2_di1", "ipu2_di1_sel", cb + 0x74, 10);
+ clks[IMX6QDL_CLK_MIPI_CORE_CFG] = imx_clk_gate2("mipi_core_cfg", "video_27m", cb + 0x74, 16);
+ clks[IMX6QDL_CLK_VIDEO_27M] = imx_clk_fixed_factor("video_27m", "pll3_pfd1_540m", 1, 20);
clk_set_parent(clks[IMX6QDL_CLK_IPU1_DI0_SEL], clks[IMX6QDL_CLK_IPU1_DI0_PRE]);
clk_set_parent(clks[IMX6QDL_CLK_IPU1_DI1_SEL], clks[IMX6QDL_CLK_IPU1_DI1_PRE]);
@@ -632,7 +647,7 @@ static void imx6_add_video_clks(void __iomem *anab, void __iomem *cb, struct dev
clk_set_parent(clks[IMX6QDL_CLK_IPU2_DI1_PRE_SEL], clks[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
}
-static int imx6_ccm_probe(struct device_d *dev)
+static int imx6_ccm_probe(struct device *dev)
{
struct resource *iores;
void __iomem *base, *anatop_base, *ccm_base;
@@ -695,7 +710,7 @@ static int imx6_ccm_probe(struct device_d *dev)
clks[IMX6QDL_CLK_PERIPH_PRE] = imx_clk_mux("periph_pre", base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
clks[IMX6QDL_CLK_PERIPH2_PRE] = imx_clk_mux("periph2_pre", base + 0x18, 21, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
clks[IMX6QDL_CLK_PERIPH_CLK2_SEL] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 1, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
- clks[IMX6QDL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
+ clks[IMX6QDL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
clks[IMX6QDL_CLK_AXI_SEL] = imx_clk_mux("axi_sel", base + 0x14, 6, 2, axi_sels, ARRAY_SIZE(axi_sels));
clks[IMX6QDL_CLK_USDHC1_SEL] = imx_clk_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
clks[IMX6QDL_CLK_USDHC2_SEL] = imx_clk_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
@@ -706,7 +721,7 @@ static int imx6_ccm_probe(struct device_d *dev)
else
clks[IMX6QDL_CLK_ENFC_SEL] = imx_clk_mux("enfc_sel", base + 0x2c, 16, 2, enfc_sels, ARRAY_SIZE(enfc_sels));
clks[IMX6QDL_CLK_EIM_SEL] = imx_clk_mux("eim_sel", base + 0x1c, 27, 2, eim_sels, ARRAY_SIZE(eim_sels));
- clks[IMX6QDL_CLK_EIM_SLOW_SEL] = imx_clk_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_sels, ARRAY_SIZE(eim_sels));
+ clks[IMX6QDL_CLK_EIM_SLOW_SEL] = imx_clk_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_sels, ARRAY_SIZE(eim_slow_sels));
clks[IMX6QDL_CLK_VDO_AXI_SEL] = imx_clk_mux("vdo_axi_sel", base + 0x18, 11, 1, vdo_axi_sels, ARRAY_SIZE(vdo_axi_sels));
clks[IMX6QDL_CLK_CKO1_SEL] = imx_clk_mux("cko1_sel", base + 0x60, 0, 4, cko1_sels, ARRAY_SIZE(cko1_sels));
clks[IMX6QDL_CLK_CKO2_SEL] = imx_clk_mux("cko2_sel", base + 0x60, 16, 5, cko2_sels, ARRAY_SIZE(cko2_sels));
@@ -788,8 +803,12 @@ static int imx6_ccm_probe(struct device_d *dev)
clkdev_add_physbase(clks[IMX6QDL_CLK_IPG], MX6_OCOTP_BASE_ADDR, NULL);
+ disable_anatop_clocks(anatop_base);
+
+ imx6q_mmdc_ch1_mask_handshake(ccm_base);
+
if (IS_ENABLED(CONFIG_DRIVER_VIDEO_IMX_IPUV3))
- imx6_add_video_clks(anatop_base, ccm_base, dev->device_node);
+ imx6_add_video_clks(anatop_base, ccm_base, dev->of_node);
writel(0xffffffff, ccm_base + CCGR0);
writel(0xf0ffffff, ccm_base + CCGR1); /* gate GPU3D, GPU2D */
@@ -805,7 +824,7 @@ static int imx6_ccm_probe(struct device_d *dev)
clk_data.clks = clks;
clk_data.clk_num = IMX6QDL_CLK_END;
- of_clk_add_provider(dev->device_node, of_clk_src_onecell_get, &clk_data);
+ of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, &clk_data);
clk_enable(clks[IMX6QDL_CLK_MMDC_CH0_AXI_PODF]);
clk_enable(clks[IMX6QDL_CLK_PLL6_ENET]);
@@ -830,15 +849,12 @@ static __maybe_unused struct of_device_id imx6_ccm_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, imx6_ccm_dt_ids);
-static struct driver_d imx6_ccm_driver = {
+static struct driver imx6_ccm_driver = {
.probe = imx6_ccm_probe,
.name = "imx6-ccm",
.of_compatible = DRV_OF_COMPAT(imx6_ccm_dt_ids),
};
-static int imx6_ccm_init(void)
-{
- return platform_driver_register(&imx6_ccm_driver);
-}
-core_initcall(imx6_ccm_init);
+core_platform_driver(imx6_ccm_driver);
diff --git a/drivers/clk/imx/clk-imx6sl.c b/drivers/clk/imx/clk-imx6sl.c
index 6ccc36e3b9..93edf24c1d 100644
--- a/drivers/clk/imx/clk-imx6sl.c
+++ b/drivers/clk/imx/clk-imx6sl.c
@@ -7,15 +7,14 @@
#include <common.h>
#include <init.h>
#include <driver.h>
-#include <linux/clk.h>
#include <io.h>
#include <of.h>
#include <linux/clkdev.h>
#include <linux/err.h>
#include <linux/clk.h>
-#include <mach/imx6-regs.h>
-#include <mach/revision.h>
-#include <mach/imx6.h>
+#include <mach/imx/imx6-regs.h>
+#include <mach/imx/revision.h>
+#include <mach/imx/imx6.h>
#include "clk.h"
#include "common.h"
@@ -82,11 +81,11 @@ static struct clk_div_table video_div_table[] = {
{ }
};
-static int imx6sl_ccm_probe(struct device_d *dev)
+static int imx6sl_ccm_probe(struct device *dev)
{
struct resource *iores;
void __iomem *base, *anatop_base, *ccm_base;
- struct device_node *ccm_node = dev->device_node;
+ struct device_node *ccm_node = dev->of_node;
clks[IMX6SL_CLK_DUMMY] = clk_fixed("dummy", 0);
@@ -309,15 +308,12 @@ static __maybe_unused struct of_device_id imx6sl_ccm_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, imx6sl_ccm_dt_ids);
-static struct driver_d imx6sl_ccm_driver = {
+static struct driver imx6sl_ccm_driver = {
.probe = imx6sl_ccm_probe,
.name = "imx6-ccm",
.of_compatible = DRV_OF_COMPAT(imx6sl_ccm_dt_ids),
};
-static int imx6sl_ccm_init(void)
-{
- return platform_driver_register(&imx6sl_ccm_driver);
-}
-core_initcall(imx6sl_ccm_init);
+core_platform_driver(imx6sl_ccm_driver);
diff --git a/drivers/clk/imx/clk-imx6sx.c b/drivers/clk/imx/clk-imx6sx.c
index d682e41e7c..bebe1ed685 100644
--- a/drivers/clk/imx/clk-imx6sx.c
+++ b/drivers/clk/imx/clk-imx6sx.c
@@ -7,15 +7,14 @@
#include <common.h>
#include <init.h>
#include <driver.h>
-#include <linux/clk.h>
#include <io.h>
#include <of.h>
#include <linux/clkdev.h>
#include <linux/err.h>
#include <linux/clk.h>
-#include <mach/imx6-regs.h>
-#include <mach/revision.h>
-#include <mach/imx6.h>
+#include <mach/imx/imx6-regs.h>
+#include <mach/imx/revision.h>
+#include <mach/imx/imx6.h>
#include "clk.h"
#include "common.h"
@@ -110,11 +109,11 @@ static struct clk_div_table video_div_table[] = {
{ }
};
-static int imx6sx_ccm_probe(struct device_d *dev)
+static int imx6sx_ccm_probe(struct device *dev)
{
struct resource *iores;
void __iomem *base, *anatop_base, *ccm_base;
- struct device_node *ccm_node = dev->device_node;
+ struct device_node *ccm_node = dev->of_node;
clks[IMX6SX_CLK_DUMMY] = clk_fixed("dummy", 0);
@@ -463,15 +462,12 @@ static __maybe_unused struct of_device_id imx6sx_ccm_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, imx6sx_ccm_dt_ids);
-static struct driver_d imx6sx_ccm_driver = {
+static struct driver imx6sx_ccm_driver = {
.probe = imx6sx_ccm_probe,
.name = "imx6-ccm",
.of_compatible = DRV_OF_COMPAT(imx6sx_ccm_dt_ids),
};
-static int imx6sx_ccm_init(void)
-{
- return platform_driver_register(&imx6sx_ccm_driver);
-}
-core_initcall(imx6sx_ccm_init);
+core_platform_driver(imx6sx_ccm_driver);
diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c
index 79b52b7ce9..e60267d8fb 100644
--- a/drivers/clk/imx/clk-imx6ul.c
+++ b/drivers/clk/imx/clk-imx6ul.c
@@ -11,9 +11,9 @@
#include <of.h>
#include <linux/clkdev.h>
#include <linux/err.h>
-#include <mach/imx6-regs.h>
-#include <mach/revision.h>
-#include <mach/imx6.h>
+#include <mach/imx/imx6-regs.h>
+#include <mach/imx/revision.h>
+#include <mach/imx/imx6.h>
#include <dt-bindings/clock/imx6ul-clock.h>
#include "clk.h"
@@ -92,12 +92,13 @@ static struct clk_div_table clk_enet_ref_table[] = {
{ }
};
-static int imx6_ccm_probe(struct device_d *dev)
+static int imx6_ccm_probe(struct device *dev)
{
struct resource *iores;
void __iomem *base, *anatop_base, *ccm_base;
int i;
- struct device_node *ccm_node = dev->device_node;
+ struct device_node *ccm_node = dev->of_node;
+ struct clk_hw *hw;
anatop_base = IOMEM(MX6_ANATOP_BASE_ADDR);
iores = dev_request_mem_resource(dev, 0);
@@ -445,7 +446,8 @@ static int imx6_ccm_probe(struct device_d *dev)
clks[IMX6UL_CLK_PLL3_PFD2]);
/* Disable GPMI_IO clk before reparenting to avoid glitches */
- clks[IMX6UL_CLK_GPMI_IO]->ops->disable(clks[IMX6UL_CLK_GPMI_IO]);
+ hw = clk_to_clk_hw(clks[IMX6UL_CLK_GPMI_IO]);
+ clks[IMX6UL_CLK_GPMI_IO]->ops->disable(hw);
clk_set_parent(clks[IMX6UL_CLK_ENFC_SEL], clks[IMX6UL_CLK_PLL2_PFD2]);
@@ -459,15 +461,12 @@ static __maybe_unused struct of_device_id imx6_ccm_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, imx6_ccm_dt_ids);
-static struct driver_d imx6_ccm_driver = {
+static struct driver imx6_ccm_driver = {
.probe = imx6_ccm_probe,
.name = "imx6-ccm",
.of_compatible = DRV_OF_COMPAT(imx6_ccm_dt_ids),
};
-static int imx6_ccm_init(void)
-{
- return platform_driver_register(&imx6_ccm_driver);
-}
-core_initcall(imx6_ccm_init);
+core_platform_driver(imx6_ccm_driver);
diff --git a/drivers/clk/imx/clk-imx7.c b/drivers/clk/imx/clk-imx7.c
index 1f15d7ef11..224471a982 100644
--- a/drivers/clk/imx/clk-imx7.c
+++ b/drivers/clk/imx/clk-imx7.c
@@ -6,13 +6,14 @@
#include <common.h>
#include <init.h>
#include <driver.h>
+#include <deep-probe.h>
#include <linux/clk.h>
#include <io.h>
#include <of.h>
#include <linux/clkdev.h>
#include <linux/err.h>
-#include <mach/imx7-regs.h>
-#include <mach/revision.h>
+#include <mach/imx/imx7-regs.h>
+#include <mach/imx/revision.h>
#include <dt-bindings/clock/imx7d-clock.h>
#include "clk.h"
@@ -358,9 +359,11 @@ static int const clks_init_on[] __initconst = {
static struct clk_onecell_data clk_data;
-static int imx7_clk_initialized;
+static struct device_node *ccm_np;
-static int imx7_ccm_probe(struct device_d *dev)
+static int imx7_clk_setup(void);
+
+static int imx7_ccm_probe(struct device *dev)
{
struct resource *iores;
void __iomem *base, *anatop_base, *ccm_base;
@@ -722,10 +725,12 @@ static int imx7_ccm_probe(struct device_d *dev)
clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate4("ocram_s_clk", "ahb_post_div", base + 0x4120, 0);
clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_gate4("nand_usdhc_root_clk", "nand_usdhc_post_div", base + 0x4130, 0);
clks[IMX7D_AHB_CHANNEL_ROOT_CLK] = imx_clk_gate4("ahb_root_clk", "ahb_post_div", base + 0x4200, 0);
+ clks[IMX7D_IPG_ROOT_CLK] = imx_clk_divider_flags("ipg_root_clk", "ahb_root_clk", base + 0x9080, 0, 2, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_PARENT);
clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate4("dram_root_clk", "dram_post_div", base + 0x4130, 0);
clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0);
clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate4("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0);
clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate4("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0);
+ clks[IMX7D_OCOTP_CLK] = imx_clk_gate4("ocotp_clk", "ipg_root_clk", base + 0x4230, 0);
clks[IMX7D_USB_HSIC_ROOT_CLK] = imx_clk_gate4("usb_hsic_root_clk", "usb_hsic_post_div", base + 0x4420, 0);
clks[IMX7D_SDMA_CORE_CLK] = imx_clk_gate4("sdma_root_clk", "ahb_root_clk", base + 0x4480, 0);
clks[IMX7D_PCIE_CTRL_ROOT_CLK] = imx_clk_gate4("pcie_ctrl_root_clk", "pcie_ctrl_post_div", base + 0x4600, 0);
@@ -802,21 +807,37 @@ static int imx7_ccm_probe(struct device_d *dev)
clk_data.clks = clks;
clk_data.clk_num = ARRAY_SIZE(clks);
- of_clk_add_provider(dev->device_node, of_clk_src_onecell_get, &clk_data);
+ of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, &clk_data);
+
+ ccm_np = dev->of_node;
- imx7_clk_initialized = 1;
+ /*
+ * imx7_clk_setup() requires both the CCM and fixed-clock osc devices
+ * to be available.
+ * With deep probe enabled, we can instead just directly call
+ * imx7_clk_setup because the osc fixed-clock will just be probed
+ * on demand if not yet available. Otherwise, the imx7_clk_setup
+ * will run at postcore_initcall level.
+ */
+ if (deep_probe_is_supported())
+ return imx7_clk_setup();
return 0;
}
static int imx7_clk_setup(void)
{
+ struct clk *clk;
int i;
- if (!imx7_clk_initialized)
+ if (!ccm_np)
return 0;
- clks[IMX7D_OSC_24M_CLK] = clk_lookup("osc");
+ clk = of_clk_get_by_name(ccm_np, "osc");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ clks[IMX7D_OSC_24M_CLK] = clk;
for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
clk_enable(clks[clks_init_on[i]]);
@@ -838,6 +859,8 @@ static int imx7_clk_setup(void)
clk_set_rate(clks[IMX7D_ENET1_TIME_ROOT_CLK], 25000000);
clk_set_rate(clks[IMX7D_ENET2_TIME_ROOT_CLK], 25000000);
+ ccm_np = NULL;
+
return 0;
}
postcore_initcall(imx7_clk_setup);
@@ -849,15 +872,12 @@ static __maybe_unused struct of_device_id imx7_ccm_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, imx7_ccm_dt_ids);
-static struct driver_d imx7_ccm_driver = {
+static struct driver imx7_ccm_driver = {
.probe = imx7_ccm_probe,
.name = "imx6-ccm",
.of_compatible = DRV_OF_COMPAT(imx7_ccm_dt_ids),
};
-static int imx7_ccm_init(void)
-{
- return platform_driver_register(&imx7_ccm_driver);
-}
-core_initcall(imx7_ccm_init);
+core_platform_driver(imx7_ccm_driver);
diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
index a31741af88..d467062e64 100644
--- a/drivers/clk/imx/clk-imx8mm.c
+++ b/drivers/clk/imx/clk-imx8mm.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2017-2018 NXP.
*/
@@ -26,6 +26,8 @@ static const char *sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
static const char *imx8mm_a53_sels[] = {"osc_24m", "arm_pll_out", "sys_pll2_500m", "sys_pll2_1000m",
"sys_pll1_800m", "sys_pll1_400m", "audio_pll1_out", "sys_pll3_out", };
+static const char *imx8mm_a53_core_sels[] = {"arm_a53_div", "arm_pll_out", };
+
static const char *imx8mm_m4_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_250m", "sys_pll1_266m",
"sys_pll1_800m", "audio_pll1_out", "video_pll1_out", "sys_pll3_out", };
@@ -278,6 +280,7 @@ static int imx8mm_clocks_init(struct device_node *ccm_np)
{
struct device_node *anatop_np;
void __iomem *ccm, *ana;
+ u32 val;
int ret;
anatop_np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
@@ -338,45 +341,45 @@ static int imx8mm_clocks_init(struct device_node *ccm_np)
clks[IMX8MM_SYS_PLL3_OUT] = imx_clk_gate("sys_pll3_out", "sys_pll3_bypass", ana + 0x114, 11);
/* SYS PLL1 fixed output */
- clks[IMX8MM_SYS_PLL1_40M_CG] = imx_clk_gate("sys_pll1_40m_cg", "sys_pll1", ana + 0x94, 27);
- clks[IMX8MM_SYS_PLL1_80M_CG] = imx_clk_gate("sys_pll1_80m_cg", "sys_pll1", ana + 0x94, 25);
- clks[IMX8MM_SYS_PLL1_100M_CG] = imx_clk_gate("sys_pll1_100m_cg", "sys_pll1", ana + 0x94, 23);
- clks[IMX8MM_SYS_PLL1_133M_CG] = imx_clk_gate("sys_pll1_133m_cg", "sys_pll1", ana + 0x94, 21);
- clks[IMX8MM_SYS_PLL1_160M_CG] = imx_clk_gate("sys_pll1_160m_cg", "sys_pll1", ana + 0x94, 19);
- clks[IMX8MM_SYS_PLL1_200M_CG] = imx_clk_gate("sys_pll1_200m_cg", "sys_pll1", ana + 0x94, 17);
- clks[IMX8MM_SYS_PLL1_266M_CG] = imx_clk_gate("sys_pll1_266m_cg", "sys_pll1", ana + 0x94, 15);
- clks[IMX8MM_SYS_PLL1_400M_CG] = imx_clk_gate("sys_pll1_400m_cg", "sys_pll1", ana + 0x94, 13);
+ /*
+ * The gates in CCM_ANALOG_SYS_PLL1_GEN_CTRL are not handled by the
+ * driver, make sure they are all enabled.
+ */
+ val = readl(ana + 0x94);
+ val |= BIT(13) | BIT(15) | BIT(17) | BIT(19) | BIT(21) | BIT(23) | BIT(25) | BIT(27);
+ writel(val, ana + 0x94);
+
clks[IMX8MM_SYS_PLL1_OUT] = imx_clk_gate("sys_pll1_out", "sys_pll1", ana + 0x94, 11);
- clks[IMX8MM_SYS_PLL1_40M] = imx_clk_fixed_factor("sys_pll1_40m", "sys_pll1_40m_cg", 1, 20);
- clks[IMX8MM_SYS_PLL1_80M] = imx_clk_fixed_factor("sys_pll1_80m", "sys_pll1_80m_cg", 1, 10);
- clks[IMX8MM_SYS_PLL1_100M] = imx_clk_fixed_factor("sys_pll1_100m", "sys_pll1_100m_cg", 1, 8);
- clks[IMX8MM_SYS_PLL1_133M] = imx_clk_fixed_factor("sys_pll1_133m", "sys_pll1_133m_cg", 1, 6);
- clks[IMX8MM_SYS_PLL1_160M] = imx_clk_fixed_factor("sys_pll1_160m", "sys_pll1_160m_cg", 1, 5);
- clks[IMX8MM_SYS_PLL1_200M] = imx_clk_fixed_factor("sys_pll1_200m", "sys_pll1_200m_cg", 1, 4);
- clks[IMX8MM_SYS_PLL1_266M] = imx_clk_fixed_factor("sys_pll1_266m", "sys_pll1_266m_cg", 1, 3);
- clks[IMX8MM_SYS_PLL1_400M] = imx_clk_fixed_factor("sys_pll1_400m", "sys_pll1_400m_cg", 1, 2);
+ clks[IMX8MM_SYS_PLL1_40M] = imx_clk_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20);
+ clks[IMX8MM_SYS_PLL1_80M] = imx_clk_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10);
+ clks[IMX8MM_SYS_PLL1_100M] = imx_clk_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8);
+ clks[IMX8MM_SYS_PLL1_133M] = imx_clk_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6);
+ clks[IMX8MM_SYS_PLL1_160M] = imx_clk_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5);
+ clks[IMX8MM_SYS_PLL1_200M] = imx_clk_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4);
+ clks[IMX8MM_SYS_PLL1_266M] = imx_clk_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3);
+ clks[IMX8MM_SYS_PLL1_400M] = imx_clk_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2);
clks[IMX8MM_SYS_PLL1_800M] = imx_clk_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1);
/* SYS PLL2 fixed output */
- clks[IMX8MM_SYS_PLL2_50M_CG] = imx_clk_gate("sys_pll2_50m_cg", "sys_pll2", ana + 0x104, 27);
- clks[IMX8MM_SYS_PLL2_100M_CG] = imx_clk_gate("sys_pll2_100m_cg", "sys_pll2", ana + 0x104, 25);
- clks[IMX8MM_SYS_PLL2_125M_CG] = imx_clk_gate("sys_pll2_125m_cg", "sys_pll2", ana + 0x104, 23);
- clks[IMX8MM_SYS_PLL2_166M_CG] = imx_clk_gate("sys_pll2_166m_cg", "sys_pll2", ana + 0x104, 21);
- clks[IMX8MM_SYS_PLL2_200M_CG] = imx_clk_gate("sys_pll2_200m_cg", "sys_pll2", ana + 0x104, 19);
- clks[IMX8MM_SYS_PLL2_250M_CG] = imx_clk_gate("sys_pll2_250m_cg", "sys_pll2", ana + 0x104, 17);
- clks[IMX8MM_SYS_PLL2_333M_CG] = imx_clk_gate("sys_pll2_333m_cg", "sys_pll2", ana + 0x104, 15);
- clks[IMX8MM_SYS_PLL2_500M_CG] = imx_clk_gate("sys_pll2_500m_cg", "sys_pll2", ana + 0x104, 13);
+ /*
+ * The gates in CCM_ANALOG_SYS_PLL2_GEN_CTRL are not handled by the
+ * driver, make sure they are all enabled.
+ */
+ val = readl(ana + 0x104);
+ val |= BIT(13) | BIT(15) | BIT(17) | BIT(19) | BIT(21) | BIT(23) | BIT(25) | BIT(27);
+ writel(val, ana + 0x104);
+
clks[IMX8MM_SYS_PLL2_OUT] = imx_clk_gate("sys_pll2_out", "sys_pll2", ana + 0x104, 11);
- clks[IMX8MM_SYS_PLL2_50M] = imx_clk_fixed_factor("sys_pll2_50m", "sys_pll2_50m_cg", 1, 20);
- clks[IMX8MM_SYS_PLL2_100M] = imx_clk_fixed_factor("sys_pll2_100m", "sys_pll2_100m_cg", 1, 10);
- clks[IMX8MM_SYS_PLL2_125M] = imx_clk_fixed_factor("sys_pll2_125m", "sys_pll2_125m_cg", 1, 8);
- clks[IMX8MM_SYS_PLL2_166M] = imx_clk_fixed_factor("sys_pll2_166m", "sys_pll2_166m_cg", 1, 6);
- clks[IMX8MM_SYS_PLL2_200M] = imx_clk_fixed_factor("sys_pll2_200m", "sys_pll2_200m_cg", 1, 5);
- clks[IMX8MM_SYS_PLL2_250M] = imx_clk_fixed_factor("sys_pll2_250m", "sys_pll2_250m_cg", 1, 4);
- clks[IMX8MM_SYS_PLL2_333M] = imx_clk_fixed_factor("sys_pll2_333m", "sys_pll2_333m_cg", 1, 3);
- clks[IMX8MM_SYS_PLL2_500M] = imx_clk_fixed_factor("sys_pll2_500m", "sys_pll2_500m_cg", 1, 2);
+ clks[IMX8MM_SYS_PLL2_50M] = imx_clk_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20);
+ clks[IMX8MM_SYS_PLL2_100M] = imx_clk_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10);
+ clks[IMX8MM_SYS_PLL2_125M] = imx_clk_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8);
+ clks[IMX8MM_SYS_PLL2_166M] = imx_clk_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6);
+ clks[IMX8MM_SYS_PLL2_200M] = imx_clk_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5);
+ clks[IMX8MM_SYS_PLL2_250M] = imx_clk_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4);
+ clks[IMX8MM_SYS_PLL2_333M] = imx_clk_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3);
+ clks[IMX8MM_SYS_PLL2_500M] = imx_clk_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2);
clks[IMX8MM_SYS_PLL2_1000M] = imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
/* Core Slice */
@@ -396,6 +399,9 @@ static int imx8mm_clocks_init(struct device_node *ccm_np)
clks[IMX8MM_CLK_GPU3D_DIV] = imx_clk_divider2("gpu3d_div", "gpu3d_cg", ccm + 0x8180, 0, 3);
clks[IMX8MM_CLK_GPU2D_DIV] = imx_clk_divider2("gpu2d_div", "gpu2d_cg", ccm + 0x8200, 0, 3);
+ /* CORE SEL */
+ clks[IMX8MM_CLK_A53_CORE] = imx_clk_mux2_flags("arm_a53_core", ccm + 0x9880, 24, 1, imx8mm_a53_core_sels, ARRAY_SIZE(imx8mm_a53_core_sels), CLK_IS_CRITICAL);
+
/* BUS */
clks[IMX8MM_CLK_MAIN_AXI] = imx8m_clk_composite_critical("main_axi", imx8mm_main_axi_sels, ccm + 0x8800);
clks[IMX8MM_CLK_ENET_AXI] = imx8m_clk_composite("enet_axi", imx8mm_enet_axi_sels, ccm + 0x8880);
@@ -556,11 +562,11 @@ static int imx8mm_clocks_init(struct device_node *ccm_np)
clks[IMX8MM_CLK_DRAM_ALT_ROOT] = imx_clk_fixed_factor("dram_alt_root", "dram_alt", 1, 4);
clks[IMX8MM_CLK_DRAM_CORE] = imx_clk_mux2_flags("dram_core_clk", ccm + 0x9800, 24, 1, imx8mm_dram_core_sels, ARRAY_SIZE(imx8mm_dram_core_sels), CLK_IS_CRITICAL);
- clks[IMX8MM_CLK_ARM] = imx_clk_cpu("arm", "arm_a53_div",
- clks[IMX8MM_CLK_A53_DIV],
- clks[IMX8MM_CLK_A53_SRC],
+ clks[IMX8MM_CLK_ARM] = imx_clk_cpu("arm", "arm_a53_core",
+ clks[IMX8MM_CLK_A53_CORE],
+ clks[IMX8MM_CLK_A53_CORE],
clks[IMX8MM_ARM_PLL_OUT],
- clks[IMX8MM_SYS_PLL1_800M]);
+ clks[IMX8MM_CLK_A53_DIV]);
imx_check_clocks(clks, ARRAY_SIZE(clks));
diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c
new file mode 100644
index 0000000000..02522add39
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8mn.c
@@ -0,0 +1,559 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2018-2019 NXP.
+ */
+
+#include <dt-bindings/clock/imx8mn-clock.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <of_address.h>
+
+#include "clk.h"
+
+static const char * const pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
+static const char * const audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
+static const char * const audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", };
+static const char * const video_pll1_bypass_sels[] = {"video_pll1", "video_pll1_ref_sel", };
+static const char * const dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
+static const char * const gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
+static const char * const vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
+static const char * const arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
+static const char * const sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
+
+static const char * const imx8mn_a53_sels[] = {"osc_24m", "arm_pll_out", "sys_pll2_500m",
+ "sys_pll2_1000m", "sys_pll1_800m", "sys_pll1_400m",
+ "audio_pll1_out", "sys_pll3_out", };
+
+static const char * const imx8mn_a53_core_sels[] = {"arm_a53_div", "arm_pll_out", };
+
+static const char * const imx8mn_gpu_core_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m",
+ "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mn_gpu_shader_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m",
+ "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mn_main_axi_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll1_800m",
+ "sys_pll2_250m", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "sys_pll1_100m",};
+
+static const char * const imx8mn_enet_axi_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m",
+ "sys_pll2_250m", "sys_pll2_200m", "audio_pll1_out",
+ "video_pll1_out", "sys_pll3_out", };
+
+static const char * const imx8mn_nand_usdhc_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m",
+ "sys_pll2_200m", "sys_pll1_133m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll1_out", };
+
+static const char * const imx8mn_disp_axi_sels[] = {"osc_24m", "sys_pll2_1000m", "sys_pll1_800m",
+ "sys_pll3_out", "sys_pll1_40m", "audio_pll2_out",
+ "clk_ext1", "clk_ext4", };
+
+static const char * const imx8mn_disp_apb_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll1_800m",
+ "sys_pll3_out", "sys_pll1_40m", "audio_pll2_out",
+ "clk_ext1", "clk_ext3", };
+
+static const char * const imx8mn_usb_bus_sels[] = {"osc_24m", "sys_pll2_500m", "sys_pll1_800m",
+ "sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
+ "clk_ext4", "audio_pll2_out", };
+
+static const char * const imx8mn_gpu_axi_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out",
+ "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mn_gpu_ahb_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out",
+ "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mn_noc_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_1000m", "sys_pll2_500m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mn_ahb_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_800m",
+ "sys_pll1_400m", "sys_pll2_125m", "sys_pll3_out",
+ "audio_pll1_out", "video_pll1_out", };
+
+static const char * const imx8mn_audio_ahb_sels[] = {"osc_24m", "sys_pll2_500m", "sys_pll1_800m",
+ "sys_pll2_1000m", "sys_pll2_166m", "sys_pll3_out",
+ "audio_pll1_out", "video_pll1_out", };
+
+static const char * const imx8mn_dram_alt_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll1_100m",
+ "sys_pll2_500m", "sys_pll2_1000m", "sys_pll3_out",
+ "audio_pll1_out", "sys_pll1_266m", };
+
+static const char * const imx8mn_dram_apb_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m",
+ "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll2_out", };
+
+static const char * const imx8mn_disp_pixel_sels[] = {"osc_24m", "video_pll1_out", "audio_pll2_out",
+ "audio_pll1_out", "sys_pll1_800m", "sys_pll2_1000m",
+ "sys_pll3_out", "clk_ext4", };
+
+static const char * const imx8mn_sai2_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
+ "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "clk_ext3", "clk_ext4", };
+
+static const char * const imx8mn_sai3_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
+ "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "clk_ext3", "clk_ext4", };
+
+static const char * const imx8mn_sai5_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
+ "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "clk_ext2", "clk_ext3", };
+
+static const char * const imx8mn_sai6_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
+ "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "clk_ext3", "clk_ext4", };
+
+static const char * const imx8mn_sai7_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
+ "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "clk_ext3", "clk_ext4", };
+
+static const char * const imx8mn_spdif1_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
+ "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "clk_ext2", "clk_ext3", };
+
+static const char * const imx8mn_enet_ref_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_50m",
+ "sys_pll2_100m", "sys_pll1_160m", "audio_pll1_out",
+ "video_pll1_out", "clk_ext4", };
+
+static const char * const imx8mn_enet_timer_sels[] = {"osc_24m", "sys_pll2_100m", "audio_pll1_out",
+ "clk_ext1", "clk_ext2", "clk_ext3",
+ "clk_ext4", "video_pll1_out", };
+
+static const char * const imx8mn_enet_phy_sels[] = {"osc_24m", "sys_pll2_50m", "sys_pll2_125m",
+ "sys_pll2_200m", "sys_pll2_500m", "video_pll1_out",
+ "audio_pll2_out", };
+
+static const char * const imx8mn_nand_sels[] = {"osc_24m", "sys_pll2_500m", "audio_pll1_out",
+ "sys_pll1_400m", "audio_pll2_out", "sys_pll3_out",
+ "sys_pll2_250m", "video_pll1_out", };
+
+static const char * const imx8mn_qspi_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll2_333m",
+ "sys_pll2_500m", "audio_pll2_out", "sys_pll1_266m",
+ "sys_pll3_out", "sys_pll1_100m", };
+
+static const char * const imx8mn_usdhc1_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m",
+ "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
+ "audio_pll2_out", "sys_pll1_100m", };
+
+static const char * const imx8mn_usdhc2_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m",
+ "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
+ "audio_pll2_out", "sys_pll1_100m", };
+
+static const char * const imx8mn_i2c1_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
+ "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "audio_pll2_out", "sys_pll1_133m", };
+
+static const char * const imx8mn_i2c2_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
+ "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "audio_pll2_out", "sys_pll1_133m", };
+
+static const char * const imx8mn_i2c3_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
+ "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "audio_pll2_out", "sys_pll1_133m", };
+
+static const char * const imx8mn_i2c4_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
+ "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "audio_pll2_out", "sys_pll1_133m", };
+
+static const char * const imx8mn_uart1_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m",
+ "sys_pll2_100m", "sys_pll3_out", "clk_ext2",
+ "clk_ext4", "audio_pll2_out", };
+
+static const char * const imx8mn_uart2_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m",
+ "sys_pll2_100m", "sys_pll3_out", "clk_ext2",
+ "clk_ext3", "audio_pll2_out", };
+
+static const char * const imx8mn_uart3_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m",
+ "sys_pll2_100m", "sys_pll3_out", "clk_ext2",
+ "clk_ext4", "audio_pll2_out", };
+
+static const char * const imx8mn_uart4_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m",
+ "sys_pll2_100m", "sys_pll3_out", "clk_ext2",
+ "clk_ext3", "audio_pll2_out", };
+
+static const char * const imx8mn_usb_core_sels[] = {"osc_24m", "sys_pll1_100m", "sys_pll1_40m",
+ "sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
+ "clk_ext3", "audio_pll2_out", };
+
+static const char * const imx8mn_usb_phy_sels[] = {"osc_24m", "sys_pll1_100m", "sys_pll1_40m",
+ "sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
+ "clk_ext3", "audio_pll2_out", };
+
+static const char * const imx8mn_gic_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m",
+ "sys_pll2_100m", "sys_pll1_800m", "clk_ext2",
+ "clk_ext4", "audio_pll2_out" };
+
+static const char * const imx8mn_ecspi1_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m",
+ "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll2_out", };
+
+static const char * const imx8mn_ecspi2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m",
+ "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll2_out", };
+
+static const char * const imx8mn_pwm1_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
+ "sys_pll1_40m", "sys_pll3_out", "clk_ext1",
+ "sys_pll1_80m", "video_pll1_out", };
+
+static const char * const imx8mn_pwm2_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
+ "sys_pll1_40m", "sys_pll3_out", "clk_ext1",
+ "sys_pll1_80m", "video_pll1_out", };
+
+static const char * const imx8mn_pwm3_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
+ "sys_pll1_40m", "sys_pll3_out", "clk_ext2",
+ "sys_pll1_80m", "video_pll1_out", };
+
+static const char * const imx8mn_pwm4_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
+ "sys_pll1_40m", "sys_pll3_out", "clk_ext2",
+ "sys_pll1_80m", "video_pll1_out", };
+
+static const char * const imx8mn_wdog_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_160m",
+ "vpu_pll_out", "sys_pll2_125m", "sys_pll3_out",
+ "sys_pll1_80m", "sys_pll2_166m", };
+
+static const char * const imx8mn_wrclk_sels[] = {"osc_24m", "sys_pll1_40m", "vpu_pll_out",
+ "sys_pll3_out", "sys_pll2_200m", "sys_pll1_266m",
+ "sys_pll2_500m", "sys_pll1_100m", };
+
+static const char * const imx8mn_dsi_core_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m",
+ "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
+ "audio_pll2_out", "video_pll1_out", };
+
+static const char * const imx8mn_dsi_phy_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_100m",
+ "sys_pll1_800m", "sys_pll2_1000m", "clk_ext2",
+ "audio_pll2_out", "video_pll1_out", };
+
+static const char * const imx8mn_dsi_dbi_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_100m",
+ "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
+ "audio_pll2_out", "video_pll1_out", };
+
+static const char * const imx8mn_usdhc3_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m",
+ "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
+ "audio_pll2_out", "sys_pll1_100m", };
+
+static const char * const imx8mn_camera_pixel_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m",
+ "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
+ "audio_pll2_out", "video_pll1_out", };
+
+static const char * const imx8mn_csi1_phy_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m",
+ "sys_pll1_800m", "sys_pll2_1000m", "clk_ext2",
+ "audio_pll2_out", "video_pll1_out", };
+
+static const char * const imx8mn_csi2_phy_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m",
+ "sys_pll1_800m", "sys_pll2_1000m", "clk_ext2",
+ "audio_pll2_out", "video_pll1_out", };
+
+static const char * const imx8mn_csi2_esc_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_80m",
+ "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
+ "clk_ext3", "audio_pll2_out", };
+
+static const char * const imx8mn_ecspi3_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m",
+ "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll2_out", };
+
+static const char * const imx8mn_pdm_sels[] = {"osc_24m", "sys_pll2_100m", "audio_pll1_out",
+ "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
+ "clk_ext3", "audio_pll2_out", };
+
+static const char * const imx8mn_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
+
+static const char * const imx8mn_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "osc_27m",
+ "sys_pll1_200m", "audio_pll2_out", "vpu_pll",
+ "sys_pll1_80m", };
+static const char * const imx8mn_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_400m",
+ "sys_pll2_166m", "sys_pll3_out", "audio_pll1_out",
+ "video_pll1_out", "osc_32k", };
+
+static const char * const clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+ "dummy", "dummy", "gpu_pll_out", "dummy",
+ "arm_pll_out", "sys_pll1", "sys_pll2", "sys_pll3",
+ "dummy", "dummy", "osc_24m", "dummy", "osc_32k"};
+
+static struct clk *clks[IMX8MN_CLK_END];
+static struct clk_onecell_data clk_data;
+
+static int imx8mn_clocks_init(struct device_node *ccm_np)
+{
+ struct device_node *anatop_np;
+ void __iomem *ccm, *ana;
+ u32 val;
+ int ret;
+
+ anatop_np = of_find_compatible_node(NULL, NULL, "fsl,imx8mn-anatop");
+ ana = of_iomap(anatop_np, 0);
+ if (WARN_ON(!ana))
+ return -ENOMEM;
+
+ ccm = of_iomap(ccm_np, 0);
+ if (WARN_ON(!ccm))
+ return -ENOMEM;
+
+ clks[IMX8MN_CLK_DUMMY] = clk_fixed("dummy", 0);
+ clks[IMX8MN_CLK_24M] = of_clk_get_by_name(ccm_np, "osc_24m");
+ clks[IMX8MN_CLK_32K] = of_clk_get_by_name(ccm_np, "osc_32k");
+ clks[IMX8MN_CLK_EXT1] = of_clk_get_by_name(ccm_np, "clk_ext1");
+ clks[IMX8MN_CLK_EXT2] = of_clk_get_by_name(ccm_np, "clk_ext2");
+ clks[IMX8MN_CLK_EXT3] = of_clk_get_by_name(ccm_np, "clk_ext3");
+ clks[IMX8MN_CLK_EXT4] = of_clk_get_by_name(ccm_np, "clk_ext4");
+
+ clks[IMX8MN_AUDIO_PLL1_REF_SEL] = imx_clk_mux("audio_pll1_ref_sel", ana + 0x0, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ clks[IMX8MN_AUDIO_PLL2_REF_SEL] = imx_clk_mux("audio_pll2_ref_sel", ana + 0x14, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ clks[IMX8MN_VIDEO_PLL1_REF_SEL] = imx_clk_mux("video_pll1_ref_sel", ana + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ clks[IMX8MN_DRAM_PLL_REF_SEL] = imx_clk_mux("dram_pll_ref_sel", ana + 0x50, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ clks[IMX8MN_GPU_PLL_REF_SEL] = imx_clk_mux("gpu_pll_ref_sel", ana + 0x64, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ clks[IMX8MN_VPU_PLL_REF_SEL] = imx_clk_mux("vpu_pll_ref_sel", ana + 0x74, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ clks[IMX8MN_ARM_PLL_REF_SEL] = imx_clk_mux("arm_pll_ref_sel", ana + 0x84, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ clks[IMX8MN_SYS_PLL3_REF_SEL] = imx_clk_mux("sys_pll3_ref_sel", ana + 0x114, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+
+ clks[IMX8MN_AUDIO_PLL1] = imx_clk_pll14xx("audio_pll1", "audio_pll1_ref_sel", ana, &imx_1443x_pll);
+ clks[IMX8MN_AUDIO_PLL2] = imx_clk_pll14xx("audio_pll2", "audio_pll2_ref_sel", ana + 0x14, &imx_1443x_pll);
+ clks[IMX8MN_VIDEO_PLL1] = imx_clk_pll14xx("video_pll1", "video_pll1_ref_sel", ana + 0x28, &imx_1443x_pll);
+ clks[IMX8MN_DRAM_PLL] = imx_clk_pll14xx("dram_pll", "dram_pll_ref_sel", ana + 0x50, &imx_1443x_pll);
+ clks[IMX8MN_GPU_PLL] = imx_clk_pll14xx("gpu_pll", "gpu_pll_ref_sel", ana + 0x64, &imx_1416x_pll);
+ clks[IMX8MN_VPU_PLL] = imx_clk_pll14xx("vpu_pll", "vpu_pll_ref_sel", ana + 0x74, &imx_1416x_pll);
+ clks[IMX8MN_ARM_PLL] = imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel", ana + 0x84, &imx_1416x_pll);
+ clks[IMX8MN_SYS_PLL1] = clk_fixed("sys_pll1", 800000000);
+ clks[IMX8MN_SYS_PLL2] = clk_fixed("sys_pll2", 1000000000);
+ clks[IMX8MN_SYS_PLL3] = imx_clk_pll14xx("sys_pll3", "sys_pll3_ref_sel", ana + 0x114, &imx_1416x_pll);
+
+ /* PLL bypass out */
+ clks[IMX8MN_AUDIO_PLL1_BYPASS] = imx_clk_mux_flags("audio_pll1_bypass", ana, 16, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX8MN_AUDIO_PLL2_BYPASS] = imx_clk_mux_flags("audio_pll2_bypass", ana + 0x14, 16, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX8MN_VIDEO_PLL1_BYPASS] = imx_clk_mux_flags("video_pll1_bypass", ana + 0x28, 16, 1, video_pll1_bypass_sels, ARRAY_SIZE(video_pll1_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX8MN_DRAM_PLL_BYPASS] = imx_clk_mux_flags("dram_pll_bypass", ana + 0x50, 16, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX8MN_GPU_PLL_BYPASS] = imx_clk_mux_flags("gpu_pll_bypass", ana + 0x64, 28, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX8MN_VPU_PLL_BYPASS] = imx_clk_mux_flags("vpu_pll_bypass", ana + 0x74, 28, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX8MN_ARM_PLL_BYPASS] = imx_clk_mux_flags("arm_pll_bypass", ana + 0x84, 28, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT);
+ clks[IMX8MN_SYS_PLL3_BYPASS] = imx_clk_mux_flags("sys_pll3_bypass", ana + 0x114, 28, 1, sys_pll3_bypass_sels, ARRAY_SIZE(sys_pll3_bypass_sels), CLK_SET_RATE_PARENT);
+
+ /* PLL out gate */
+ clks[IMX8MN_AUDIO_PLL1_OUT] = imx_clk_gate("audio_pll1_out", "audio_pll1_bypass", ana, 13);
+ clks[IMX8MN_AUDIO_PLL2_OUT] = imx_clk_gate("audio_pll2_out", "audio_pll2_bypass", ana + 0x14, 13);
+ clks[IMX8MN_VIDEO_PLL1_OUT] = imx_clk_gate("video_pll1_out", "video_pll1_bypass", ana + 0x28, 13);
+ clks[IMX8MN_DRAM_PLL_OUT] = imx_clk_gate("dram_pll_out", "dram_pll_bypass", ana + 0x50, 13);
+ clks[IMX8MN_GPU_PLL_OUT] = imx_clk_gate("gpu_pll_out", "gpu_pll_bypass", ana + 0x64, 11);
+ clks[IMX8MN_VPU_PLL_OUT] = imx_clk_gate("vpu_pll_out", "vpu_pll_bypass", ana + 0x74, 11);
+ clks[IMX8MN_ARM_PLL_OUT] = imx_clk_gate("arm_pll_out", "arm_pll_bypass", ana + 0x84, 11);
+ clks[IMX8MN_SYS_PLL3_OUT] = imx_clk_gate("sys_pll3_out", "sys_pll3_bypass", ana + 0x114, 11);
+
+ /* SYS PLL1 fixed output */
+ /*
+ * The gates in CCM_ANALOG_SYS_PLL1_GEN_CTRL are not handled by the
+ * driver, make sure they are all enabled.
+ */
+ val = readl(ana + 0x94);
+ val |= BIT(13) | BIT(15) | BIT(17) | BIT(19) | BIT(21) | BIT(23) | BIT(25) | BIT(27);
+ writel(val, ana + 0x94);
+
+ clks[IMX8MN_SYS_PLL1_OUT] = imx_clk_gate("sys_pll1_out", "sys_pll1", ana + 0x94, 11);
+
+ clks[IMX8MN_SYS_PLL1_40M] = imx_clk_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20);
+ clks[IMX8MN_SYS_PLL1_80M] = imx_clk_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10);
+ clks[IMX8MN_SYS_PLL1_100M] = imx_clk_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8);
+ clks[IMX8MN_SYS_PLL1_133M] = imx_clk_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6);
+ clks[IMX8MN_SYS_PLL1_160M] = imx_clk_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5);
+ clks[IMX8MN_SYS_PLL1_200M] = imx_clk_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4);
+ clks[IMX8MN_SYS_PLL1_266M] = imx_clk_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3);
+ clks[IMX8MN_SYS_PLL1_400M] = imx_clk_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2);
+ clks[IMX8MN_SYS_PLL1_800M] = imx_clk_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1);
+
+ /* SYS PLL2 fixed output */
+ /*
+ * The gates in CCM_ANALOG_SYS_PLL2_GEN_CTRL are not handled by the
+ * driver, make sure they are all enabled.
+ */
+ val = readl(ana + 0x104);
+ val |= BIT(13) | BIT(15) | BIT(17) | BIT(19) | BIT(21) | BIT(23) | BIT(25) | BIT(27);
+ writel(val, ana + 0x104);
+
+ clks[IMX8MN_SYS_PLL2_OUT] = imx_clk_gate("sys_pll2_out", "sys_pll2", ana + 0x104, 11);
+
+ clks[IMX8MN_SYS_PLL2_50M] = imx_clk_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20);
+ clks[IMX8MN_SYS_PLL2_100M] = imx_clk_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10);
+ clks[IMX8MN_SYS_PLL2_125M] = imx_clk_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8);
+ clks[IMX8MN_SYS_PLL2_166M] = imx_clk_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6);
+ clks[IMX8MN_SYS_PLL2_200M] = imx_clk_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5);
+ clks[IMX8MN_SYS_PLL2_250M] = imx_clk_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4);
+ clks[IMX8MN_SYS_PLL2_333M] = imx_clk_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3);
+ clks[IMX8MN_SYS_PLL2_500M] = imx_clk_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2);
+ clks[IMX8MN_SYS_PLL2_1000M] = imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
+
+ clks[IMX8MN_CLK_CLKOUT1_SEL] = imx_clk_mux("clkout1_sel", ana + 0x128, 4, 4, clkout_sels, ARRAY_SIZE(clkout_sels));
+ clks[IMX8MN_CLK_CLKOUT1_DIV] = imx_clk_divider("clkout1_div", "clkout1_sel", ana + 0x128, 0, 4);
+ clks[IMX8MN_CLK_CLKOUT1] = imx_clk_gate("clkout1", "clkout1_div", ana + 0x128, 8);
+ clks[IMX8MN_CLK_CLKOUT2_SEL] = imx_clk_mux("clkout2_sel", ana + 0x128, 20, 4, clkout_sels, ARRAY_SIZE(clkout_sels));
+ clks[IMX8MN_CLK_CLKOUT2_DIV] = imx_clk_divider("clkout2_div", "clkout2_sel", ana + 0x128, 16, 4);
+ clks[IMX8MN_CLK_CLKOUT2] = imx_clk_gate("clkout2", "clkout2_div", ana + 0x128, 24);
+
+ /* CORE */
+ clks[IMX8MN_CLK_A53_SRC] = imx_clk_mux2("arm_a53_src", ccm + 0x8000, 24, 3, imx8mn_a53_sels, ARRAY_SIZE(imx8mn_a53_sels));
+ clks[IMX8MN_CLK_GPU_CORE_SRC] = imx_clk_mux2("gpu_core_src", ccm + 0x8180, 24, 3, imx8mn_gpu_core_sels, ARRAY_SIZE(imx8mn_gpu_core_sels));
+ clks[IMX8MN_CLK_GPU_SHADER_SRC] = imx_clk_mux2("gpu_shader_src", ccm + 0x8200, 24, 3, imx8mn_gpu_shader_sels, ARRAY_SIZE(imx8mn_gpu_shader_sels));
+ clks[IMX8MN_CLK_A53_CG] = imx_clk_gate3("arm_a53_cg", "arm_a53_src", ccm + 0x8000, 28);
+ clks[IMX8MN_CLK_GPU_CORE_CG] = imx_clk_gate3("gpu_core_cg", "gpu_core_src", ccm + 0x8180, 28);
+ clks[IMX8MN_CLK_GPU_SHADER_CG] = imx_clk_gate3("gpu_shader_cg", "gpu_shader_src", ccm + 0x8200, 28);
+
+ clks[IMX8MN_CLK_A53_DIV] = imx_clk_divider2("arm_a53_div", "arm_a53_cg", ccm + 0x8000, 0, 3);
+ clks[IMX8MN_CLK_GPU_CORE_DIV] = imx_clk_divider2("gpu_core_div", "gpu_core_cg", ccm + 0x8180, 0, 3);
+ clks[IMX8MN_CLK_GPU_SHADER_DIV] = imx_clk_divider2("gpu_shader_div", "gpu_shader_cg", ccm + 0x8200, 0, 3);
+
+ /* CORE SEL */
+ clks[IMX8MN_CLK_A53_CORE] = imx_clk_mux2("arm_a53_core", ccm + 0x9880, 24, 1, imx8mn_a53_core_sels, ARRAY_SIZE(imx8mn_a53_core_sels));
+
+ /* BUS */
+ clks[IMX8MN_CLK_MAIN_AXI] = imx8m_clk_composite_critical("main_axi", imx8mn_main_axi_sels, ccm + 0x8800);
+ clks[IMX8MN_CLK_ENET_AXI] = imx8m_clk_composite("enet_axi", imx8mn_enet_axi_sels, ccm + 0x8880);
+ clks[IMX8MN_CLK_NAND_USDHC_BUS] = imx8m_clk_composite("nand_usdhc_bus", imx8mn_nand_usdhc_sels, ccm + 0x8900);
+ clks[IMX8MN_CLK_DISP_AXI] = imx8m_clk_composite("disp_axi", imx8mn_disp_axi_sels, ccm + 0x8a00);
+ clks[IMX8MN_CLK_DISP_APB] = imx8m_clk_composite("disp_apb", imx8mn_disp_apb_sels, ccm + 0x8a80);
+ clks[IMX8MN_CLK_USB_BUS] = imx8m_clk_composite("usb_bus", imx8mn_usb_bus_sels, ccm + 0x8b80);
+ clks[IMX8MN_CLK_GPU_AXI] = imx8m_clk_composite("gpu_axi", imx8mn_gpu_axi_sels, ccm + 0x8c00);
+ clks[IMX8MN_CLK_GPU_AHB] = imx8m_clk_composite("gpu_ahb", imx8mn_gpu_ahb_sels, ccm + 0x8c80);
+ clks[IMX8MN_CLK_NOC] = imx8m_clk_composite_critical("noc", imx8mn_noc_sels, ccm + 0x8d00);
+
+ clks[IMX8MN_CLK_AHB] = imx8m_clk_composite_critical("ahb", imx8mn_ahb_sels, ccm + 0x9000);
+ clks[IMX8MN_CLK_AUDIO_AHB] = imx8m_clk_composite("audio_ahb", imx8mn_audio_ahb_sels, ccm + 0x9100);
+ clks[IMX8MN_CLK_IPG_ROOT] = imx_clk_divider2("ipg_root", "ahb", ccm + 0x9080, 0, 1);
+ clks[IMX8MN_CLK_IPG_AUDIO_ROOT] = imx_clk_divider2("ipg_audio_root", "audio_ahb", ccm + 0x9180, 0, 1);
+ clks[IMX8MN_CLK_DRAM_CORE] = imx_clk_mux2_flags("dram_core_clk", ccm + 0x9800, 24, 1, imx8mn_dram_core_sels, ARRAY_SIZE(imx8mn_dram_core_sels), CLK_IS_CRITICAL);
+
+ /*
+ * DRAM clocks are manipulated from TF-A outside clock framework.
+ * Mark with GET_RATE_NOCACHE to always read div value from hardware
+ */
+ clks[IMX8MN_CLK_DRAM_ALT] = __imx8m_clk_composite("dram_alt", imx8mn_dram_alt_sels, ccm + 0xa000, CLK_GET_RATE_NOCACHE);
+ clks[IMX8MN_CLK_DRAM_APB] = __imx8m_clk_composite("dram_apb", imx8mn_dram_apb_sels, ccm + 0xa080, CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE);
+
+ clks[IMX8MN_CLK_DISP_PIXEL] = imx8m_clk_composite("disp_pixel", imx8mn_disp_pixel_sels, ccm + 0xa500);
+ clks[IMX8MN_CLK_SAI2] = imx8m_clk_composite("sai2", imx8mn_sai2_sels, ccm + 0xa600);
+ clks[IMX8MN_CLK_SAI3] = imx8m_clk_composite("sai3", imx8mn_sai3_sels, ccm + 0xa680);
+ clks[IMX8MN_CLK_SAI5] = imx8m_clk_composite("sai5", imx8mn_sai5_sels, ccm + 0xa780);
+ clks[IMX8MN_CLK_SAI6] = imx8m_clk_composite("sai6", imx8mn_sai6_sels, ccm + 0xa800);
+ clks[IMX8MN_CLK_SPDIF1] = imx8m_clk_composite("spdif1", imx8mn_spdif1_sels, ccm + 0xa880);
+ clks[IMX8MN_CLK_ENET_REF] = imx8m_clk_composite("enet_ref", imx8mn_enet_ref_sels, ccm + 0xa980);
+ clks[IMX8MN_CLK_ENET_TIMER] = imx8m_clk_composite("enet_timer", imx8mn_enet_timer_sels, ccm + 0xaa00);
+ clks[IMX8MN_CLK_ENET_PHY_REF] = imx8m_clk_composite("enet_phy", imx8mn_enet_phy_sels, ccm + 0xaa80);
+ clks[IMX8MN_CLK_NAND] = imx8m_clk_composite("nand", imx8mn_nand_sels, ccm + 0xab00);
+ clks[IMX8MN_CLK_QSPI] = imx8m_clk_composite("qspi", imx8mn_qspi_sels, ccm + 0xab80);
+ clks[IMX8MN_CLK_USDHC1] = imx8m_clk_composite("usdhc1", imx8mn_usdhc1_sels, ccm + 0xac00);
+ clks[IMX8MN_CLK_USDHC2] = imx8m_clk_composite("usdhc2", imx8mn_usdhc2_sels, ccm + 0xac80);
+ clks[IMX8MN_CLK_I2C1] = imx8m_clk_composite("i2c1", imx8mn_i2c1_sels, ccm + 0xad00);
+ clks[IMX8MN_CLK_I2C2] = imx8m_clk_composite("i2c2", imx8mn_i2c2_sels, ccm + 0xad80);
+ clks[IMX8MN_CLK_I2C3] = imx8m_clk_composite("i2c3", imx8mn_i2c3_sels, ccm + 0xae00);
+ clks[IMX8MN_CLK_I2C4] = imx8m_clk_composite("i2c4", imx8mn_i2c4_sels, ccm + 0xae80);
+ clks[IMX8MN_CLK_UART1] = imx8m_clk_composite("uart1", imx8mn_uart1_sels, ccm + 0xaf00);
+ clks[IMX8MN_CLK_UART2] = imx8m_clk_composite("uart2", imx8mn_uart2_sels, ccm + 0xaf80);
+ clks[IMX8MN_CLK_UART3] = imx8m_clk_composite("uart3", imx8mn_uart3_sels, ccm + 0xb000);
+ clks[IMX8MN_CLK_UART4] = imx8m_clk_composite("uart4", imx8mn_uart4_sels, ccm + 0xb080);
+ clks[IMX8MN_CLK_USB_CORE_REF] = imx8m_clk_composite("usb_core_ref", imx8mn_usb_core_sels, ccm + 0xb100);
+ clks[IMX8MN_CLK_USB_PHY_REF] = imx8m_clk_composite("usb_phy_ref", imx8mn_usb_phy_sels, ccm + 0xb180);
+ clks[IMX8MN_CLK_GIC] = imx8m_clk_composite_critical("gic", imx8mn_gic_sels, ccm + 0xb200);
+ clks[IMX8MN_CLK_ECSPI1] = imx8m_clk_composite("ecspi1", imx8mn_ecspi1_sels, ccm + 0xb280);
+ clks[IMX8MN_CLK_ECSPI2] = imx8m_clk_composite("ecspi2", imx8mn_ecspi2_sels, ccm + 0xb300);
+ clks[IMX8MN_CLK_PWM1] = imx8m_clk_composite("pwm1", imx8mn_pwm1_sels, ccm + 0xb380);
+ clks[IMX8MN_CLK_PWM2] = imx8m_clk_composite("pwm2", imx8mn_pwm2_sels, ccm + 0xb400);
+ clks[IMX8MN_CLK_PWM3] = imx8m_clk_composite("pwm3", imx8mn_pwm3_sels, ccm + 0xb480);
+ clks[IMX8MN_CLK_PWM4] = imx8m_clk_composite("pwm4", imx8mn_pwm4_sels, ccm + 0xb500);
+ clks[IMX8MN_CLK_WDOG] = imx8m_clk_composite("wdog", imx8mn_wdog_sels, ccm + 0xb900);
+ clks[IMX8MN_CLK_WRCLK] = imx8m_clk_composite("wrclk", imx8mn_wrclk_sels, ccm + 0xb980);
+ clks[IMX8MN_CLK_CLKO1] = imx8m_clk_composite("clko1", imx8mn_clko1_sels, ccm + 0xba00);
+ clks[IMX8MN_CLK_CLKO2] = imx8m_clk_composite("clko2", imx8mn_clko2_sels, ccm + 0xba80);
+ clks[IMX8MN_CLK_DSI_CORE] = imx8m_clk_composite("dsi_core", imx8mn_dsi_core_sels, ccm + 0xbb00);
+ clks[IMX8MN_CLK_DSI_PHY_REF] = imx8m_clk_composite("dsi_phy_ref", imx8mn_dsi_phy_sels, ccm + 0xbb80);
+ clks[IMX8MN_CLK_DSI_DBI] = imx8m_clk_composite("dsi_dbi", imx8mn_dsi_dbi_sels, ccm + 0xbc00);
+ clks[IMX8MN_CLK_USDHC3] = imx8m_clk_composite("usdhc3", imx8mn_usdhc3_sels, ccm + 0xbc80);
+ clks[IMX8MN_CLK_CAMERA_PIXEL] = imx8m_clk_composite("camera_pixel", imx8mn_camera_pixel_sels, ccm + 0xbd00);
+ clks[IMX8MN_CLK_CSI1_PHY_REF] = imx8m_clk_composite("csi1_phy_ref", imx8mn_csi1_phy_sels, ccm + 0xbd80);
+ clks[IMX8MN_CLK_CSI2_PHY_REF] = imx8m_clk_composite("csi2_phy_ref", imx8mn_csi2_phy_sels, ccm + 0xbf00);
+ clks[IMX8MN_CLK_CSI2_ESC] = imx8m_clk_composite("csi2_esc", imx8mn_csi2_esc_sels, ccm + 0xbf80);
+ clks[IMX8MN_CLK_ECSPI3] = imx8m_clk_composite("ecspi3", imx8mn_ecspi3_sels, ccm + 0xc180);
+ clks[IMX8MN_CLK_PDM] = imx8m_clk_composite("pdm", imx8mn_pdm_sels, ccm + 0xc200);
+ clks[IMX8MN_CLK_SAI7] = imx8m_clk_composite("sai7", imx8mn_sai7_sels, ccm + 0xc300);
+
+ clks[IMX8MN_CLK_ECSPI1_ROOT] = imx_clk_gate4("ecspi1_root_clk", "ecspi1", ccm + 0x4070, 0);
+ clks[IMX8MN_CLK_ECSPI2_ROOT] = imx_clk_gate4("ecspi2_root_clk", "ecspi2", ccm + 0x4080, 0);
+ clks[IMX8MN_CLK_ECSPI3_ROOT] = imx_clk_gate4("ecspi3_root_clk", "ecspi3", ccm + 0x4090, 0);
+ clks[IMX8MN_CLK_ENET1_ROOT] = imx_clk_gate4("enet1_root_clk", "enet_axi", ccm + 0x40a0, 0);
+ clks[IMX8MN_CLK_GPIO1_ROOT] = imx_clk_gate4("gpio1_root_clk", "ipg_root", ccm + 0x40b0, 0);
+ clks[IMX8MN_CLK_GPIO2_ROOT] = imx_clk_gate4("gpio2_root_clk", "ipg_root", ccm + 0x40c0, 0);
+ clks[IMX8MN_CLK_GPIO3_ROOT] = imx_clk_gate4("gpio3_root_clk", "ipg_root", ccm + 0x40d0, 0);
+ clks[IMX8MN_CLK_GPIO4_ROOT] = imx_clk_gate4("gpio4_root_clk", "ipg_root", ccm + 0x40e0, 0);
+ clks[IMX8MN_CLK_GPIO5_ROOT] = imx_clk_gate4("gpio5_root_clk", "ipg_root", ccm + 0x40f0, 0);
+ clks[IMX8MN_CLK_I2C1_ROOT] = imx_clk_gate4("i2c1_root_clk", "i2c1", ccm + 0x4170, 0);
+ clks[IMX8MN_CLK_I2C2_ROOT] = imx_clk_gate4("i2c2_root_clk", "i2c2", ccm + 0x4180, 0);
+ clks[IMX8MN_CLK_I2C3_ROOT] = imx_clk_gate4("i2c3_root_clk", "i2c3", ccm + 0x4190, 0);
+ clks[IMX8MN_CLK_I2C4_ROOT] = imx_clk_gate4("i2c4_root_clk", "i2c4", ccm + 0x41a0, 0);
+ clks[IMX8MN_CLK_MU_ROOT] = imx_clk_gate4("mu_root_clk", "ipg_root", ccm + 0x4210, 0);
+ clks[IMX8MN_CLK_OCOTP_ROOT] = imx_clk_gate4("ocotp_root_clk", "ipg_root", ccm + 0x4220, 0);
+ clks[IMX8MN_CLK_PWM1_ROOT] = imx_clk_gate4("pwm1_root_clk", "pwm1", ccm + 0x4280, 0);
+ clks[IMX8MN_CLK_PWM2_ROOT] = imx_clk_gate4("pwm2_root_clk", "pwm2", ccm + 0x4290, 0);
+ clks[IMX8MN_CLK_PWM3_ROOT] = imx_clk_gate4("pwm3_root_clk", "pwm3", ccm + 0x42a0, 0);
+ clks[IMX8MN_CLK_PWM4_ROOT] = imx_clk_gate4("pwm4_root_clk", "pwm4", ccm + 0x42b0, 0);
+ clks[IMX8MN_CLK_QSPI_ROOT] = imx_clk_gate4("qspi_root_clk", "qspi", ccm + 0x42f0, 0);
+ clks[IMX8MN_CLK_NAND_ROOT] = imx_clk_gate2_shared2("nand_root_clk", "nand", ccm + 0x4300, 0);
+ clks[IMX8MN_CLK_NAND_USDHC_BUS_RAWNAND_CLK] = imx_clk_gate2_shared2("nand_usdhc_rawnand_clk", "nand_usdhc_bus", ccm + 0x4300, 0);
+ clks[IMX8MN_CLK_SAI2_ROOT] = imx_clk_gate2_shared2("sai2_root_clk", "sai2", ccm + 0x4340, 0);
+ clks[IMX8MN_CLK_SAI2_IPG] = imx_clk_gate2_shared2("sai2_ipg_clk", "ipg_audio_root", ccm + 0x4340, 0);
+ clks[IMX8MN_CLK_SAI3_ROOT] = imx_clk_gate2_shared2("sai3_root_clk", "sai3", ccm + 0x4350, 0);
+ clks[IMX8MN_CLK_SAI3_IPG] = imx_clk_gate2_shared2("sai3_ipg_clk", "ipg_audio_root", ccm + 0x4350, 0);
+ clks[IMX8MN_CLK_SAI5_ROOT] = imx_clk_gate2_shared2("sai5_root_clk", "sai5", ccm + 0x4370, 0);
+ clks[IMX8MN_CLK_SAI5_IPG] = imx_clk_gate2_shared2("sai5_ipg_clk", "ipg_audio_root", ccm + 0x4370, 0);
+ clks[IMX8MN_CLK_SAI6_ROOT] = imx_clk_gate2_shared2("sai6_root_clk", "sai6", ccm + 0x4380, 0);
+ clks[IMX8MN_CLK_SAI6_IPG] = imx_clk_gate2_shared2("sai6_ipg_clk", "ipg_audio_root", ccm + 0x4380, 0);
+ clks[IMX8MN_CLK_SNVS_ROOT] = imx_clk_gate4("snvs_root_clk", "ipg_root", ccm + 0x4470, 0);
+ clks[IMX8MN_CLK_UART1_ROOT] = imx_clk_gate4("uart1_root_clk", "uart1", ccm + 0x4490, 0);
+ clks[IMX8MN_CLK_UART2_ROOT] = imx_clk_gate4("uart2_root_clk", "uart2", ccm + 0x44a0, 0);
+ clks[IMX8MN_CLK_UART3_ROOT] = imx_clk_gate4("uart3_root_clk", "uart3", ccm + 0x44b0, 0);
+ clks[IMX8MN_CLK_UART4_ROOT] = imx_clk_gate4("uart4_root_clk", "uart4", ccm + 0x44c0, 0);
+ clks[IMX8MN_CLK_USB1_CTRL_ROOT] = imx_clk_gate4("usb1_ctrl_root_clk", "usb_bus", ccm + 0x44d0, 0);
+ clks[IMX8MN_CLK_GPU_CORE_ROOT] = imx_clk_gate4("gpu_core_root_clk", "gpu_core_div", ccm + 0x44f0, 0);
+ clks[IMX8MN_CLK_USDHC1_ROOT] = imx_clk_gate4("usdhc1_root_clk", "usdhc1", ccm + 0x4510, 0);
+ clks[IMX8MN_CLK_USDHC2_ROOT] = imx_clk_gate4("usdhc2_root_clk", "usdhc2", ccm + 0x4520, 0);
+ clks[IMX8MN_CLK_WDOG1_ROOT] = imx_clk_gate4("wdog1_root_clk", "wdog", ccm + 0x4530, 0);
+ clks[IMX8MN_CLK_WDOG2_ROOT] = imx_clk_gate4("wdog2_root_clk", "wdog", ccm + 0x4540, 0);
+ clks[IMX8MN_CLK_WDOG3_ROOT] = imx_clk_gate4("wdog3_root_clk", "wdog", ccm + 0x4550, 0);
+ clks[IMX8MN_CLK_GPU_BUS_ROOT] = imx_clk_gate4("gpu_root_clk", "gpu_axi", ccm + 0x4570, 0);
+ clks[IMX8MN_CLK_ASRC_ROOT] = imx_clk_gate4("asrc_root_clk", "audio_ahb", ccm + 0x4580, 0);
+ clks[IMX8MN_CLK_PDM_ROOT] = imx_clk_gate2_shared2("pdm_root_clk", "pdm", ccm + 0x45b0, 0);
+ clks[IMX8MN_CLK_PDM_IPG] = imx_clk_gate2_shared2("pdm_ipg_clk", "ipg_audio_root", ccm + 0x45b0, 0);
+ clks[IMX8MN_CLK_DISP_AXI_ROOT] = imx_clk_gate2_shared2("disp_axi_root_clk", "disp_axi", ccm + 0x45d0, 0);
+ clks[IMX8MN_CLK_DISP_APB_ROOT] = imx_clk_gate2_shared2("disp_apb_root_clk", "disp_apb", ccm + 0x45d0, 0);
+ clks[IMX8MN_CLK_CAMERA_PIXEL_ROOT] = imx_clk_gate2_shared2("camera_pixel_clk", "camera_pixel", ccm + 0x45d0, 0);
+ clks[IMX8MN_CLK_DISP_PIXEL_ROOT] = imx_clk_gate2_shared2("disp_pixel_clk", "disp_pixel", ccm + 0x45d0, 0);
+ clks[IMX8MN_CLK_USDHC3_ROOT] = imx_clk_gate4("usdhc3_root_clk", "usdhc3", ccm + 0x45e0, 0);
+ clks[IMX8MN_CLK_TMU_ROOT] = imx_clk_gate4("tmu_root_clk", "ipg_root", ccm + 0x4620, 0);
+ clks[IMX8MN_CLK_SDMA1_ROOT] = imx_clk_gate4("sdma1_clk", "ipg_root", ccm + 0x43a0, 0);
+ clks[IMX8MN_CLK_SDMA2_ROOT] = imx_clk_gate4("sdma2_clk", "ipg_audio_root", ccm + 0x43b0, 0);
+ clks[IMX8MN_CLK_SDMA3_ROOT] = imx_clk_gate4("sdma3_clk", "ipg_audio_root", ccm + 0x45f0, 0);
+ clks[IMX8MN_CLK_SAI7_ROOT] = imx_clk_gate2_shared2("sai7_root_clk", "sai7", ccm + 0x4650, 0);
+
+ clks[IMX8MN_CLK_DRAM_ALT_ROOT] = imx_clk_fixed_factor("dram_alt_root", "dram_alt", 1, 4);
+
+ clks[IMX8MN_CLK_ARM] = imx_clk_cpu("arm", "arm_a53_core",
+ clks[IMX8MN_CLK_A53_CORE],
+ clks[IMX8MN_CLK_A53_CORE],
+ clks[IMX8MN_ARM_PLL_OUT],
+ clks[IMX8MN_CLK_A53_DIV]);
+
+ imx_check_clocks(clks, ARRAY_SIZE(clks));
+
+ clk_enable(clks[IMX8MN_SYS_PLL3_OUT]);
+ clk_data.clks = clks;
+ clk_data.clk_num = ARRAY_SIZE(clks);
+
+ ret = of_clk_add_provider(ccm_np, of_clk_src_onecell_get, &clk_data);
+ if (ret < 0)
+ pr_err("failed to register clks for i.MX8MN\n");
+
+ return ret;
+}
+CLK_OF_DECLARE(imx8mn, "fsl,imx8mn-ccm", imx8mn_clocks_init);
+
+MODULE_AUTHOR("Anson Huang <Anson.Huang@nxp.com>");
+MODULE_DESCRIPTION("NXP i.MX8MN clock driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
new file mode 100644
index 0000000000..e08cebc19c
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8mp.c
@@ -0,0 +1,708 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2019 NXP.
+ */
+
+#include <dt-bindings/clock/imx8mp-clock.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <of_address.h>
+
+#include "clk.h"
+
+static const char * const pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
+static const char * const audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
+static const char * const audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", };
+static const char * const video_pll1_bypass_sels[] = {"video_pll1", "video_pll1_ref_sel", };
+static const char * const dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
+static const char * const gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
+static const char * const vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
+static const char * const arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
+static const char * const sys_pll1_bypass_sels[] = {"sys_pll1", "sys_pll1_ref_sel", };
+static const char * const sys_pll2_bypass_sels[] = {"sys_pll2", "sys_pll2_ref_sel", };
+static const char * const sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
+
+static const char * const imx8mp_a53_sels[] = {"osc_24m", "arm_pll_out", "sys_pll2_500m",
+ "sys_pll2_1000m", "sys_pll1_800m", "sys_pll1_400m",
+ "audio_pll1_out", "sys_pll3_out", };
+
+static const char * const imx8mp_a53_core_sels[] = {"arm_a53_div", "arm_pll_out", };
+
+static const char * const imx8mp_m7_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_250m",
+ "vpu_pll_out", "sys_pll1_800m", "audio_pll1_out",
+ "video_pll1_out", "sys_pll3_out", };
+
+static const char * const imx8mp_ml_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m",
+ "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mp_gpu3d_core_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m",
+ "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mp_gpu3d_shader_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m",
+ "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mp_gpu2d_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m",
+ "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mp_audio_axi_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m",
+ "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mp_hsio_axi_sels[] = {"osc_24m", "sys_pll2_500m", "sys_pll1_800m",
+ "sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
+ "clk_ext4", "audio_pll2_out", };
+
+static const char * const imx8mp_media_isp_sels[] = {"osc_24m", "sys_pll2_1000m", "sys_pll1_800m",
+ "sys_pll3_out", "sys_pll1_400m", "audio_pll2_out",
+ "clk_ext1", "sys_pll2_500m", };
+
+static const char * const imx8mp_main_axi_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll1_800m",
+ "sys_pll2_250m", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "sys_pll1_100m",};
+
+static const char * const imx8mp_enet_axi_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m",
+ "sys_pll2_250m", "sys_pll2_200m", "audio_pll1_out",
+ "video_pll1_out", "sys_pll3_out", };
+
+static const char * const imx8mp_nand_usdhc_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m",
+ "sys_pll2_200m", "sys_pll1_133m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll1_out", };
+
+static const char * const imx8mp_vpu_bus_sels[] = {"osc_24m", "sys_pll1_800m", "vpu_pll_out",
+ "audio_pll2_out", "sys_pll3_out", "sys_pll2_1000m",
+ "sys_pll2_200m", "sys_pll1_100m", };
+
+static const char * const imx8mp_media_axi_sels[] = {"osc_24m", "sys_pll2_1000m", "sys_pll1_800m",
+ "sys_pll3_out", "sys_pll1_40m", "audio_pll2_out",
+ "clk_ext1", "sys_pll2_500m", };
+
+static const char * const imx8mp_media_apb_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll1_800m",
+ "sys_pll3_out", "sys_pll1_40m", "audio_pll2_out",
+ "clk_ext1", "sys_pll1_133m", };
+
+static const char * const imx8mp_gpu_axi_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out",
+ "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mp_gpu_ahb_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out",
+ "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mp_noc_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_1000m", "sys_pll2_500m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mp_noc_io_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_1000m", "sys_pll2_500m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mp_ml_axi_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out",
+ "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mp_ml_ahb_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out",
+ "sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mp_ahb_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_800m",
+ "sys_pll1_400m", "sys_pll2_125m", "sys_pll3_out",
+ "audio_pll1_out", "video_pll1_out", };
+
+static const char * const imx8mp_audio_ahb_sels[] = {"osc_24m", "sys_pll2_500m", "sys_pll1_800m",
+ "sys_pll2_1000m", "sys_pll2_166m", "sys_pll3_out",
+ "audio_pll1_out", "video_pll1_out", };
+
+static const char * const imx8mp_mipi_dsi_esc_rx_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_80m",
+ "sys_pll1_800m", "sys_pll2_1000m",
+ "sys_pll3_out", "clk_ext3", "audio_pll2_out", };
+
+static const char * const imx8mp_dram_alt_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll1_100m",
+ "sys_pll2_500m", "sys_pll2_1000m", "sys_pll3_out",
+ "audio_pll1_out", "sys_pll1_266m", };
+
+static const char * const imx8mp_dram_apb_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m",
+ "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll2_out", };
+
+static const char * const imx8mp_vpu_g1_sels[] = {"osc_24m", "vpu_pll_out", "sys_pll1_800m",
+ "sys_pll2_1000m", "sys_pll1_100m", "sys_pll2_125m",
+ "sys_pll3_out", "audio_pll1_out", };
+
+static const char * const imx8mp_vpu_g2_sels[] = {"osc_24m", "vpu_pll_out", "sys_pll1_800m",
+ "sys_pll2_1000m", "sys_pll1_100m", "sys_pll2_125m",
+ "sys_pll3_out", "audio_pll1_out", };
+
+static const char * const imx8mp_can1_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m",
+ "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll2_out", };
+
+static const char * const imx8mp_can2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m",
+ "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll2_out", };
+
+static const char * const imx8mp_memrepair_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
+ "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "audio_pll2_out", "sys_pll1_133m", };
+
+static const char * const imx8mp_pcie_aux_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_50m",
+ "sys_pll3_out", "sys_pll2_100m", "sys_pll1_80m",
+ "sys_pll1_160m", "sys_pll1_200m", };
+
+static const char * const imx8mp_i2c5_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
+ "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "audio_pll2_out", "sys_pll1_133m", };
+
+static const char * const imx8mp_i2c6_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
+ "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "audio_pll2_out", "sys_pll1_133m", };
+
+static const char * const imx8mp_sai1_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
+ "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "clk_ext1", "clk_ext2", };
+
+static const char * const imx8mp_sai2_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
+ "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "clk_ext2", "clk_ext3", };
+
+static const char * const imx8mp_sai3_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
+ "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "clk_ext3", "clk_ext4", };
+
+static const char * const imx8mp_sai5_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
+ "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "clk_ext2", "clk_ext3", };
+
+static const char * const imx8mp_sai6_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
+ "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "clk_ext3", "clk_ext4", };
+
+static const char * const imx8mp_enet_qos_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_50m",
+ "sys_pll2_100m", "sys_pll1_160m", "audio_pll1_out",
+ "video_pll1_out", "clk_ext4", };
+
+static const char * const imx8mp_enet_qos_timer_sels[] = {"osc_24m", "sys_pll2_100m", "audio_pll1_out",
+ "clk_ext1", "clk_ext2", "clk_ext3",
+ "clk_ext4", "video_pll1_out", };
+
+static const char * const imx8mp_enet_ref_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_50m",
+ "sys_pll2_100m", "sys_pll1_160m", "audio_pll1_out",
+ "video_pll1_out", "clk_ext4", };
+
+static const char * const imx8mp_enet_timer_sels[] = {"osc_24m", "sys_pll2_100m", "audio_pll1_out",
+ "clk_ext1", "clk_ext2", "clk_ext3",
+ "clk_ext4", "video_pll1_out", };
+
+static const char * const imx8mp_enet_phy_ref_sels[] = {"osc_24m", "sys_pll2_50m", "sys_pll2_125m",
+ "sys_pll2_200m", "sys_pll2_500m", "audio_pll1_out",
+ "video_pll1_out", "audio_pll2_out", };
+
+static const char * const imx8mp_nand_sels[] = {"osc_24m", "sys_pll2_500m", "audio_pll1_out",
+ "sys_pll1_400m", "audio_pll2_out", "sys_pll3_out",
+ "sys_pll2_250m", "video_pll1_out", };
+
+static const char * const imx8mp_qspi_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll2_333m",
+ "sys_pll2_500m", "audio_pll2_out", "sys_pll1_266m",
+ "sys_pll3_out", "sys_pll1_100m", };
+
+static const char * const imx8mp_usdhc1_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m",
+ "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
+ "audio_pll2_out", "sys_pll1_100m", };
+
+static const char * const imx8mp_usdhc2_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m",
+ "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
+ "audio_pll2_out", "sys_pll1_100m", };
+
+static const char * const imx8mp_i2c1_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
+ "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "audio_pll2_out", "sys_pll1_133m", };
+
+static const char * const imx8mp_i2c2_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
+ "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "audio_pll2_out", "sys_pll1_133m", };
+
+static const char * const imx8mp_i2c3_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
+ "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "audio_pll2_out", "sys_pll1_133m", };
+
+static const char * const imx8mp_i2c4_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
+ "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "audio_pll2_out", "sys_pll1_133m", };
+
+static const char * const imx8mp_uart1_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m",
+ "sys_pll2_100m", "sys_pll3_out", "clk_ext2",
+ "clk_ext4", "audio_pll2_out", };
+
+static const char * const imx8mp_uart2_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m",
+ "sys_pll2_100m", "sys_pll3_out", "clk_ext2",
+ "clk_ext3", "audio_pll2_out", };
+
+static const char * const imx8mp_uart3_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m",
+ "sys_pll2_100m", "sys_pll3_out", "clk_ext2",
+ "clk_ext4", "audio_pll2_out", };
+
+static const char * const imx8mp_uart4_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m",
+ "sys_pll2_100m", "sys_pll3_out", "clk_ext2",
+ "clk_ext3", "audio_pll2_out", };
+
+static const char * const imx8mp_usb_core_ref_sels[] = {"osc_24m", "sys_pll1_100m", "sys_pll1_40m",
+ "sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
+ "clk_ext3", "audio_pll2_out", };
+
+static const char * const imx8mp_usb_phy_ref_sels[] = {"osc_24m", "sys_pll1_100m", "sys_pll1_40m",
+ "sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
+ "clk_ext3", "audio_pll2_out", };
+
+static const char * const imx8mp_gic_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m",
+ "sys_pll2_100m", "sys_pll1_800m",
+ "sys_pll2_500m", "clk_ext4", "audio_pll2_out" };
+
+static const char * const imx8mp_ecspi1_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m",
+ "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll2_out", };
+
+static const char * const imx8mp_ecspi2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m",
+ "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll2_out", };
+
+static const char * const imx8mp_pwm1_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
+ "sys_pll1_40m", "sys_pll3_out", "clk_ext1",
+ "sys_pll1_80m", "video_pll1_out", };
+
+static const char * const imx8mp_pwm2_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
+ "sys_pll1_40m", "sys_pll3_out", "clk_ext1",
+ "sys_pll1_80m", "video_pll1_out", };
+
+static const char * const imx8mp_pwm3_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
+ "sys_pll1_40m", "sys_pll3_out", "clk_ext2",
+ "sys_pll1_80m", "video_pll1_out", };
+
+static const char * const imx8mp_pwm4_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
+ "sys_pll1_40m", "sys_pll3_out", "clk_ext2",
+ "sys_pll1_80m", "video_pll1_out", };
+
+static const char * const imx8mp_gpt1_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m",
+ "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m",
+ "audio_pll1_out", "clk_ext1" };
+
+static const char * const imx8mp_gpt2_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m",
+ "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m",
+ "audio_pll1_out", "clk_ext2" };
+
+static const char * const imx8mp_gpt3_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m",
+ "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m",
+ "audio_pll1_out", "clk_ext3" };
+
+static const char * const imx8mp_gpt4_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m",
+ "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m",
+ "audio_pll1_out", "clk_ext1" };
+
+static const char * const imx8mp_gpt5_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m",
+ "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m",
+ "audio_pll1_out", "clk_ext2" };
+
+static const char * const imx8mp_gpt6_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m",
+ "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m",
+ "audio_pll1_out", "clk_ext3" };
+
+static const char * const imx8mp_wdog_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_160m",
+ "vpu_pll_out", "sys_pll2_125m", "sys_pll3_out",
+ "sys_pll1_80m", "sys_pll2_166m" };
+
+static const char * const imx8mp_wrclk_sels[] = {"osc_24m", "sys_pll1_40m", "vpu_pll_out",
+ "sys_pll3_out", "sys_pll2_200m", "sys_pll1_266m",
+ "sys_pll2_500m", "sys_pll1_100m" };
+
+static const char * const imx8mp_ipp_do_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll1_133m",
+ "sys_pll1_200m", "audio_pll2_out", "sys_pll2_500m",
+ "vpu_pll_out", "sys_pll1_80m" };
+
+static const char * const imx8mp_ipp_do_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_400m",
+ "sys_pll1_166m", "sys_pll3_out", "audio_pll1_out",
+ "video_pll1_out", "osc_32k" };
+
+static const char * const imx8mp_hdmi_fdcc_tst_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m",
+ "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
+ "audio_pll2_out", "video_pll1_out", };
+
+static const char * const imx8mp_hdmi_24m_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
+ "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "audio_pll2_out", "sys_pll1_133m", };
+
+static const char * const imx8mp_hdmi_ref_266m_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll3_out",
+ "sys_pll2_333m", "sys_pll1_266m", "sys_pll2_200m",
+ "audio_pll1_out", "video_pll1_out", };
+
+static const char * const imx8mp_usdhc3_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m",
+ "sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
+ "audio_pll2_out", "sys_pll1_100m", };
+
+static const char * const imx8mp_media_cam1_pix_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m",
+ "sys_pll1_800m", "sys_pll2_1000m",
+ "sys_pll3_out", "audio_pll2_out",
+ "video_pll1_out", };
+
+static const char * const imx8mp_media_mipi_phy1_ref_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m",
+ "sys_pll1_800m", "sys_pll2_1000m",
+ "clk_ext2", "audio_pll2_out",
+ "video_pll1_out", };
+
+static const char * const imx8mp_media_disp1_pix_sels[] = {"osc_24m", "video_pll1_out", "audio_pll2_out",
+ "audio_pll1_out", "sys_pll1_800m",
+ "sys_pll2_1000m", "sys_pll3_out", "clk_ext4", };
+
+static const char * const imx8mp_media_cam2_pix_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m",
+ "sys_pll1_800m", "sys_pll2_1000m",
+ "sys_pll3_out", "audio_pll2_out",
+ "video_pll1_out", };
+
+static const char * const imx8mp_media_ldb_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m",
+ "sys_pll1_800m", "sys_pll2_1000m",
+ "clk_ext2", "audio_pll2_out",
+ "video_pll1_out", };
+
+static const char * const imx8mp_media_mipi_csi2_esc_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_80m",
+ "sys_pll1_800m", "sys_pll2_1000m",
+ "sys_pll3_out", "clk_ext3",
+ "audio_pll2_out", };
+
+static const char * const imx8mp_media_mipi_test_byte_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_50m",
+ "sys_pll3_out", "sys_pll2_100m",
+ "sys_pll1_80m", "sys_pll1_160m",
+ "sys_pll1_200m", };
+
+static const char * const imx8mp_ecspi3_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m",
+ "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
+ "sys_pll2_250m", "audio_pll2_out", };
+
+static const char * const imx8mp_pdm_sels[] = {"osc_24m", "sys_pll2_100m", "audio_pll1_out",
+ "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
+ "clk_ext3", "audio_pll2_out", };
+
+static const char * const imx8mp_vpu_vc8000e_sels[] = {"osc_24m", "vpu_pll_out", "sys_pll1_800m",
+ "sys_pll2_1000m", "audio_pll2_out", "sys_pll2_125m",
+ "sys_pll3_out", "audio_pll1_out", };
+
+static const char * const imx8mp_sai7_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
+ "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "clk_ext3", "clk_ext4", };
+
+static const char * const imx8mp_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
+
+static struct clk_onecell_data clk_data;
+static struct clk *clks[IMX8MP_CLK_END];
+
+static int imx8mp_clocks_init(struct device_node *ccm_np)
+{
+ struct device_node *anatop_np;
+ void __iomem *ccm_base, *anatop_base;
+ struct clk **hws = clks;
+ u32 val;
+ int ret;
+
+ anatop_np = of_find_compatible_node(NULL, NULL, "fsl,imx8mp-anatop");
+ anatop_base = of_iomap(anatop_np, 0);
+ if (WARN_ON(!anatop_base))
+ return -ENOMEM;
+
+ ccm_base = of_iomap(ccm_np, 0);
+ if (WARN_ON(!ccm_base))
+ return -ENOMEM;
+
+ hws[IMX8MP_CLK_DUMMY] = clk_fixed("dummy", 0);
+ hws[IMX8MP_CLK_24M] = of_clk_get_by_name(ccm_np, "osc_24m");
+ hws[IMX8MP_CLK_32K] = of_clk_get_by_name(ccm_np, "osc_32k");
+ hws[IMX8MP_CLK_EXT1] = of_clk_get_by_name(ccm_np, "clk_ext1");
+ hws[IMX8MP_CLK_EXT2] = of_clk_get_by_name(ccm_np, "clk_ext2");
+ hws[IMX8MP_CLK_EXT3] = of_clk_get_by_name(ccm_np, "clk_ext3");
+ hws[IMX8MP_CLK_EXT4] = of_clk_get_by_name(ccm_np, "clk_ext4");
+
+ hws[IMX8MP_AUDIO_PLL1_REF_SEL] = imx_clk_hw_mux("audio_pll1_ref_sel", anatop_base + 0x0, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ hws[IMX8MP_AUDIO_PLL2_REF_SEL] = imx_clk_hw_mux("audio_pll2_ref_sel", anatop_base + 0x14, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ hws[IMX8MP_VIDEO_PLL1_REF_SEL] = imx_clk_hw_mux("video_pll1_ref_sel", anatop_base + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ hws[IMX8MP_DRAM_PLL_REF_SEL] = imx_clk_hw_mux("dram_pll_ref_sel", anatop_base + 0x50, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ hws[IMX8MP_GPU_PLL_REF_SEL] = imx_clk_hw_mux("gpu_pll_ref_sel", anatop_base + 0x64, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ hws[IMX8MP_VPU_PLL_REF_SEL] = imx_clk_hw_mux("vpu_pll_ref_sel", anatop_base + 0x74, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ hws[IMX8MP_ARM_PLL_REF_SEL] = imx_clk_hw_mux("arm_pll_ref_sel", anatop_base + 0x84, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ hws[IMX8MP_SYS_PLL1_REF_SEL] = imx_clk_hw_mux("sys_pll1_ref_sel", anatop_base + 0x94, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ hws[IMX8MP_SYS_PLL2_REF_SEL] = imx_clk_hw_mux("sys_pll2_ref_sel", anatop_base + 0x104, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ hws[IMX8MP_SYS_PLL3_REF_SEL] = imx_clk_hw_mux("sys_pll3_ref_sel", anatop_base + 0x114, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+
+ hws[IMX8MP_AUDIO_PLL1] = imx_clk_hw_pll14xx("audio_pll1", "audio_pll1_ref_sel", anatop_base, &imx_1443x_pll);
+ hws[IMX8MP_AUDIO_PLL2] = imx_clk_hw_pll14xx("audio_pll2", "audio_pll2_ref_sel", anatop_base + 0x14, &imx_1443x_pll);
+ hws[IMX8MP_VIDEO_PLL1] = imx_clk_hw_pll14xx("video_pll1", "video_pll1_ref_sel", anatop_base + 0x28, &imx_1443x_pll);
+ hws[IMX8MP_DRAM_PLL] = imx_clk_hw_pll14xx("dram_pll", "dram_pll_ref_sel", anatop_base + 0x50, &imx_1443x_pll);
+ hws[IMX8MP_GPU_PLL] = imx_clk_hw_pll14xx("gpu_pll", "gpu_pll_ref_sel", anatop_base + 0x64, &imx_1416x_pll);
+ hws[IMX8MP_VPU_PLL] = imx_clk_hw_pll14xx("vpu_pll", "vpu_pll_ref_sel", anatop_base + 0x74, &imx_1416x_pll);
+ hws[IMX8MP_ARM_PLL] = imx_clk_hw_pll14xx("arm_pll", "arm_pll_ref_sel", anatop_base + 0x84, &imx_1416x_pll);
+ hws[IMX8MP_SYS_PLL1] = imx_clk_hw_pll14xx("sys_pll1", "sys_pll1_ref_sel", anatop_base + 0x94, &imx_1416x_pll);
+ hws[IMX8MP_SYS_PLL2] = imx_clk_hw_pll14xx("sys_pll2", "sys_pll2_ref_sel", anatop_base + 0x104, &imx_1416x_pll);
+ hws[IMX8MP_SYS_PLL3] = imx_clk_hw_pll14xx("sys_pll3", "sys_pll3_ref_sel", anatop_base + 0x114, &imx_1416x_pll);
+
+ hws[IMX8MP_AUDIO_PLL1_BYPASS] = imx_clk_hw_mux_flags("audio_pll1_bypass", anatop_base, 16, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT);
+ hws[IMX8MP_AUDIO_PLL2_BYPASS] = imx_clk_hw_mux_flags("audio_pll2_bypass", anatop_base + 0x14, 16, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels), CLK_SET_RATE_PARENT);
+ hws[IMX8MP_VIDEO_PLL1_BYPASS] = imx_clk_hw_mux_flags("video_pll1_bypass", anatop_base + 0x28, 16, 1, video_pll1_bypass_sels, ARRAY_SIZE(video_pll1_bypass_sels), CLK_SET_RATE_PARENT);
+ hws[IMX8MP_DRAM_PLL_BYPASS] = imx_clk_hw_mux_flags("dram_pll_bypass", anatop_base + 0x50, 16, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT);
+ hws[IMX8MP_GPU_PLL_BYPASS] = imx_clk_hw_mux_flags("gpu_pll_bypass", anatop_base + 0x64, 28, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
+ hws[IMX8MP_VPU_PLL_BYPASS] = imx_clk_hw_mux_flags("vpu_pll_bypass", anatop_base + 0x74, 28, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
+ hws[IMX8MP_ARM_PLL_BYPASS] = imx_clk_hw_mux_flags("arm_pll_bypass", anatop_base + 0x84, 28, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT);
+ hws[IMX8MP_SYS_PLL1_BYPASS] = imx_clk_hw_mux_flags("sys_pll1_bypass", anatop_base + 0x94, 28, 1, sys_pll1_bypass_sels, ARRAY_SIZE(sys_pll1_bypass_sels), CLK_SET_RATE_PARENT);
+ hws[IMX8MP_SYS_PLL2_BYPASS] = imx_clk_hw_mux_flags("sys_pll2_bypass", anatop_base + 0x104, 28, 1, sys_pll2_bypass_sels, ARRAY_SIZE(sys_pll2_bypass_sels), CLK_SET_RATE_PARENT);
+ hws[IMX8MP_SYS_PLL3_BYPASS] = imx_clk_hw_mux_flags("sys_pll3_bypass", anatop_base + 0x114, 28, 1, sys_pll3_bypass_sels, ARRAY_SIZE(sys_pll3_bypass_sels), CLK_SET_RATE_PARENT);
+
+ hws[IMX8MP_AUDIO_PLL1_OUT] = imx_clk_hw_gate("audio_pll1_out", "audio_pll1_bypass", anatop_base, 13);
+ hws[IMX8MP_AUDIO_PLL2_OUT] = imx_clk_hw_gate("audio_pll2_out", "audio_pll2_bypass", anatop_base + 0x14, 13);
+ hws[IMX8MP_VIDEO_PLL1_OUT] = imx_clk_hw_gate("video_pll1_out", "video_pll1_bypass", anatop_base + 0x28, 13);
+ hws[IMX8MP_DRAM_PLL_OUT] = imx_clk_hw_gate("dram_pll_out", "dram_pll_bypass", anatop_base + 0x50, 13);
+ hws[IMX8MP_GPU_PLL_OUT] = imx_clk_hw_gate("gpu_pll_out", "gpu_pll_bypass", anatop_base + 0x64, 11);
+ hws[IMX8MP_VPU_PLL_OUT] = imx_clk_hw_gate("vpu_pll_out", "vpu_pll_bypass", anatop_base + 0x74, 11);
+ hws[IMX8MP_ARM_PLL_OUT] = imx_clk_hw_gate("arm_pll_out", "arm_pll_bypass", anatop_base + 0x84, 11);
+ hws[IMX8MP_SYS_PLL3_OUT] = imx_clk_hw_gate("sys_pll3_out", "sys_pll3_bypass", anatop_base + 0x114, 11);
+
+ /*
+ * The gates in CCM_ANALOG_SYS_PLL1_GEN_CTRL are not handled by the
+ * driver, make sure they are all enabled.
+ */
+ val = readl(anatop_base + 0x94);
+ val |= BIT(13) | BIT(15) | BIT(17) | BIT(19) | BIT(21) | BIT(23) |
+ BIT(25) | BIT(27);
+ writel(val, anatop_base + 0x94);
+
+ hws[IMX8MP_SYS_PLL1_OUT] = imx_clk_hw_gate("sys_pll1_out", "sys_pll1_bypass", anatop_base + 0x94, 11);
+
+ hws[IMX8MP_SYS_PLL1_40M] = imx_clk_hw_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20);
+ hws[IMX8MP_SYS_PLL1_80M] = imx_clk_hw_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10);
+ hws[IMX8MP_SYS_PLL1_100M] = imx_clk_hw_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8);
+ hws[IMX8MP_SYS_PLL1_133M] = imx_clk_hw_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6);
+ hws[IMX8MP_SYS_PLL1_160M] = imx_clk_hw_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5);
+ hws[IMX8MP_SYS_PLL1_200M] = imx_clk_hw_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4);
+ hws[IMX8MP_SYS_PLL1_266M] = imx_clk_hw_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3);
+ hws[IMX8MP_SYS_PLL1_400M] = imx_clk_hw_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2);
+ hws[IMX8MP_SYS_PLL1_800M] = imx_clk_hw_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1);
+
+ hws[IMX8MP_SYS_PLL2_OUT] = imx_clk_hw_gate("sys_pll2_out", "sys_pll2_bypass", anatop_base + 0x104, 11);
+
+ /*
+ * The gates in CCM_ANALOG_SYS_PLL2_GEN_CTRL are not handled by the
+ * driver, make sure they are all enabled.
+ */
+ val = readl(anatop_base + 0x104);
+ val |= BIT(13) | BIT(15) | BIT(17) | BIT(19) | BIT(21) | BIT(23) |
+ BIT(25) | BIT(27);
+ writel(val, anatop_base + 0x104);
+
+ hws[IMX8MP_SYS_PLL2_50M] = imx_clk_hw_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20);
+ hws[IMX8MP_SYS_PLL2_100M] = imx_clk_hw_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10);
+ hws[IMX8MP_SYS_PLL2_125M] = imx_clk_hw_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8);
+ hws[IMX8MP_SYS_PLL2_166M] = imx_clk_hw_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6);
+ hws[IMX8MP_SYS_PLL2_200M] = imx_clk_hw_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5);
+ hws[IMX8MP_SYS_PLL2_250M] = imx_clk_hw_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4);
+ hws[IMX8MP_SYS_PLL2_333M] = imx_clk_hw_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3);
+ hws[IMX8MP_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2);
+ hws[IMX8MP_SYS_PLL2_1000M] = imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
+
+ hws[IMX8MP_CLK_A53_DIV] = imx8m_clk_hw_composite_core("arm_a53_div", imx8mp_a53_sels, ccm_base + 0x8000);
+ hws[IMX8MP_CLK_A53_SRC] = hws[IMX8MP_CLK_A53_DIV];
+ hws[IMX8MP_CLK_A53_CG] = hws[IMX8MP_CLK_A53_DIV];
+ hws[IMX8MP_CLK_M7_CORE] = imx8m_clk_hw_composite_core("m7_core", imx8mp_m7_sels, ccm_base + 0x8080);
+ hws[IMX8MP_CLK_ML_CORE] = imx8m_clk_hw_composite_core("ml_core", imx8mp_ml_sels, ccm_base + 0x8100);
+ hws[IMX8MP_CLK_GPU3D_CORE] = imx8m_clk_hw_composite_core("gpu3d_core", imx8mp_gpu3d_core_sels, ccm_base + 0x8180);
+ hws[IMX8MP_CLK_GPU3D_SHADER_CORE] = imx8m_clk_hw_composite("gpu3d_shader_core", imx8mp_gpu3d_shader_sels, ccm_base + 0x8200);
+ hws[IMX8MP_CLK_GPU2D_CORE] = imx8m_clk_hw_composite("gpu2d_core", imx8mp_gpu2d_sels, ccm_base + 0x8280);
+ hws[IMX8MP_CLK_AUDIO_AXI] = imx8m_clk_hw_composite("audio_axi", imx8mp_audio_axi_sels, ccm_base + 0x8300);
+ hws[IMX8MP_CLK_AUDIO_AXI_SRC] = hws[IMX8MP_CLK_AUDIO_AXI];
+ hws[IMX8MP_CLK_HSIO_AXI] = imx8m_clk_hw_composite("hsio_axi", imx8mp_hsio_axi_sels, ccm_base + 0x8380);
+ hws[IMX8MP_CLK_MEDIA_ISP] = imx8m_clk_hw_composite("media_isp", imx8mp_media_isp_sels, ccm_base + 0x8400);
+
+ /* CORE SEL */
+ hws[IMX8MP_CLK_A53_CORE] = imx_clk_hw_mux2("arm_a53_core", ccm_base + 0x9880, 24, 1, imx8mp_a53_core_sels, ARRAY_SIZE(imx8mp_a53_core_sels));
+
+ hws[IMX8MP_CLK_MAIN_AXI] = imx8m_clk_hw_composite_critical("main_axi", imx8mp_main_axi_sels, ccm_base + 0x8800);
+ hws[IMX8MP_CLK_ENET_AXI] = imx8m_clk_hw_composite_bus("enet_axi", imx8mp_enet_axi_sels, ccm_base + 0x8880);
+ hws[IMX8MP_CLK_NAND_USDHC_BUS] = imx8m_clk_hw_composite_critical("nand_usdhc_bus", imx8mp_nand_usdhc_sels, ccm_base + 0x8900);
+ hws[IMX8MP_CLK_VPU_BUS] = imx8m_clk_hw_composite_bus("vpu_bus", imx8mp_vpu_bus_sels, ccm_base + 0x8980);
+ hws[IMX8MP_CLK_MEDIA_AXI] = imx8m_clk_hw_composite_bus("media_axi", imx8mp_media_axi_sels, ccm_base + 0x8a00);
+ hws[IMX8MP_CLK_MEDIA_APB] = imx8m_clk_hw_composite_bus("media_apb", imx8mp_media_apb_sels, ccm_base + 0x8a80);
+ hws[IMX8MP_CLK_HDMI_APB] = imx8m_clk_hw_composite_bus("hdmi_apb", imx8mp_media_apb_sels, ccm_base + 0x8b00);
+ hws[IMX8MP_CLK_HDMI_AXI] = imx8m_clk_hw_composite_bus("hdmi_axi", imx8mp_media_axi_sels, ccm_base + 0x8b80);
+ hws[IMX8MP_CLK_GPU_AXI] = imx8m_clk_hw_composite_bus("gpu_axi", imx8mp_gpu_axi_sels, ccm_base + 0x8c00);
+ hws[IMX8MP_CLK_GPU_AHB] = imx8m_clk_hw_composite_bus("gpu_ahb", imx8mp_gpu_ahb_sels, ccm_base + 0x8c80);
+ hws[IMX8MP_CLK_NOC] = imx8m_clk_hw_composite_critical("noc", imx8mp_noc_sels, ccm_base + 0x8d00);
+ hws[IMX8MP_CLK_NOC_IO] = imx8m_clk_hw_composite_critical("noc_io", imx8mp_noc_io_sels, ccm_base + 0x8d80);
+ hws[IMX8MP_CLK_ML_AXI] = imx8m_clk_hw_composite_bus("ml_axi", imx8mp_ml_axi_sels, ccm_base + 0x8e00);
+ hws[IMX8MP_CLK_ML_AHB] = imx8m_clk_hw_composite_bus("ml_ahb", imx8mp_ml_ahb_sels, ccm_base + 0x8e80);
+
+ hws[IMX8MP_CLK_AHB] = imx8m_clk_hw_composite_critical("ahb_root", imx8mp_ahb_sels, ccm_base + 0x9000);
+ hws[IMX8MP_CLK_AUDIO_AHB] = imx8m_clk_hw_composite_bus("audio_ahb", imx8mp_audio_ahb_sels, ccm_base + 0x9100);
+ hws[IMX8MP_CLK_MIPI_DSI_ESC_RX] = imx8m_clk_hw_composite_bus("mipi_dsi_esc_rx", imx8mp_mipi_dsi_esc_rx_sels, ccm_base + 0x9200);
+
+ hws[IMX8MP_CLK_IPG_ROOT] = imx_clk_hw_divider2("ipg_root", "ahb_root", ccm_base + 0x9080, 0, 1);
+
+ hws[IMX8MP_CLK_DRAM_ALT] = imx8m_clk_hw_composite("dram_alt", imx8mp_dram_alt_sels, ccm_base + 0xa000);
+ hws[IMX8MP_CLK_DRAM_APB] = imx8m_clk_hw_composite_critical("dram_apb", imx8mp_dram_apb_sels, ccm_base + 0xa080);
+ hws[IMX8MP_CLK_VPU_G1] = imx8m_clk_hw_composite("vpu_g1", imx8mp_vpu_g1_sels, ccm_base + 0xa100);
+ hws[IMX8MP_CLK_VPU_G2] = imx8m_clk_hw_composite("vpu_g2", imx8mp_vpu_g2_sels, ccm_base + 0xa180);
+ hws[IMX8MP_CLK_CAN1] = imx8m_clk_hw_composite("can1", imx8mp_can1_sels, ccm_base + 0xa200);
+ hws[IMX8MP_CLK_CAN2] = imx8m_clk_hw_composite("can2", imx8mp_can2_sels, ccm_base + 0xa280);
+ hws[IMX8MP_CLK_MEMREPAIR] = imx8m_clk_hw_composite("memrepair", imx8mp_memrepair_sels, ccm_base + 0xa300);
+ hws[IMX8MP_CLK_PCIE_AUX] = imx8m_clk_hw_composite("pcie_aux", imx8mp_pcie_aux_sels, ccm_base + 0xa400);
+ hws[IMX8MP_CLK_I2C5] = imx8m_clk_hw_composite("i2c5", imx8mp_i2c5_sels, ccm_base + 0xa480);
+ hws[IMX8MP_CLK_I2C6] = imx8m_clk_hw_composite("i2c6", imx8mp_i2c6_sels, ccm_base + 0xa500);
+ hws[IMX8MP_CLK_SAI1] = imx8m_clk_hw_composite("sai1", imx8mp_sai1_sels, ccm_base + 0xa580);
+ hws[IMX8MP_CLK_SAI2] = imx8m_clk_hw_composite("sai2", imx8mp_sai2_sels, ccm_base + 0xa600);
+ hws[IMX8MP_CLK_SAI3] = imx8m_clk_hw_composite("sai3", imx8mp_sai3_sels, ccm_base + 0xa680);
+ hws[IMX8MP_CLK_SAI5] = imx8m_clk_hw_composite("sai5", imx8mp_sai5_sels, ccm_base + 0xa780);
+ hws[IMX8MP_CLK_SAI6] = imx8m_clk_hw_composite("sai6", imx8mp_sai6_sels, ccm_base + 0xa800);
+ hws[IMX8MP_CLK_ENET_QOS] = imx8m_clk_hw_composite("enet_qos", imx8mp_enet_qos_sels, ccm_base + 0xa880);
+ hws[IMX8MP_CLK_ENET_QOS_TIMER] = imx8m_clk_hw_composite("enet_qos_timer", imx8mp_enet_qos_timer_sels, ccm_base + 0xa900);
+ hws[IMX8MP_CLK_ENET_REF] = imx8m_clk_hw_composite("enet_ref", imx8mp_enet_ref_sels, ccm_base + 0xa980);
+ hws[IMX8MP_CLK_ENET_TIMER] = imx8m_clk_hw_composite("enet_timer", imx8mp_enet_timer_sels, ccm_base + 0xaa00);
+ hws[IMX8MP_CLK_ENET_PHY_REF] = imx8m_clk_hw_composite("enet_phy_ref", imx8mp_enet_phy_ref_sels, ccm_base + 0xaa80);
+ hws[IMX8MP_CLK_NAND] = imx8m_clk_hw_composite("nand", imx8mp_nand_sels, ccm_base + 0xab00);
+ hws[IMX8MP_CLK_QSPI] = imx8m_clk_hw_composite("qspi", imx8mp_qspi_sels, ccm_base + 0xab80);
+ hws[IMX8MP_CLK_USDHC1] = imx8m_clk_hw_composite("usdhc1", imx8mp_usdhc1_sels, ccm_base + 0xac00);
+ hws[IMX8MP_CLK_USDHC2] = imx8m_clk_hw_composite("usdhc2", imx8mp_usdhc2_sels, ccm_base + 0xac80);
+ hws[IMX8MP_CLK_I2C1] = imx8m_clk_hw_composite("i2c1", imx8mp_i2c1_sels, ccm_base + 0xad00);
+ hws[IMX8MP_CLK_I2C2] = imx8m_clk_hw_composite("i2c2", imx8mp_i2c2_sels, ccm_base + 0xad80);
+ hws[IMX8MP_CLK_I2C3] = imx8m_clk_hw_composite("i2c3", imx8mp_i2c3_sels, ccm_base + 0xae00);
+ hws[IMX8MP_CLK_I2C4] = imx8m_clk_hw_composite("i2c4", imx8mp_i2c4_sels, ccm_base + 0xae80);
+
+ hws[IMX8MP_CLK_UART1] = imx8m_clk_hw_composite("uart1", imx8mp_uart1_sels, ccm_base + 0xaf00);
+ hws[IMX8MP_CLK_UART2] = imx8m_clk_hw_composite("uart2", imx8mp_uart2_sels, ccm_base + 0xaf80);
+ hws[IMX8MP_CLK_UART3] = imx8m_clk_hw_composite("uart3", imx8mp_uart3_sels, ccm_base + 0xb000);
+ hws[IMX8MP_CLK_UART4] = imx8m_clk_hw_composite("uart4", imx8mp_uart4_sels, ccm_base + 0xb080);
+ hws[IMX8MP_CLK_USB_CORE_REF] = imx8m_clk_hw_composite("usb_core_ref", imx8mp_usb_core_ref_sels, ccm_base + 0xb100);
+ hws[IMX8MP_CLK_USB_PHY_REF] = imx8m_clk_hw_composite("usb_phy_ref", imx8mp_usb_phy_ref_sels, ccm_base + 0xb180);
+ hws[IMX8MP_CLK_GIC] = imx8m_clk_hw_composite_critical("gic", imx8mp_gic_sels, ccm_base + 0xb200);
+ hws[IMX8MP_CLK_ECSPI1] = imx8m_clk_hw_composite("ecspi1", imx8mp_ecspi1_sels, ccm_base + 0xb280);
+ hws[IMX8MP_CLK_ECSPI2] = imx8m_clk_hw_composite("ecspi2", imx8mp_ecspi2_sels, ccm_base + 0xb300);
+ hws[IMX8MP_CLK_PWM1] = imx8m_clk_hw_composite("pwm1", imx8mp_pwm1_sels, ccm_base + 0xb380);
+ hws[IMX8MP_CLK_PWM2] = imx8m_clk_hw_composite("pwm2", imx8mp_pwm2_sels, ccm_base + 0xb400);
+ hws[IMX8MP_CLK_PWM3] = imx8m_clk_hw_composite("pwm3", imx8mp_pwm3_sels, ccm_base + 0xb480);
+ hws[IMX8MP_CLK_PWM4] = imx8m_clk_hw_composite("pwm4", imx8mp_pwm4_sels, ccm_base + 0xb500);
+
+ hws[IMX8MP_CLK_GPT1] = imx8m_clk_hw_composite("gpt1", imx8mp_gpt1_sels, ccm_base + 0xb580);
+ hws[IMX8MP_CLK_GPT2] = imx8m_clk_hw_composite("gpt2", imx8mp_gpt2_sels, ccm_base + 0xb600);
+ hws[IMX8MP_CLK_GPT3] = imx8m_clk_hw_composite("gpt3", imx8mp_gpt3_sels, ccm_base + 0xb680);
+ hws[IMX8MP_CLK_GPT4] = imx8m_clk_hw_composite("gpt4", imx8mp_gpt4_sels, ccm_base + 0xb700);
+ hws[IMX8MP_CLK_GPT5] = imx8m_clk_hw_composite("gpt5", imx8mp_gpt5_sels, ccm_base + 0xb780);
+ hws[IMX8MP_CLK_GPT6] = imx8m_clk_hw_composite("gpt6", imx8mp_gpt6_sels, ccm_base + 0xb800);
+ hws[IMX8MP_CLK_WDOG] = imx8m_clk_hw_composite("wdog", imx8mp_wdog_sels, ccm_base + 0xb900);
+ hws[IMX8MP_CLK_WRCLK] = imx8m_clk_hw_composite("wrclk", imx8mp_wrclk_sels, ccm_base + 0xb980);
+ hws[IMX8MP_CLK_IPP_DO_CLKO1] = imx8m_clk_hw_composite("ipp_do_clko1", imx8mp_ipp_do_clko1_sels, ccm_base + 0xba00);
+ hws[IMX8MP_CLK_IPP_DO_CLKO2] = imx8m_clk_hw_composite("ipp_do_clko2", imx8mp_ipp_do_clko2_sels, ccm_base + 0xba80);
+ hws[IMX8MP_CLK_HDMI_FDCC_TST] = imx8m_clk_hw_composite("hdmi_fdcc_tst", imx8mp_hdmi_fdcc_tst_sels, ccm_base + 0xbb00);
+ hws[IMX8MP_CLK_HDMI_24M] = imx8m_clk_hw_composite("hdmi_24m", imx8mp_hdmi_24m_sels, ccm_base + 0xbb80);
+ hws[IMX8MP_CLK_HDMI_REF_266M] = imx8m_clk_hw_composite("hdmi_ref_266m", imx8mp_hdmi_ref_266m_sels, ccm_base + 0xbc00);
+ hws[IMX8MP_CLK_USDHC3] = imx8m_clk_hw_composite("usdhc3", imx8mp_usdhc3_sels, ccm_base + 0xbc80);
+ hws[IMX8MP_CLK_MEDIA_CAM1_PIX] = imx8m_clk_hw_composite("media_cam1_pix", imx8mp_media_cam1_pix_sels, ccm_base + 0xbd00);
+ hws[IMX8MP_CLK_MEDIA_MIPI_PHY1_REF] = imx8m_clk_hw_composite("media_mipi_phy1_ref", imx8mp_media_mipi_phy1_ref_sels, ccm_base + 0xbd80);
+ hws[IMX8MP_CLK_MEDIA_DISP1_PIX] = imx8m_clk_hw_composite("media_disp1_pix", imx8mp_media_disp1_pix_sels, ccm_base + 0xbe00);
+ hws[IMX8MP_CLK_MEDIA_CAM2_PIX] = imx8m_clk_hw_composite("media_cam2_pix", imx8mp_media_cam2_pix_sels, ccm_base + 0xbe80);
+ hws[IMX8MP_CLK_MEDIA_LDB] = imx8m_clk_hw_composite("media_ldb", imx8mp_media_ldb_sels, ccm_base + 0xbf00);
+ hws[IMX8MP_CLK_MEDIA_MIPI_CSI2_ESC] = imx8m_clk_hw_composite("media_mipi_csi2_esc", imx8mp_media_mipi_csi2_esc_sels, ccm_base + 0xbf80);
+ hws[IMX8MP_CLK_MEDIA_MIPI_TEST_BYTE] = imx8m_clk_hw_composite("media_mipi_test_byte", imx8mp_media_mipi_test_byte_sels, ccm_base + 0xc100);
+ hws[IMX8MP_CLK_ECSPI3] = imx8m_clk_hw_composite("ecspi3", imx8mp_ecspi3_sels, ccm_base + 0xc180);
+ hws[IMX8MP_CLK_PDM] = imx8m_clk_hw_composite("pdm", imx8mp_pdm_sels, ccm_base + 0xc200);
+ hws[IMX8MP_CLK_VPU_VC8000E] = imx8m_clk_hw_composite("vpu_vc8000e", imx8mp_vpu_vc8000e_sels, ccm_base + 0xc280);
+ hws[IMX8MP_CLK_SAI7] = imx8m_clk_hw_composite("sai7", imx8mp_sai7_sels, ccm_base + 0xc300);
+
+ hws[IMX8MP_CLK_DRAM_ALT_ROOT] = imx_clk_hw_fixed_factor("dram_alt_root", "dram_alt", 1, 4);
+ hws[IMX8MP_CLK_DRAM_CORE] = imx_clk_hw_mux2_flags("dram_core_clk", ccm_base + 0x9800, 24, 1, imx8mp_dram_core_sels, ARRAY_SIZE(imx8mp_dram_core_sels), CLK_IS_CRITICAL);
+
+ hws[IMX8MP_CLK_DRAM1_ROOT] = imx_clk_hw_gate4_flags("dram1_root_clk", "dram_core_clk", ccm_base + 0x4050, 0, CLK_IS_CRITICAL);
+ hws[IMX8MP_CLK_ECSPI1_ROOT] = imx_clk_hw_gate4("ecspi1_root_clk", "ecspi1", ccm_base + 0x4070, 0);
+ hws[IMX8MP_CLK_ECSPI2_ROOT] = imx_clk_hw_gate4("ecspi2_root_clk", "ecspi2", ccm_base + 0x4080, 0);
+ hws[IMX8MP_CLK_ECSPI3_ROOT] = imx_clk_hw_gate4("ecspi3_root_clk", "ecspi3", ccm_base + 0x4090, 0);
+ hws[IMX8MP_CLK_ENET1_ROOT] = imx_clk_hw_gate4("enet1_root_clk", "enet_axi", ccm_base + 0x40a0, 0);
+ hws[IMX8MP_CLK_GPIO1_ROOT] = imx_clk_hw_gate4("gpio1_root_clk", "ipg_root", ccm_base + 0x40b0, 0);
+ hws[IMX8MP_CLK_GPIO2_ROOT] = imx_clk_hw_gate4("gpio2_root_clk", "ipg_root", ccm_base + 0x40c0, 0);
+ hws[IMX8MP_CLK_GPIO3_ROOT] = imx_clk_hw_gate4("gpio3_root_clk", "ipg_root", ccm_base + 0x40d0, 0);
+ hws[IMX8MP_CLK_GPIO4_ROOT] = imx_clk_hw_gate4("gpio4_root_clk", "ipg_root", ccm_base + 0x40e0, 0);
+ hws[IMX8MP_CLK_GPIO5_ROOT] = imx_clk_hw_gate4("gpio5_root_clk", "ipg_root", ccm_base + 0x40f0, 0);
+ hws[IMX8MP_CLK_GPT1_ROOT] = imx_clk_hw_gate4("gpt1_root_clk", "gpt1", ccm_base + 0x4100, 0);
+ hws[IMX8MP_CLK_GPT2_ROOT] = imx_clk_hw_gate4("gpt2_root_clk", "gpt2", ccm_base + 0x4110, 0);
+ hws[IMX8MP_CLK_GPT3_ROOT] = imx_clk_hw_gate4("gpt3_root_clk", "gpt3", ccm_base + 0x4120, 0);
+ hws[IMX8MP_CLK_GPT4_ROOT] = imx_clk_hw_gate4("gpt4_root_clk", "gpt4", ccm_base + 0x4130, 0);
+ hws[IMX8MP_CLK_GPT5_ROOT] = imx_clk_hw_gate4("gpt5_root_clk", "gpt5", ccm_base + 0x4140, 0);
+ hws[IMX8MP_CLK_GPT6_ROOT] = imx_clk_hw_gate4("gpt6_root_clk", "gpt6", ccm_base + 0x4150, 0);
+ hws[IMX8MP_CLK_I2C1_ROOT] = imx_clk_hw_gate4("i2c1_root_clk", "i2c1", ccm_base + 0x4170, 0);
+ hws[IMX8MP_CLK_I2C2_ROOT] = imx_clk_hw_gate4("i2c2_root_clk", "i2c2", ccm_base + 0x4180, 0);
+ hws[IMX8MP_CLK_I2C3_ROOT] = imx_clk_hw_gate4("i2c3_root_clk", "i2c3", ccm_base + 0x4190, 0);
+ hws[IMX8MP_CLK_I2C4_ROOT] = imx_clk_hw_gate4("i2c4_root_clk", "i2c4", ccm_base + 0x41a0, 0);
+ hws[IMX8MP_CLK_OCOTP_ROOT] = imx_clk_hw_gate4("ocotp_root_clk", "ipg_root", ccm_base + 0x4220, 0);
+ hws[IMX8MP_CLK_PCIE_ROOT] = imx_clk_hw_gate4("pcie_root_clk", "pcie_aux", ccm_base + 0x4250, 0);
+ hws[IMX8MP_CLK_PWM1_ROOT] = imx_clk_hw_gate4("pwm1_root_clk", "pwm1", ccm_base + 0x4280, 0);
+ hws[IMX8MP_CLK_PWM2_ROOT] = imx_clk_hw_gate4("pwm2_root_clk", "pwm2", ccm_base + 0x4290, 0);
+ hws[IMX8MP_CLK_PWM3_ROOT] = imx_clk_hw_gate4("pwm3_root_clk", "pwm3", ccm_base + 0x42a0, 0);
+ hws[IMX8MP_CLK_PWM4_ROOT] = imx_clk_hw_gate4("pwm4_root_clk", "pwm4", ccm_base + 0x42b0, 0);
+ hws[IMX8MP_CLK_QOS_ROOT] = imx_clk_hw_gate4("qos_root_clk", "ipg_root", ccm_base + 0x42c0, 0);
+ hws[IMX8MP_CLK_QOS_ENET_ROOT] = imx_clk_hw_gate4("qos_enet_root_clk", "ipg_root", ccm_base + 0x42e0, 0);
+ hws[IMX8MP_CLK_QSPI_ROOT] = imx_clk_hw_gate4("qspi_root_clk", "qspi", ccm_base + 0x42f0, 0);
+ hws[IMX8MP_CLK_NAND_ROOT] = imx_clk_hw_gate2_shared2("nand_root_clk", "nand", ccm_base + 0x4300, 0);
+ hws[IMX8MP_CLK_NAND_USDHC_BUS_RAWNAND_CLK] = imx_clk_hw_gate2_shared2("nand_usdhc_rawnand_clk", "nand_usdhc_bus", ccm_base + 0x4300, 0);
+ hws[IMX8MP_CLK_I2C5_ROOT] = imx_clk_hw_gate2("i2c5_root_clk", "i2c5", ccm_base + 0x4330, 0);
+ hws[IMX8MP_CLK_I2C6_ROOT] = imx_clk_hw_gate2("i2c6_root_clk", "i2c6", ccm_base + 0x4340, 0);
+ hws[IMX8MP_CLK_CAN1_ROOT] = imx_clk_hw_gate2("can1_root_clk", "can1", ccm_base + 0x4350, 0);
+ hws[IMX8MP_CLK_CAN2_ROOT] = imx_clk_hw_gate2("can2_root_clk", "can2", ccm_base + 0x4360, 0);
+ hws[IMX8MP_CLK_SDMA1_ROOT] = imx_clk_hw_gate4("sdma1_root_clk", "ipg_root", ccm_base + 0x43a0, 0);
+ hws[IMX8MP_CLK_ENET_QOS_ROOT] = imx_clk_hw_gate4("enet_qos_root_clk", "sim_enet_root_clk", ccm_base + 0x43b0, 0);
+ hws[IMX8MP_CLK_SIM_ENET_ROOT] = imx_clk_hw_gate4("sim_enet_root_clk", "enet_axi", ccm_base + 0x4400, 0);
+ hws[IMX8MP_CLK_GPU2D_ROOT] = imx_clk_hw_gate4("gpu2d_root_clk", "gpu2d_core", ccm_base + 0x4450, 0);
+ hws[IMX8MP_CLK_GPU3D_ROOT] = imx_clk_hw_gate4("gpu3d_root_clk", "gpu3d_core", ccm_base + 0x4460, 0);
+ hws[IMX8MP_CLK_SNVS_ROOT] = imx_clk_hw_gate4("snvs_root_clk", "ipg_root", ccm_base + 0x4470, 0);
+ hws[IMX8MP_CLK_UART1_ROOT] = imx_clk_hw_gate4("uart1_root_clk", "uart1", ccm_base + 0x4490, 0);
+ hws[IMX8MP_CLK_UART2_ROOT] = imx_clk_hw_gate4("uart2_root_clk", "uart2", ccm_base + 0x44a0, 0);
+ hws[IMX8MP_CLK_UART3_ROOT] = imx_clk_hw_gate4("uart3_root_clk", "uart3", ccm_base + 0x44b0, 0);
+ hws[IMX8MP_CLK_UART4_ROOT] = imx_clk_hw_gate4("uart4_root_clk", "uart4", ccm_base + 0x44c0, 0);
+ hws[IMX8MP_CLK_USB_ROOT] = imx_clk_hw_gate2_shared2("usb_root_clk", "hsio_axi", ccm_base + 0x44d0, 0);
+ hws[IMX8MP_CLK_USB_SUSP] = imx_clk_hw_gate2_shared2("usb_suspend_clk", "osc_32k", ccm_base + 0x44d0, 0);
+ hws[IMX8MP_CLK_USB_PHY_ROOT] = imx_clk_hw_gate4("usb_phy_root_clk", "usb_phy_ref", ccm_base + 0x44f0, 0);
+ hws[IMX8MP_CLK_USDHC1_ROOT] = imx_clk_hw_gate4("usdhc1_root_clk", "usdhc1", ccm_base + 0x4510, 0);
+ hws[IMX8MP_CLK_USDHC2_ROOT] = imx_clk_hw_gate4("usdhc2_root_clk", "usdhc2", ccm_base + 0x4520, 0);
+ hws[IMX8MP_CLK_WDOG1_ROOT] = imx_clk_hw_gate4("wdog1_root_clk", "wdog", ccm_base + 0x4530, 0);
+ hws[IMX8MP_CLK_WDOG2_ROOT] = imx_clk_hw_gate4("wdog2_root_clk", "wdog", ccm_base + 0x4540, 0);
+ hws[IMX8MP_CLK_WDOG3_ROOT] = imx_clk_hw_gate4("wdog3_root_clk", "wdog", ccm_base + 0x4550, 0);
+ hws[IMX8MP_CLK_VPU_G1_ROOT] = imx_clk_hw_gate4("vpu_g1_root_clk", "vpu_g1", ccm_base + 0x4560, 0);
+ hws[IMX8MP_CLK_GPU_ROOT] = imx_clk_hw_gate4("gpu_root_clk", "gpu_axi", ccm_base + 0x4570, 0);
+ hws[IMX8MP_CLK_VPU_VC8KE_ROOT] = imx_clk_hw_gate4("vpu_vc8ke_root_clk", "vpu_vc8000e", ccm_base + 0x4590, 0);
+ hws[IMX8MP_CLK_VPU_G2_ROOT] = imx_clk_hw_gate4("vpu_g2_root_clk", "vpu_g2", ccm_base + 0x45a0, 0);
+ hws[IMX8MP_CLK_NPU_ROOT] = imx_clk_hw_gate4("npu_root_clk", "ml_core", ccm_base + 0x45b0, 0);
+ hws[IMX8MP_CLK_HSIO_ROOT] = imx_clk_hw_gate4("hsio_root_clk", "ipg_root", ccm_base + 0x45c0, 0);
+ hws[IMX8MP_CLK_MEDIA_APB_ROOT] = imx_clk_hw_gate2_shared2("media_apb_root_clk", "media_apb", ccm_base + 0x45d0, 0);
+ hws[IMX8MP_CLK_MEDIA_AXI_ROOT] = imx_clk_hw_gate2_shared2("media_axi_root_clk", "media_axi", ccm_base + 0x45d0, 0);
+ hws[IMX8MP_CLK_MEDIA_CAM1_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_cam1_pix_root_clk", "media_cam1_pix", ccm_base + 0x45d0, 0);
+ hws[IMX8MP_CLK_MEDIA_CAM2_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_cam2_pix_root_clk", "media_cam2_pix", ccm_base + 0x45d0, 0);
+ hws[IMX8MP_CLK_MEDIA_DISP1_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_disp1_pix_root_clk", "media_disp1_pix", ccm_base + 0x45d0, 0);
+ hws[IMX8MP_CLK_MEDIA_DISP2_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_disp2_pix_root_clk", "media_disp2_pix", ccm_base + 0x45d0, 0);
+ hws[IMX8MP_CLK_MEDIA_ISP_ROOT] = imx_clk_hw_gate2_shared2("media_isp_root_clk", "media_isp", ccm_base + 0x45d0, 0);
+
+ hws[IMX8MP_CLK_USDHC3_ROOT] = imx_clk_hw_gate4("usdhc3_root_clk", "usdhc3", ccm_base + 0x45e0, 0);
+ hws[IMX8MP_CLK_HDMI_ROOT] = imx_clk_hw_gate4("hdmi_root_clk", "hdmi_axi", ccm_base + 0x45f0, 0);
+ hws[IMX8MP_CLK_TSENSOR_ROOT] = imx_clk_hw_gate4("tsensor_root_clk", "ipg_root", ccm_base + 0x4620, 0);
+ hws[IMX8MP_CLK_VPU_ROOT] = imx_clk_hw_gate4("vpu_root_clk", "vpu_bus", ccm_base + 0x4630, 0);
+ hws[IMX8MP_CLK_AUDIO_ROOT] = imx_clk_hw_gate4("audio_root_clk", "ipg_root", ccm_base + 0x4650, 0);
+
+ hws[IMX8MP_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_core",
+ hws[IMX8MP_CLK_A53_CORE],
+ hws[IMX8MP_CLK_A53_CORE],
+ hws[IMX8MP_ARM_PLL_OUT],
+ hws[IMX8MP_CLK_A53_DIV]);
+
+ imx_check_clocks(hws, IMX8MP_CLK_END);
+
+ clk_data.clks = clks;
+ clk_data.clk_num = ARRAY_SIZE(clks);
+
+ ret = of_clk_add_provider(ccm_np, of_clk_src_onecell_get, &clk_data);
+ if (ret < 0)
+ pr_err("failed to register clks for i.MX8MM\n");
+
+ return ret;
+}
+CLK_OF_DECLARE(imx8mp, "fsl,imx8mp-ccm", imx8mp_clocks_init);
diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c
index 016d405e90..2c21f75ea7 100644
--- a/drivers/clk/imx/clk-imx8mq.c
+++ b/drivers/clk/imx/clk-imx8mq.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2018 NXP.
* Copyright (C) 2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
@@ -255,6 +255,9 @@ static const char *imx8mq_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", }
static const char *imx8mq_clko2_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_400m", "sys2_pll_166m", "audio_pll1_out",
"video_pll1_out", "ckil", };
+static const char * const imx8mq_arm_m4_sels[] = {"osc_25m", "sys2_pll_200m",
+ "sys2_pll_250m", "sys1_pll_266m", "sys1_pll_800m", "audio_pll1_out",
+ "video_pll1_out", "sys3_pll_out", };
static struct clk_onecell_data clk_data;
@@ -552,6 +555,8 @@ static int imx8mq_clocks_init(struct device_node *ccm_node)
clks[IMX8MQ_CLK_SDMA1_ROOT] = imx_clk_gate4("sdma1_clk", "ipg_root", base + 0x43a0, 0);
clks[IMX8MQ_CLK_SDMA2_ROOT] = imx_clk_gate4("sdma2_clk", "ipg_audio_root", base + 0x43b0, 0);
+ clks[IMX8MQ_CLK_M4_CORE] = imx8m_clk_hw_composite_core("arm_m4_core", imx8mq_arm_m4_sels, base + 0x8080);
+
clks[IMX8MQ_GPT_3M_CLK] = imx_clk_fixed_factor("gpt_3m", "osc_25m", 1, 8);
clks[IMX8MQ_CLK_DRAM_ALT_ROOT] = imx_clk_fixed_factor("dram_alt_root", "dram_alt", 1, 4);
diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c
new file mode 100644
index 0000000000..e460091ba6
--- /dev/null
+++ b/drivers/clk/imx/clk-imx93.c
@@ -0,0 +1,331 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2021 NXP.
+ */
+
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <of_address.h>
+#include <dt-bindings/clock/imx93-clock.h>
+
+#include "clk.h"
+
+enum clk_sel {
+ LOW_SPEED_IO_SEL,
+ NON_IO_SEL,
+ FAST_SEL,
+ AUDIO_SEL,
+ VIDEO_SEL,
+ TPM_SEL,
+ CKO1_SEL,
+ CKO2_SEL,
+ MISC_SEL,
+ MAX_SEL
+};
+
+static u32 share_count_sai1;
+static u32 share_count_sai2;
+static u32 share_count_sai3;
+static u32 share_count_mub;
+static u32 share_count_pdm;
+
+static const char * const a55_core_sels[] = {"a55_alt", "arm_pll"};
+static const char *parent_names[MAX_SEL][4] = {
+ {"osc_24m", "sys_pll_pfd0_div2", "sys_pll_pfd1_div2", "video_pll"},
+ {"osc_24m", "sys_pll_pfd0_div2", "sys_pll_pfd1_div2", "sys_pll_pfd2_div2"},
+ {"osc_24m", "sys_pll_pfd0", "sys_pll_pfd1", "sys_pll_pfd2"},
+ {"osc_24m", "audio_pll", "video_pll", "clk_ext1"},
+ {"osc_24m", "audio_pll", "video_pll", "sys_pll_pfd0"},
+ {"osc_24m", "sys_pll_pfd0", "audio_pll", "clk_ext1"},
+ {"osc_24m", "sys_pll_pfd0", "sys_pll_pfd1", "audio_pll"},
+ {"osc_24m", "sys_pll_pfd0", "sys_pll_pfd1", "video_pll"},
+ {"osc_24m", "audio_pll", "video_pll", "sys_pll_pfd2"},
+};
+
+static const struct imx93_clk_root {
+ u32 clk;
+ char *name;
+ u32 off;
+ enum clk_sel sel;
+ unsigned long flags;
+} root_array[] = {
+ /* a55/m33/bus critical clk for system run */
+ { IMX93_CLK_A55_PERIPH, "a55_periph_root", 0x0000, FAST_SEL, CLK_IS_CRITICAL },
+ { IMX93_CLK_A55_MTR_BUS, "a55_mtr_bus_root", 0x0080, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL },
+ { IMX93_CLK_A55, "a55_alt_root", 0x0100, FAST_SEL, CLK_IS_CRITICAL },
+ { IMX93_CLK_M33, "m33_root", 0x0180, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL },
+ { IMX93_CLK_BUS_WAKEUP, "bus_wakeup_root", 0x0280, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL },
+ { IMX93_CLK_BUS_AON, "bus_aon_root", 0x0300, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL },
+ { IMX93_CLK_WAKEUP_AXI, "wakeup_axi_root", 0x0380, FAST_SEL, CLK_IS_CRITICAL },
+ { IMX93_CLK_SWO_TRACE, "swo_trace_root", 0x0400, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_M33_SYSTICK, "m33_systick_root", 0x0480, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_FLEXIO1, "flexio1_root", 0x0500, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_FLEXIO2, "flexio2_root", 0x0580, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPTMR1, "lptmr1_root", 0x0700, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPTMR2, "lptmr2_root", 0x0780, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_TPM2, "tpm2_root", 0x0880, TPM_SEL, },
+ { IMX93_CLK_TPM4, "tpm4_root", 0x0980, TPM_SEL, },
+ { IMX93_CLK_TPM5, "tpm5_root", 0x0a00, TPM_SEL, },
+ { IMX93_CLK_TPM6, "tpm6_root", 0x0a80, TPM_SEL, },
+ { IMX93_CLK_FLEXSPI1, "flexspi1_root", 0x0b00, FAST_SEL, },
+ { IMX93_CLK_CAN1, "can1_root", 0x0b80, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_CAN2, "can2_root", 0x0c00, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPUART1, "lpuart1_root", 0x0c80, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPUART2, "lpuart2_root", 0x0d00, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPUART3, "lpuart3_root", 0x0d80, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPUART4, "lpuart4_root", 0x0e00, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPUART5, "lpuart5_root", 0x0e80, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPUART6, "lpuart6_root", 0x0f00, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPUART7, "lpuart7_root", 0x0f80, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPUART8, "lpuart8_root", 0x1000, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPI2C1, "lpi2c1_root", 0x1080, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPI2C2, "lpi2c2_root", 0x1100, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPI2C3, "lpi2c3_root", 0x1180, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPI2C4, "lpi2c4_root", 0x1200, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPI2C5, "lpi2c5_root", 0x1280, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPI2C6, "lpi2c6_root", 0x1300, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPI2C7, "lpi2c7_root", 0x1380, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPI2C8, "lpi2c8_root", 0x1400, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPSPI1, "lpspi1_root", 0x1480, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPSPI2, "lpspi2_root", 0x1500, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPSPI3, "lpspi3_root", 0x1580, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPSPI4, "lpspi4_root", 0x1600, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPSPI5, "lpspi5_root", 0x1680, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPSPI6, "lpspi6_root", 0x1700, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPSPI7, "lpspi7_root", 0x1780, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_LPSPI8, "lpspi8_root", 0x1800, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_I3C1, "i3c1_root", 0x1880, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_I3C2, "i3c2_root", 0x1900, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_USDHC1, "usdhc1_root", 0x1980, FAST_SEL, },
+ { IMX93_CLK_USDHC2, "usdhc2_root", 0x1a00, FAST_SEL, },
+ { IMX93_CLK_USDHC3, "usdhc3_root", 0x1a80, FAST_SEL, },
+ { IMX93_CLK_SAI1, "sai1_root", 0x1b00, AUDIO_SEL, },
+ { IMX93_CLK_SAI2, "sai2_root", 0x1b80, AUDIO_SEL, },
+ { IMX93_CLK_SAI3, "sai3_root", 0x1c00, AUDIO_SEL, },
+ { IMX93_CLK_CCM_CKO1, "ccm_cko1_root", 0x1c80, CKO1_SEL, },
+ { IMX93_CLK_CCM_CKO2, "ccm_cko2_root", 0x1d00, CKO2_SEL, },
+ { IMX93_CLK_CCM_CKO3, "ccm_cko3_root", 0x1d80, CKO1_SEL, },
+ { IMX93_CLK_CCM_CKO4, "ccm_cko4_root", 0x1e00, CKO2_SEL, },
+ /*
+ * Critical because clk is used for handshake between HSIOMIX and NICMIX when
+ * NICMIX power down/on during system suspend/resume
+ */
+ { IMX93_CLK_HSIO, "hsio_root", 0x1e80, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL},
+ { IMX93_CLK_HSIO_USB_TEST_60M, "hsio_usb_test_60m_root", 0x1f00, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_HSIO_ACSCAN_80M, "hsio_acscan_80m_root", 0x1f80, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_HSIO_ACSCAN_480M, "hsio_acscan_480m_root", 0x2000, MISC_SEL, },
+ { IMX93_CLK_NIC_AXI, "nic_axi_root", 0x2080, FAST_SEL, CLK_IS_CRITICAL, },
+ { IMX93_CLK_ML_APB, "ml_apb_root", 0x2180, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_ML, "ml_root", 0x2200, FAST_SEL, },
+ { IMX93_CLK_MEDIA_AXI, "media_axi_root", 0x2280, FAST_SEL, },
+ { IMX93_CLK_MEDIA_APB, "media_apb_root", 0x2300, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_MEDIA_LDB, "media_ldb_root", 0x2380, VIDEO_SEL, },
+ { IMX93_CLK_MEDIA_DISP_PIX, "media_disp_pix_root", 0x2400, VIDEO_SEL, },
+ { IMX93_CLK_CAM_PIX, "cam_pix_root", 0x2480, VIDEO_SEL, },
+ { IMX93_CLK_MIPI_TEST_BYTE, "mipi_test_byte_root", 0x2500, VIDEO_SEL, },
+ { IMX93_CLK_MIPI_PHY_CFG, "mipi_phy_cfg_root", 0x2580, VIDEO_SEL, },
+ { IMX93_CLK_ADC, "adc_root", 0x2700, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_PDM, "pdm_root", 0x2780, AUDIO_SEL, },
+ { IMX93_CLK_TSTMR1, "tstmr1_root", 0x2800, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_TSTMR2, "tstmr2_root", 0x2880, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_MQS1, "mqs1_root", 0x2900, AUDIO_SEL, },
+ { IMX93_CLK_MQS2, "mqs2_root", 0x2980, AUDIO_SEL, },
+ { IMX93_CLK_AUDIO_XCVR, "audio_xcvr_root", 0x2a00, NON_IO_SEL, },
+ { IMX93_CLK_SPDIF, "spdif_root", 0x2a80, AUDIO_SEL, },
+ { IMX93_CLK_ENET, "enet_root", 0x2b00, NON_IO_SEL, },
+ { IMX93_CLK_ENET_TIMER1, "enet_timer1_root", 0x2b80, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_ENET_TIMER2, "enet_timer2_root", 0x2c00, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_ENET_REF, "enet_ref_root", 0x2c80, NON_IO_SEL, },
+ { IMX93_CLK_ENET_REF_PHY, "enet_ref_phy_root", 0x2d00, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_I3C1_SLOW, "i3c1_slow_root", 0x2d80, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_I3C2_SLOW, "i3c2_slow_root", 0x2e00, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_USB_PHY_BURUNIN, "usb_phy_root", 0x2e80, LOW_SPEED_IO_SEL, },
+ { IMX93_CLK_PAL_CAME_SCAN, "pal_came_scan_root", 0x2f00, MISC_SEL, }
+};
+
+static const struct imx93_clk_ccgr {
+ u32 clk;
+ char *name;
+ char *parent_name;
+ u32 off;
+ unsigned long flags;
+ u32 *shared_count;
+} ccgr_array[] = {
+ { IMX93_CLK_A55_GATE, "a55_alt", "a55_alt_root", 0x8000, },
+ /* M33 critical clk for system run */
+ { IMX93_CLK_CM33_GATE, "cm33", "m33_root", 0x8040, CLK_IS_CRITICAL },
+ { IMX93_CLK_ADC1_GATE, "adc1", "adc_root", 0x82c0, },
+ { IMX93_CLK_WDOG1_GATE, "wdog1", "osc_24m", 0x8300, },
+ { IMX93_CLK_WDOG2_GATE, "wdog2", "osc_24m", 0x8340, },
+ { IMX93_CLK_WDOG3_GATE, "wdog3", "osc_24m", 0x8380, },
+ { IMX93_CLK_WDOG4_GATE, "wdog4", "osc_24m", 0x83c0, },
+ { IMX93_CLK_WDOG5_GATE, "wdog5", "osc_24m", 0x8400, },
+ { IMX93_CLK_SEMA1_GATE, "sema1", "bus_aon_root", 0x8440, },
+ { IMX93_CLK_SEMA2_GATE, "sema2", "bus_wakeup_root", 0x8480, },
+ { IMX93_CLK_MU1_A_GATE, "mu1_a", "bus_aon_root", 0x84c0, CLK_IGNORE_UNUSED },
+ { IMX93_CLK_MU2_A_GATE, "mu2_a", "bus_wakeup_root", 0x84c0, CLK_IGNORE_UNUSED },
+ { IMX93_CLK_MU1_B_GATE, "mu1_b", "bus_aon_root", 0x8500, 0, &share_count_mub },
+ { IMX93_CLK_MU2_B_GATE, "mu2_b", "bus_wakeup_root", 0x8500, 0, &share_count_mub },
+ { IMX93_CLK_EDMA1_GATE, "edma1", "m33_root", 0x8540, },
+ { IMX93_CLK_EDMA2_GATE, "edma2", "wakeup_axi_root", 0x8580, },
+ { IMX93_CLK_FLEXSPI1_GATE, "flexspi1", "flexspi1_root", 0x8640, },
+ { IMX93_CLK_GPIO1_GATE, "gpio1", "m33_root", 0x8880, },
+ { IMX93_CLK_GPIO2_GATE, "gpio2", "bus_wakeup_root", 0x88c0, },
+ { IMX93_CLK_GPIO3_GATE, "gpio3", "bus_wakeup_root", 0x8900, },
+ { IMX93_CLK_GPIO4_GATE, "gpio4", "bus_wakeup_root", 0x8940, },
+ { IMX93_CLK_FLEXIO1_GATE, "flexio1", "flexio1_root", 0x8980, },
+ { IMX93_CLK_FLEXIO2_GATE, "flexio2", "flexio2_root", 0x89c0, },
+ { IMX93_CLK_LPIT1_GATE, "lpit1", "bus_aon_root", 0x8a00, },
+ { IMX93_CLK_LPIT2_GATE, "lpit2", "bus_wakeup_root", 0x8a40, },
+ { IMX93_CLK_LPTMR1_GATE, "lptmr1", "lptmr1_root", 0x8a80, },
+ { IMX93_CLK_LPTMR2_GATE, "lptmr2", "lptmr2_root", 0x8ac0, },
+ { IMX93_CLK_TPM1_GATE, "tpm1", "bus_aon_root", 0x8b00, },
+ { IMX93_CLK_TPM2_GATE, "tpm2", "tpm2_root", 0x8b40, },
+ { IMX93_CLK_TPM3_GATE, "tpm3", "bus_wakeup_root", 0x8b80, },
+ { IMX93_CLK_TPM4_GATE, "tpm4", "tpm4_root", 0x8bc0, },
+ { IMX93_CLK_TPM5_GATE, "tpm5", "tpm5_root", 0x8c00, },
+ { IMX93_CLK_TPM6_GATE, "tpm6", "tpm6_root", 0x8c40, },
+ { IMX93_CLK_CAN1_GATE, "can1", "can1_root", 0x8c80, },
+ { IMX93_CLK_CAN2_GATE, "can2", "can2_root", 0x8cc0, },
+ { IMX93_CLK_LPUART1_GATE, "lpuart1", "lpuart1_root", 0x8d00, },
+ { IMX93_CLK_LPUART2_GATE, "lpuart2", "lpuart2_root", 0x8d40, },
+ { IMX93_CLK_LPUART3_GATE, "lpuart3", "lpuart3_root", 0x8d80, },
+ { IMX93_CLK_LPUART4_GATE, "lpuart4", "lpuart4_root", 0x8dc0, },
+ { IMX93_CLK_LPUART5_GATE, "lpuart5", "lpuart5_root", 0x8e00, },
+ { IMX93_CLK_LPUART6_GATE, "lpuart6", "lpuart6_root", 0x8e40, },
+ { IMX93_CLK_LPUART7_GATE, "lpuart7", "lpuart7_root", 0x8e80, },
+ { IMX93_CLK_LPUART8_GATE, "lpuart8", "lpuart8_root", 0x8ec0, },
+ { IMX93_CLK_LPI2C1_GATE, "lpi2c1", "lpi2c1_root", 0x8f00, },
+ { IMX93_CLK_LPI2C2_GATE, "lpi2c2", "lpi2c2_root", 0x8f40, },
+ { IMX93_CLK_LPI2C3_GATE, "lpi2c3", "lpi2c3_root", 0x8f80, },
+ { IMX93_CLK_LPI2C4_GATE, "lpi2c4", "lpi2c4_root", 0x8fc0, },
+ { IMX93_CLK_LPI2C5_GATE, "lpi2c5", "lpi2c5_root", 0x9000, },
+ { IMX93_CLK_LPI2C6_GATE, "lpi2c6", "lpi2c6_root", 0x9040, },
+ { IMX93_CLK_LPI2C7_GATE, "lpi2c7", "lpi2c7_root", 0x9080, },
+ { IMX93_CLK_LPI2C8_GATE, "lpi2c8", "lpi2c8_root", 0x90c0, },
+ { IMX93_CLK_LPSPI1_GATE, "lpspi1", "lpspi1_root", 0x9100, },
+ { IMX93_CLK_LPSPI2_GATE, "lpspi2", "lpspi2_root", 0x9140, },
+ { IMX93_CLK_LPSPI3_GATE, "lpspi3", "lpspi3_root", 0x9180, },
+ { IMX93_CLK_LPSPI4_GATE, "lpspi4", "lpspi4_root", 0x91c0, },
+ { IMX93_CLK_LPSPI5_GATE, "lpspi5", "lpspi5_root", 0x9200, },
+ { IMX93_CLK_LPSPI6_GATE, "lpspi6", "lpspi6_root", 0x9240, },
+ { IMX93_CLK_LPSPI7_GATE, "lpspi7", "lpspi7_root", 0x9280, },
+ { IMX93_CLK_LPSPI8_GATE, "lpspi8", "lpspi8_root", 0x92c0, },
+ { IMX93_CLK_I3C1_GATE, "i3c1", "i3c1_root", 0x9300, },
+ { IMX93_CLK_I3C2_GATE, "i3c2", "i3c2_root", 0x9340, },
+ { IMX93_CLK_USDHC1_GATE, "usdhc1", "usdhc1_root", 0x9380, },
+ { IMX93_CLK_USDHC2_GATE, "usdhc2", "usdhc2_root", 0x93c0, },
+ { IMX93_CLK_USDHC3_GATE, "usdhc3", "usdhc3_root", 0x9400, },
+ { IMX93_CLK_SAI1_GATE, "sai1", "sai1_root", 0x9440, 0, &share_count_sai1},
+ { IMX93_CLK_SAI1_IPG, "sai1_ipg_clk", "bus_aon_root", 0x9440, 0, &share_count_sai1},
+ { IMX93_CLK_SAI2_GATE, "sai2", "sai2_root", 0x9480, 0, &share_count_sai2},
+ { IMX93_CLK_SAI2_IPG, "sai2_ipg_clk", "bus_wakeup_root", 0x9480, 0, &share_count_sai2},
+ { IMX93_CLK_SAI3_GATE, "sai3", "sai3_root", 0x94c0, 0, &share_count_sai3},
+ { IMX93_CLK_SAI3_IPG, "sai3_ipg_clk", "bus_wakeup_root", 0x94c0, 0, &share_count_sai3},
+ { IMX93_CLK_MIPI_CSI_GATE, "mipi_csi", "media_apb_root", 0x9580, },
+ { IMX93_CLK_MIPI_DSI_GATE, "mipi_dsi", "media_apb_root", 0x95c0, },
+ { IMX93_CLK_LVDS_GATE, "lvds", "media_ldb_root", 0x9600, },
+ { IMX93_CLK_LCDIF_GATE, "lcdif", "media_apb_root", 0x9640, },
+ { IMX93_CLK_PXP_GATE, "pxp", "media_apb_root", 0x9680, },
+ { IMX93_CLK_ISI_GATE, "isi", "media_apb_root", 0x96c0, },
+ { IMX93_CLK_NIC_MEDIA_GATE, "nic_media", "media_axi_root", 0x9700, },
+ { IMX93_CLK_USB_CONTROLLER_GATE, "usb_controller", "hsio_root", 0x9a00, },
+ { IMX93_CLK_USB_TEST_60M_GATE, "usb_test_60m", "hsio_usb_test_60m_root", 0x9a40, },
+ { IMX93_CLK_HSIO_TROUT_24M_GATE, "hsio_trout_24m", "osc_24m", 0x9a80, },
+ { IMX93_CLK_PDM_GATE, "pdm", "pdm_root", 0x9ac0, 0, &share_count_pdm},
+ { IMX93_CLK_PDM_IPG, "pdm_ipg_clk", "bus_aon_root", 0x9ac0, 0, &share_count_pdm},
+ { IMX93_CLK_MQS1_GATE, "mqs1", "sai1_root", 0x9b00, },
+ { IMX93_CLK_MQS2_GATE, "mqs2", "sai3_root", 0x9b40, },
+ { IMX93_CLK_AUD_XCVR_GATE, "aud_xcvr", "audio_xcvr_root", 0x9b80, },
+ { IMX93_CLK_SPDIF_GATE, "spdif", "spdif_root", 0x9c00, },
+ { IMX93_CLK_HSIO_32K_GATE, "hsio_32k", "osc_32k", 0x9dc0, },
+ { IMX93_CLK_ENET1_GATE, "enet1", "wakeup_axi_root", 0x9e00, },
+ { IMX93_CLK_ENET_QOS_GATE, "enet_qos", "wakeup_axi_root", 0x9e40, },
+ /* Critical because clk accessed during CPU idle */
+ { IMX93_CLK_SYS_CNT_GATE, "sys_cnt", "osc_24m", 0x9e80, CLK_IS_CRITICAL},
+ { IMX93_CLK_TSTMR1_GATE, "tstmr1", "bus_aon_root", 0x9ec0, },
+ { IMX93_CLK_TSTMR2_GATE, "tstmr2", "bus_wakeup_root", 0x9f00, },
+ { IMX93_CLK_TMC_GATE, "tmc", "osc_24m", 0x9f40, },
+ { IMX93_CLK_PMRO_GATE, "pmro", "osc_24m", 0x9f80, }
+};
+
+static struct clk_onecell_data clk_data;
+static struct clk *clks[IMX93_CLK_END];
+
+static int imx93_clocks_probe(struct device_node *np)
+{
+ struct device_node *anatop_np;
+ const struct imx93_clk_root *root;
+ const struct imx93_clk_ccgr *ccgr;
+ void __iomem *base, *anatop_base;
+ int i, ret;
+
+ clk_data.clk_num = IMX93_CLK_END;
+ clk_data.clks = clks;
+
+ clks[IMX93_CLK_DUMMY] = clk_fixed("dummy", 0);
+ clks[IMX93_CLK_24M] = of_clk_get_by_name(np, "osc_24m");
+ clks[IMX93_CLK_32K] = of_clk_get_by_name(np, "osc_32k");
+ clks[IMX93_CLK_EXT1] = of_clk_get_by_name(np, "clk_ext1");
+
+ clks[IMX93_CLK_SYS_PLL_PFD0] = clk_fixed("sys_pll_pfd0", 1000000000);
+ clks[IMX93_CLK_SYS_PLL_PFD0_DIV2] = imx_clk_hw_fixed_factor("sys_pll_pfd0_div2",
+ "sys_pll_pfd0", 1, 2);
+ clks[IMX93_CLK_SYS_PLL_PFD1] = clk_fixed("sys_pll_pfd1", 800000000);
+ clks[IMX93_CLK_SYS_PLL_PFD1_DIV2] = imx_clk_hw_fixed_factor("sys_pll_pfd1_div2",
+ "sys_pll_pfd1", 1, 2);
+ clks[IMX93_CLK_SYS_PLL_PFD2] = clk_fixed("sys_pll_pfd2", 625000000);
+ clks[IMX93_CLK_SYS_PLL_PFD2_DIV2] = imx_clk_hw_fixed_factor("sys_pll_pfd2_div2",
+ "sys_pll_pfd2", 1, 2);
+
+ anatop_np = of_find_compatible_node(NULL, NULL, "fsl,imx93-anatop");
+ anatop_base = of_iomap(anatop_np, 0);
+ if (WARN_ON(IS_ERR(anatop_base)))
+ return PTR_ERR(anatop_base);
+
+ clks[IMX93_CLK_ARM_PLL] = imx_clk_fracn_gppll_integer("arm_pll", "osc_24m",
+ anatop_base + 0x1000,
+ &imx_fracn_gppll_integer);
+ clks[IMX93_CLK_AUDIO_PLL] = imx_clk_fracn_gppll("audio_pll", "osc_24m", anatop_base + 0x1200,
+ &imx_fracn_gppll);
+ clks[IMX93_CLK_VIDEO_PLL] = imx_clk_fracn_gppll("video_pll", "osc_24m", anatop_base + 0x1400,
+ &imx_fracn_gppll);
+
+ base = of_iomap(np, 0);
+ if (WARN_ON(IS_ERR(base)))
+ return PTR_ERR(base);
+
+ for (i = 0; i < ARRAY_SIZE(root_array); i++) {
+ root = &root_array[i];
+ clks[root->clk] = imx93_clk_composite_flags(root->name,
+ parent_names[root->sel],
+ 4, base + root->off, 3,
+ root->flags);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(ccgr_array); i++) {
+ ccgr = &ccgr_array[i];
+ clks[ccgr->clk] = imx93_clk_gate(NULL, ccgr->name, ccgr->parent_name,
+ ccgr->flags, base + ccgr->off, 0, 1, 1, 3,
+ ccgr->shared_count);
+ }
+
+ clks[IMX93_CLK_A55_SEL] = imx_clk_hw_mux2("a55_sel", base + 0x4820, 0, 1, a55_core_sels,
+ ARRAY_SIZE(a55_core_sels));
+ clks[IMX93_CLK_A55_CORE] = imx_clk_hw_cpu("a55_core", "a55_sel",
+ clks[IMX93_CLK_A55_SEL],
+ clks[IMX93_CLK_A55_SEL],
+ clks[IMX93_CLK_ARM_PLL],
+ clks[IMX93_CLK_A55_GATE]);
+
+ imx_check_clocks(clks, IMX93_CLK_END);
+
+ ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+CLK_OF_DECLARE(imx93, "fsl,imx93-ccm", imx93_clocks_probe);
diff --git a/drivers/clk/imx/clk-pfd.c b/drivers/clk/imx/clk-pfd.c
index eb2b1700ae..d16e39f85c 100644
--- a/drivers/clk/imx/clk-pfd.c
+++ b/drivers/clk/imx/clk-pfd.c
@@ -12,7 +12,7 @@
#include <linux/clkdev.h>
#include <linux/err.h>
#include <malloc.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
@@ -27,37 +27,37 @@
* register has SET, CLR and TOG registers at offset 0x4 0x8 and 0xc.
*/
struct clk_pfd {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *reg;
u8 idx;
const char *parent;
};
-#define to_clk_pfd(_clk) container_of(_clk, struct clk_pfd, clk)
+#define to_clk_pfd(_hw) container_of(_hw, struct clk_pfd, hw)
#define SET 0x4
#define CLR 0x8
#define OTG 0xc
-static int clk_pfd_enable(struct clk *clk)
+static int clk_pfd_enable(struct clk_hw *hw)
{
- struct clk_pfd *pfd = to_clk_pfd(clk);
+ struct clk_pfd *pfd = to_clk_pfd(hw);
writel(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + CLR);
return 0;
}
-static void clk_pfd_disable(struct clk *clk)
+static void clk_pfd_disable(struct clk_hw *hw)
{
- struct clk_pfd *pfd = to_clk_pfd(clk);
+ struct clk_pfd *pfd = to_clk_pfd(hw);
writel(1 << ((pfd->idx + 1) * 8 - 1), pfd->reg + SET);
}
-static unsigned long clk_pfd_recalc_rate(struct clk *clk,
+static unsigned long clk_pfd_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_pfd *pfd = to_clk_pfd(clk);
+ struct clk_pfd *pfd = to_clk_pfd(hw);
u64 tmp = parent_rate;
u8 frac = (readl(pfd->reg) >> (pfd->idx * 8)) & 0x3f;
@@ -67,7 +67,7 @@ static unsigned long clk_pfd_recalc_rate(struct clk *clk,
return tmp;
}
-static long clk_pfd_round_rate(struct clk *clk, unsigned long rate,
+static long clk_pfd_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
u64 tmp = *prate;
@@ -87,10 +87,10 @@ static long clk_pfd_round_rate(struct clk *clk, unsigned long rate,
return tmp;
}
-static int clk_pfd_set_rate(struct clk *clk, unsigned long rate,
+static int clk_pfd_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_pfd *pfd = to_clk_pfd(clk);
+ struct clk_pfd *pfd = to_clk_pfd(hw);
u64 tmp = parent_rate;
u8 frac;
@@ -127,16 +127,16 @@ struct clk *imx_clk_pfd(const char *name, const char *parent,
pfd->reg = reg;
pfd->idx = idx;
pfd->parent = parent;
- pfd->clk.name = name;
- pfd->clk.ops = &clk_pfd_ops;
- pfd->clk.parent_names = &pfd->parent;
- pfd->clk.num_parents = 1;
+ pfd->hw.clk.name = name;
+ pfd->hw.clk.ops = &clk_pfd_ops;
+ pfd->hw.clk.parent_names = &pfd->parent;
+ pfd->hw.clk.num_parents = 1;
- ret = clk_register(&pfd->clk);
+ ret = bclk_register(&pfd->hw.clk);
if (ret) {
free(pfd);
return ERR_PTR(ret);
}
- return &pfd->clk;
+ return &pfd->hw.clk;
}
diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c
index 91e9624a60..86286448e9 100644
--- a/drivers/clk/imx/clk-pll14xx.c
+++ b/drivers/clk/imx/clk-pll14xx.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2017-2018 NXP.
*/
@@ -14,7 +14,7 @@
#include <malloc.h>
#include <clock.h>
#include <soc/imx8m/clk-early.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
@@ -37,7 +37,7 @@
#define LOCK_TIMEOUT_US 10000
struct clk_pll14xx {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *base;
enum imx_pll14xx_type type;
const struct imx_pll14xx_rate_table *rate_table;
@@ -45,7 +45,7 @@ struct clk_pll14xx {
const char *parent;
};
-#define to_clk_pll14xx(clk) container_of(clk, struct clk_pll14xx, clk)
+#define to_clk_pll14xx(_hw) container_of(_hw, struct clk_pll14xx, hw)
static const struct imx_pll14xx_rate_table imx_pll1416x_tbl[] = {
PLL_1416X_RATE(1800000000U, 225, 3, 0),
@@ -92,10 +92,10 @@ static const struct imx_pll14xx_rate_table *imx_get_pll_settings(
return NULL;
}
-static long clk_pll14xx_round_rate(struct clk *clk, unsigned long rate,
+static long clk_pll14xx_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
- struct clk_pll14xx *pll = to_clk_pll14xx(clk);
+ struct clk_pll14xx *pll = to_clk_pll14xx(hw);
const struct imx_pll14xx_rate_table *rate_table = pll->rate_table;
int i;
@@ -108,10 +108,10 @@ static long clk_pll14xx_round_rate(struct clk *clk, unsigned long rate,
return rate_table[i - 1].rate;
}
-static unsigned long clk_pll1416x_recalc_rate(struct clk *clk,
+static unsigned long clk_pll1416x_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_pll14xx *pll = to_clk_pll14xx(clk);
+ struct clk_pll14xx *pll = to_clk_pll14xx(hw);
u32 mdiv, pdiv, sdiv, pll_div;
u64 fvco = parent_rate;
@@ -126,10 +126,10 @@ static unsigned long clk_pll1416x_recalc_rate(struct clk *clk,
return fvco;
}
-static unsigned long clk_pll1443x_recalc_rate(struct clk *clk,
+static unsigned long clk_pll1443x_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_pll14xx *pll = to_clk_pll14xx(clk);
+ struct clk_pll14xx *pll = to_clk_pll14xx(hw);
u32 mdiv, pdiv, sdiv, pll_div_ctl0, pll_div_ctl1;
short int kdiv;
u64 fvco = parent_rate;
@@ -169,10 +169,10 @@ static int clk_pll14xx_wait_lock(struct clk_pll14xx *pll)
LOCK_TIMEOUT_US);
}
-static int clk_pll1416x_set_rate(struct clk *clk, unsigned long drate,
+static int clk_pll1416x_set_rate(struct clk_hw *hw, unsigned long drate,
unsigned long prate)
{
- struct clk_pll14xx *pll = to_clk_pll14xx(clk);
+ struct clk_pll14xx *pll = to_clk_pll14xx(hw);
const struct imx_pll14xx_rate_table *rate;
u32 tmp, div_val;
int ret;
@@ -180,7 +180,7 @@ static int clk_pll1416x_set_rate(struct clk *clk, unsigned long drate,
rate = imx_get_pll_settings(pll, drate);
if (!rate) {
pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
- drate, clk->name);
+ drate, hw->clk.name);
return -EINVAL;
}
@@ -239,7 +239,7 @@ int clk_pll1416x_early_set_rate(void __iomem *base, unsigned long drate,
unsigned long prate)
{
struct clk_pll14xx pll = {
- .clk = {
+ .hw.clk = {
.name = "pll1416x",
},
.base = base,
@@ -247,13 +247,14 @@ int clk_pll1416x_early_set_rate(void __iomem *base, unsigned long drate,
.rate_count = ARRAY_SIZE(imx_pll1416x_tbl),
};
- return clk_pll1416x_set_rate(&pll.clk, drate, prate);
+ return clk_pll1416x_set_rate(&pll.hw, drate, prate);
}
-static int clk_pll1443x_set_rate(struct clk *clk, unsigned long drate,
+static int clk_pll1443x_set_rate(struct clk_hw *hw, unsigned long drate,
unsigned long prate)
{
- struct clk_pll14xx *pll = to_clk_pll14xx(clk);
+ struct clk_pll14xx *pll = to_clk_pll14xx(hw);
+ struct clk *clk = clk_hw_to_clk(hw);
const struct imx_pll14xx_rate_table *rate;
u32 tmp, div_val;
int ret;
@@ -316,9 +317,9 @@ static int clk_pll1443x_set_rate(struct clk *clk, unsigned long drate,
return 0;
}
-static int clk_pll14xx_prepare(struct clk *clk)
+static int clk_pll14xx_prepare(struct clk_hw *hw)
{
- struct clk_pll14xx *pll = to_clk_pll14xx(clk);
+ struct clk_pll14xx *pll = to_clk_pll14xx(hw);
u32 val;
int ret;
@@ -344,9 +345,9 @@ static int clk_pll14xx_prepare(struct clk *clk)
return 0;
}
-static int clk_pll14xx_is_prepared(struct clk *clk)
+static int clk_pll14xx_is_prepared(struct clk_hw *hw)
{
- struct clk_pll14xx *pll = to_clk_pll14xx(clk);
+ struct clk_pll14xx *pll = to_clk_pll14xx(hw);
u32 val;
val = readl(pll->base + GNRL_CTL);
@@ -354,12 +355,11 @@ static int clk_pll14xx_is_prepared(struct clk *clk)
return (val & RST_MASK) ? 1 : 0;
}
-static void clk_pll14xx_unprepare(struct clk *clk)
+static void clk_pll14xx_unprepare(struct clk_hw *hw)
{
- struct clk_pll14xx *pll = to_clk_pll14xx(clk);
+ struct clk_pll14xx *pll = to_clk_pll14xx(hw);
u32 val;
-printf("%s %p\n", __func__, pll);
-printf("%s %p\n", __func__, pll->base);
+
/*
* Set RST to 0, power down mode is enabled and
* every digital block is reset
@@ -404,7 +404,7 @@ struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
if (!pll)
return ERR_PTR(-ENOMEM);
- clk = &pll->clk;
+ clk = &pll->hw.clk;
pll->parent = parent_name;
clk->name = name;
@@ -436,7 +436,7 @@ struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
val &= ~BYPASS_MASK;
writel(val, pll->base + GNRL_CTL);
- ret = clk_register(clk);
+ ret = bclk_register(clk);
if (ret) {
free(pll);
return ERR_PTR(ret);
diff --git a/drivers/clk/imx/clk-pllv1.c b/drivers/clk/imx/clk-pllv1.c
index 9b5d28f22f..62afa2b6b2 100644
--- a/drivers/clk/imx/clk-pllv1.c
+++ b/drivers/clk/imx/clk-pllv1.c
@@ -8,20 +8,29 @@
#include <linux/clkdev.h>
#include <linux/err.h>
#include <malloc.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
+#define MFN_BITS (10)
+#define MFN_SIGN (BIT(MFN_BITS - 1))
+#define MFN_MASK (MFN_SIGN - 1)
+
struct clk_pllv1 {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *reg;
const char *parent;
};
-static unsigned long clk_pllv1_recalc_rate(struct clk *clk,
+static inline bool mfn_is_negative(unsigned int mfn)
+{
+ return mfn & MFN_SIGN;
+}
+
+static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_pllv1 *pll = container_of(clk, struct clk_pllv1, clk);
+ struct clk_pllv1 *pll = container_of(hw, struct clk_pllv1, hw);
unsigned long long ll;
int mfn_abs;
unsigned int mfi, mfn, mfd, pd;
@@ -50,7 +59,7 @@ static unsigned long clk_pllv1_recalc_rate(struct clk *clk,
ll = (unsigned long long)freq * mfn_abs;
do_div(ll, mfd + 1);
- if (mfn < 0)
+ if (mfn_is_negative(mfn))
ll = (freq * mfi) - ll;
else
ll = (freq * mfi) + ll;
@@ -70,16 +79,16 @@ struct clk *imx_clk_pllv1(const char *name, const char *parent,
pll->parent = parent;
pll->reg = base;
- pll->clk.ops = &clk_pllv1_ops;
- pll->clk.name = name;
- pll->clk.parent_names = &pll->parent;
- pll->clk.num_parents = 1;
+ pll->hw.clk.ops = &clk_pllv1_ops;
+ pll->hw.clk.name = name;
+ pll->hw.clk.parent_names = &pll->parent;
+ pll->hw.clk.num_parents = 1;
- ret = clk_register(&pll->clk);
+ ret = bclk_register(&pll->hw.clk);
if (ret) {
free(pll);
return ERR_PTR(ret);
}
- return &pll->clk;
+ return &pll->hw.clk;
}
diff --git a/drivers/clk/imx/clk-pllv2.c b/drivers/clk/imx/clk-pllv2.c
index 56005ca725..d997e465d5 100644
--- a/drivers/clk/imx/clk-pllv2.c
+++ b/drivers/clk/imx/clk-pllv2.c
@@ -8,7 +8,7 @@
#include <linux/clkdev.h>
#include <linux/err.h>
#include <malloc.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
@@ -70,7 +70,7 @@
#define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */
struct clk_pllv2 {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *reg;
const char *parent;
};
@@ -110,12 +110,12 @@ static unsigned long __clk_pllv2_recalc_rate(unsigned long parent_rate,
return temp;
}
-static unsigned long clk_pllv2_recalc_rate(struct clk *clk,
+static unsigned long clk_pllv2_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
u32 dp_op, dp_mfd, dp_mfn, dp_ctl;
void __iomem *pllbase;
- struct clk_pllv2 *pll = container_of(clk, struct clk_pllv2, clk);
+ struct clk_pllv2 *pll = container_of(hw, struct clk_pllv2, hw);
pllbase = pll->reg;
@@ -156,10 +156,10 @@ static int __clk_pllv2_set_rate(unsigned long rate, unsigned long parent_rate,
return 0;
}
-static int clk_pllv2_set_rate(struct clk *clk, unsigned long rate,
+static int clk_pllv2_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_pllv2 *pll = container_of(clk, struct clk_pllv2, clk);
+ struct clk_pllv2 *pll = container_of(hw, struct clk_pllv2, hw);
void __iomem *pllbase;
u32 dp_ctl, dp_op, dp_mfd, dp_mfn;
int ret;
@@ -181,7 +181,7 @@ static int clk_pllv2_set_rate(struct clk *clk, unsigned long rate,
return 0;
}
-static long clk_pllv2_round_rate(struct clk *clk, unsigned long rate,
+static long clk_pllv2_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
u32 dp_op, dp_mfd, dp_mfn;
@@ -205,16 +205,16 @@ struct clk *imx_clk_pllv2(const char *name, const char *parent,
pll->parent = parent;
pll->reg = base;
- pll->clk.ops = &clk_pllv2_ops;
- pll->clk.name = name;
- pll->clk.parent_names = &pll->parent;
- pll->clk.num_parents = 1;
+ pll->hw.clk.ops = &clk_pllv2_ops;
+ pll->hw.clk.name = name;
+ pll->hw.clk.parent_names = &pll->parent;
+ pll->hw.clk.num_parents = 1;
- ret = clk_register(&pll->clk);
+ ret = bclk_register(&pll->hw.clk);
if (ret) {
free(pll);
return ERR_PTR(ret);
}
- return &pll->clk;
+ return &pll->hw.clk;
}
diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c
index e10b61b040..cb1d65058f 100644
--- a/drivers/clk/imx/clk-pllv3.c
+++ b/drivers/clk/imx/clk-pllv3.c
@@ -9,7 +9,7 @@
#include <linux/err.h>
#include <malloc.h>
#include <clock.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
@@ -25,7 +25,7 @@
#define IMX7_ENET_PLL_POWER (0x1 << 5)
struct clk_pllv3 {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *base;
bool powerup_set;
u32 div_mask;
@@ -35,11 +35,11 @@ struct clk_pllv3 {
u32 power_bit;
};
-#define to_clk_pllv3(_clk) container_of(_clk, struct clk_pllv3, clk)
+#define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw)
-static int clk_pllv3_enable(struct clk *clk)
+static int clk_pllv3_enable(struct clk_hw *hw)
{
- struct clk_pllv3 *pll = to_clk_pllv3(clk);
+ struct clk_pllv3 *pll = to_clk_pllv3(hw);
u32 val;
int timeout = 10000;
@@ -66,9 +66,9 @@ static int clk_pllv3_enable(struct clk *clk)
return 0;
}
-static void clk_pllv3_disable(struct clk *clk)
+static void clk_pllv3_disable(struct clk_hw *hw)
{
- struct clk_pllv3 *pll = to_clk_pllv3(clk);
+ struct clk_pllv3 *pll = to_clk_pllv3(hw);
u32 val;
val = readl(pll->base);
@@ -82,16 +82,16 @@ static void clk_pllv3_disable(struct clk *clk)
writel(val, pll->base);
}
-static unsigned long clk_pllv3_recalc_rate(struct clk *clk,
+static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_pllv3 *pll = to_clk_pllv3(clk);
+ struct clk_pllv3 *pll = to_clk_pllv3(hw);
u32 div = (readl(pll->base) >> pll->div_shift) & pll->div_mask;
return (div == 1) ? parent_rate * 22 : parent_rate * 20;
}
-static long clk_pllv3_round_rate(struct clk *clk, unsigned long rate,
+static long clk_pllv3_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
unsigned long parent_rate = *prate;
@@ -100,10 +100,10 @@ static long clk_pllv3_round_rate(struct clk *clk, unsigned long rate,
parent_rate * 20;
}
-static int clk_pllv3_set_rate(struct clk *clk, unsigned long rate,
+static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_pllv3 *pll = to_clk_pllv3(clk);
+ struct clk_pllv3 *pll = to_clk_pllv3(hw);
u32 val, div;
if (rate == parent_rate * 22)
@@ -129,16 +129,16 @@ static const struct clk_ops clk_pllv3_ops = {
.set_rate = clk_pllv3_set_rate,
};
-static unsigned long clk_pllv3_sys_recalc_rate(struct clk *clk,
+static unsigned long clk_pllv3_sys_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_pllv3 *pll = to_clk_pllv3(clk);
+ struct clk_pllv3 *pll = to_clk_pllv3(hw);
u32 div = readl(pll->base) & pll->div_mask;
return parent_rate * div / 2;
}
-static long clk_pllv3_sys_round_rate(struct clk *clk, unsigned long rate,
+static long clk_pllv3_sys_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
unsigned long parent_rate = *prate;
@@ -155,10 +155,10 @@ static long clk_pllv3_sys_round_rate(struct clk *clk, unsigned long rate,
return parent_rate * div / 2;
}
-static int clk_pllv3_sys_set_rate(struct clk *clk, unsigned long rate,
+static int clk_pllv3_sys_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_pllv3 *pll = to_clk_pllv3(clk);
+ struct clk_pllv3 *pll = to_clk_pllv3(hw);
unsigned long min_rate = parent_rate * 54 / 2;
unsigned long max_rate = parent_rate * 108 / 2;
u32 val, div;
@@ -183,10 +183,11 @@ static const struct clk_ops clk_pllv3_sys_ops = {
.set_rate = clk_pllv3_sys_set_rate,
};
-static unsigned long clk_pllv3_av_recalc_rate(struct clk *clk,
+static unsigned long clk_pllv3_av_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_pllv3 *pll = to_clk_pllv3(clk);
+ struct clk_pllv3 *pll = to_clk_pllv3(hw);
+
u32 mfn = readl(pll->base + PLL_NUM_OFFSET);
u32 mfd = readl(pll->base + PLL_DENOM_OFFSET);
u32 div = readl(pll->base) & pll->div_mask;
@@ -194,7 +195,7 @@ static unsigned long clk_pllv3_av_recalc_rate(struct clk *clk,
return (parent_rate * div) + ((parent_rate / mfd) * mfn);
}
-static long clk_pllv3_av_round_rate(struct clk *clk, unsigned long rate,
+static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
unsigned long parent_rate = *prate;
@@ -218,10 +219,11 @@ static long clk_pllv3_av_round_rate(struct clk *clk, unsigned long rate,
return parent_rate * div + parent_rate / mfd * mfn;
}
-static int clk_pllv3_av_set_rate(struct clk *clk, unsigned long rate,
+static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_pllv3 *pll = to_clk_pllv3(clk);
+ struct clk_pllv3 *pll = to_clk_pllv3(hw);
+
unsigned long min_rate = parent_rate * 27;
unsigned long max_rate = parent_rate * 54;
u32 val, div;
@@ -255,10 +257,10 @@ static const struct clk_ops clk_pllv3_av_ops = {
.set_rate = clk_pllv3_av_set_rate,
};
-static unsigned long clk_pllv3_enet_recalc_rate(struct clk *clk,
+static unsigned long clk_pllv3_enet_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_pllv3 *pll = to_clk_pllv3(clk);
+ struct clk_pllv3 *pll = to_clk_pllv3(hw);
return pll->ref_clock;
}
@@ -274,10 +276,10 @@ static const struct clk_ops clk_pllv3_mlb_ops = {
.disable = clk_pllv3_disable,
};
-static unsigned long clk_pllv3_sys_vf610_recalc_rate(struct clk *clk,
+static unsigned long clk_pllv3_sys_vf610_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_pllv3 *pll = to_clk_pllv3(clk);
+ struct clk_pllv3 *pll = to_clk_pllv3(hw);
u32 mfn = readl(pll->base + SYS_VF610_PLL_OFFSET + PLL_NUM_OFFSET);
u32 mfd = readl(pll->base + SYS_VF610_PLL_OFFSET + PLL_DENOM_OFFSET);
@@ -286,7 +288,7 @@ static unsigned long clk_pllv3_sys_vf610_recalc_rate(struct clk *clk,
return (parent_rate * div) + ((parent_rate / mfd) * mfn);
}
-static long clk_pllv3_sys_vf610_round_rate(struct clk *clk, unsigned long rate,
+static long clk_pllv3_sys_vf610_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
unsigned long parent_rate = *prate;
@@ -308,10 +310,10 @@ static long clk_pllv3_sys_vf610_round_rate(struct clk *clk, unsigned long rate,
return parent_rate * 20 + parent_rate / mfd * mfn;
}
-static int clk_pllv3_sys_vf610_set_rate(struct clk *clk, unsigned long rate,
+static int clk_pllv3_sys_vf610_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_pllv3 *pll = to_clk_pllv3(clk);
+ struct clk_pllv3 *pll = to_clk_pllv3(hw);
unsigned long min_rate = parent_rate * 20;
unsigned long max_rate = 528000000;
u32 val;
@@ -400,20 +402,20 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
pll->base = base;
pll->div_mask = div_mask;
pll->parent = parent;
- pll->clk.ops = ops;
- pll->clk.name = name;
- pll->clk.parent_names = &pll->parent;
- pll->clk.num_parents = 1;
+ pll->hw.clk.ops = ops;
+ pll->hw.clk.name = name;
+ pll->hw.clk.parent_names = &pll->parent;
+ pll->hw.clk.num_parents = 1;
val = readl(pll->base);
val &= ~BM_PLL_BYPASS;
writel(val, pll->base);
- ret = clk_register(&pll->clk);
+ ret = bclk_register(&pll->hw.clk);
if (ret) {
free(pll);
return ERR_PTR(ret);
}
- return &pll->clk;
+ return &pll->hw.clk;
}
diff --git a/drivers/clk/imx/clk-sccg-pll.c b/drivers/clk/imx/clk-sccg-pll.c
index aabab27a22..f911bf4aa1 100644
--- a/drivers/clk/imx/clk-sccg-pll.c
+++ b/drivers/clk/imx/clk-sccg-pll.c
@@ -12,7 +12,7 @@
#include <linux/err.h>
#include <malloc.h>
#include <clock.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
@@ -39,26 +39,26 @@
#define OSC_27M 27000000
struct clk_sccg_pll {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *base;
const char *parent;
};
-#define to_clk_sccg_pll(_clk) container_of(_clk, struct clk_sccg_pll, clk)
+#define to_clk_sccg_pll(_hw) container_of(_hw, struct clk_sccg_pll, hw)
-static int clk_pll1_is_prepared(struct clk *clk)
+static int clk_pll1_is_prepared(struct clk_hw *hw)
{
- struct clk_sccg_pll *pll = to_clk_sccg_pll(clk);
+ struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
u32 val;
val = readl(pll->base + PLL_CFG0);
return (val & (1 << PLL_PD)) ? 0 : 1;
}
-static unsigned long clk_pll1_recalc_rate(struct clk *clk,
+static unsigned long clk_pll1_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_sccg_pll *pll = to_clk_sccg_pll(clk);
+ struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
u32 val, divf;
val = readl(pll->base + PLL_CFG2);
@@ -67,7 +67,7 @@ static unsigned long clk_pll1_recalc_rate(struct clk *clk,
return parent_rate * 2 * (divf + 1);
}
-static long clk_pll1_round_rate(struct clk *clk, unsigned long rate,
+static long clk_pll1_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
unsigned long parent_rate = *prate;
@@ -78,10 +78,10 @@ static long clk_pll1_round_rate(struct clk *clk, unsigned long rate,
return parent_rate * div * 2;
}
-static int clk_pll1_set_rate(struct clk *clk, unsigned long rate,
+static int clk_pll1_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_sccg_pll *pll = to_clk_sccg_pll(clk);
+ struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
u32 val;
u32 divf;
@@ -97,9 +97,9 @@ static int clk_pll1_set_rate(struct clk *clk, unsigned long rate,
return 0;
}
-static int clk_pll1_prepare(struct clk *clk)
+static int clk_pll1_prepare(struct clk_hw *hw)
{
- struct clk_sccg_pll *pll = to_clk_sccg_pll(clk);
+ struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
u32 val;
val = readl(pll->base);
@@ -111,19 +111,20 @@ static int clk_pll1_prepare(struct clk *clk)
return 0;
}
-static void clk_pll1_unprepare(struct clk *clk)
+static void clk_pll1_unprepare(struct clk_hw *hw)
{
- struct clk_sccg_pll *pll = to_clk_sccg_pll(clk);
+ struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
u32 val;
+
val = readl(pll->base);
val |= (1 << PLL_PD);
writel(val, pll->base);
}
-static unsigned long clk_pll2_recalc_rate(struct clk *clk,
+static unsigned long clk_pll2_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_sccg_pll *pll = to_clk_sccg_pll(clk);
+ struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
u32 val, ref, divr1, divf1, divr2, divf2;
u64 temp64;
@@ -154,7 +155,7 @@ static unsigned long clk_pll2_recalc_rate(struct clk *clk,
return (unsigned long)temp64;
}
-static long clk_pll2_round_rate(struct clk *clk, unsigned long rate,
+static long clk_pll2_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
u32 div;
@@ -165,12 +166,12 @@ static long clk_pll2_round_rate(struct clk *clk, unsigned long rate,
return parent_rate * div;
}
-static int clk_pll2_set_rate(struct clk *clk, unsigned long rate,
+static int clk_pll2_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
+ struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
u32 val;
u32 divf;
- struct clk_sccg_pll *pll = to_clk_sccg_pll(clk);
divf = rate / (parent_rate);
@@ -210,25 +211,25 @@ struct clk *imx_clk_sccg_pll(const char *name, const char *parent_name,
return ERR_PTR(-ENOMEM);
pll->base = base;
- pll->clk.name = name;
+ pll->hw.clk.name = name;
switch (pll_type) {
case SCCG_PLL1:
- pll->clk.ops = &clk_sccg_pll1_ops;
+ pll->hw.clk.ops = &clk_sccg_pll1_ops;
break;
case SCCG_PLL2:
- pll->clk.ops = &clk_sccg_pll2_ops;
+ pll->hw.clk.ops = &clk_sccg_pll2_ops;
break;
}
pll->parent = parent_name;
- pll->clk.parent_names = &pll->parent;
- pll->clk.num_parents = 1;
+ pll->hw.clk.parent_names = &pll->parent;
+ pll->hw.clk.num_parents = 1;
- ret = clk_register(&pll->clk);
+ ret = bclk_register(&pll->hw.clk);
if (ret) {
free(pll);
return ERR_PTR(ret);
}
- return &pll->clk;
+ return &pll->hw.clk;
}
diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c
index 1bd1fe5c44..112f64df9b 100644
--- a/drivers/clk/imx/clk-vf610.c
+++ b/drivers/clk/imx/clk-vf610.c
@@ -13,8 +13,8 @@
#include <linux/clk.h>
#include <notifier.h>
#include <dt-bindings/clock/vf610-clock.h>
-#include <mach/vf610-regs.h>
-#include <mach/vf610-fusemap.h>
+#include <mach/imx/vf610-regs.h>
+#include <mach/imx/vf610-fusemap.h>
#include "clk.h"
@@ -568,13 +568,16 @@ static int vf610_switch_cpu_clock_to_400mhz(void)
static int vf610_switch_cpu_clock(void)
{
int ret;
- bool sense_enable;
+ int sense_enable;
uint32_t speed_grading;
if (!of_machine_is_compatible("fsl,vf610"))
return 0;
sense_enable = imx_ocotp_sense_enable(true);
+ if (sense_enable < 0)
+ return sense_enable;
+
ret = imx_ocotp_read_field(VF610_OCOTP_SPEED_GRADING, &speed_grading);
imx_ocotp_sense_enable(sense_enable);
if (ret < 0)
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 5cd2c56a1b..9058f913d3 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -40,11 +40,19 @@ static inline struct clk *imx_clk_divider_table(const char *name,
width, table, 0);
}
+static inline struct clk *__imx_clk_mux(const char *name, void __iomem *reg,
+ u8 shift, u8 width, const char * const *parents,
+ u8 num_parents, unsigned flags, unsigned long clk_mux_flags)
+{
+ return clk_mux(name, CLK_SET_RATE_NO_REPARENT | flags, reg,
+ shift, width, parents, num_parents, clk_mux_flags);
+}
+
static inline struct clk *imx_clk_mux_ldb(const char *name, void __iomem *reg,
- u8 shift, u8 width, const char **parents, int num_parents)
+ u8 shift, u8 width, const char * const *parents, int num_parents)
{
- return clk_mux(name, CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, reg,
- shift, width, parents, num_parents, CLK_MUX_READ_ONLY);
+ return __imx_clk_mux(name, reg, shift, width, parents, num_parents,
+ CLK_SET_RATE_PARENT, CLK_MUX_READ_ONLY);
}
@@ -56,39 +64,39 @@ static inline struct clk *imx_clk_fixed_factor(const char *name,
static inline struct clk *imx_clk_mux_flags(const char *name, void __iomem *reg,
u8 shift, u8 width,
- const char **parents, u8 num_parents,
+ const char * const *parents, u8 num_parents,
unsigned long clk_flags)
{
- return clk_mux(name, clk_flags, reg, shift, width, parents, num_parents,
- 0);
+ return __imx_clk_mux(name, reg, shift, width, parents, num_parents,
+ clk_flags, 0);
}
static inline struct clk *imx_clk_mux2_flags(const char *name,
- void __iomem *reg, u8 shift, u8 width, const char **parents,
+ void __iomem *reg, u8 shift, u8 width, const char * const *parents,
int num_parents, unsigned long clk_flags)
{
- return clk_mux(name, clk_flags | CLK_OPS_PARENT_ENABLE, reg, shift,
- width, parents, num_parents, 0);
+ return __imx_clk_mux(name,reg, shift, width, parents, num_parents,
+ clk_flags | CLK_OPS_PARENT_ENABLE, 0);
}
static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
- u8 shift, u8 width, const char **parents, u8 num_parents)
+ u8 shift, u8 width, const char * const *parents, u8 num_parents)
{
- return clk_mux(name, 0, reg, shift, width, parents, num_parents, 0);
+ return __imx_clk_mux(name, reg, shift, width, parents, num_parents, 0, 0);
}
static inline struct clk *imx_clk_mux2(const char *name, void __iomem *reg,
- u8 shift, u8 width, const char **parents, u8 num_parents)
+ u8 shift, u8 width, const char * const *parents, u8 num_parents)
{
- return clk_mux(name, CLK_OPS_PARENT_ENABLE, reg, shift, width, parents,
- num_parents, 0);
+ return __imx_clk_mux(name, reg, shift, width, parents,
+ num_parents, CLK_OPS_PARENT_ENABLE, 0);
}
static inline struct clk *imx_clk_mux_p(const char *name, void __iomem *reg,
- u8 shift, u8 width, const char **parents, u8 num_parents)
+ u8 shift, u8 width, const char * const *parents, u8 num_parents)
{
- return clk_mux(name, CLK_SET_RATE_PARENT, reg, shift, width, parents,
- num_parents, 0);
+ return __imx_clk_mux(name, reg, shift, width, parents, num_parents,
+ CLK_SET_RATE_PARENT, 0);
}
static inline struct clk *imx_clk_gate(const char *name, const char *parent,
@@ -141,6 +149,12 @@ static inline struct clk *imx_clk_gate4(const char *name, const char *parent,
return clk_gate2(name, parent, reg, shift, 0x3, CLK_OPS_PARENT_ENABLE);
}
+static inline struct clk *imx_clk_gate4_flags(const char *name, const char *parent,
+ void __iomem *reg, u8 shift, unsigned long flags)
+{
+ return clk_gate2(name, parent, reg, shift, 0x3, flags | CLK_OPS_PARENT_ENABLE);
+}
+
static inline struct clk *imx_clk_gate_shared(const char *name, const char *parent,
const char *shared)
{
@@ -259,13 +273,29 @@ struct clk *imx_clk_cpu(const char *name, const char *parent_name,
struct clk *div, struct clk *mux, struct clk *pll,
struct clk *step);
+#define IMX_COMPOSITE_CORE BIT(0)
+#define IMX_COMPOSITE_BUS BIT(1)
+
struct clk *imx8m_clk_composite_flags(const char *name,
- const char **parent_names, int num_parents, void __iomem *reg,
+ const char * const *parent_names, int num_parents, void __iomem *reg,
+ u32 composite_flags,
unsigned long flags);
+#define imx8m_clk_hw_composite_core(name, parent_names, reg) \
+ imx8m_clk_hw_composite_flags(name, parent_names, \
+ ARRAY_SIZE(parent_names), reg, \
+ IMX_COMPOSITE_CORE, \
+ CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE)
+
+#define imx8m_clk_hw_composite_bus(name, parent_names, reg) \
+ imx8m_clk_hw_composite_flags(name, parent_names, \
+ ARRAY_SIZE(parent_names), reg, \
+ IMX_COMPOSITE_BUS, \
+ CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE)
+
#define __imx8m_clk_composite(name, parent_names, reg, flags) \
imx8m_clk_composite_flags(name, parent_names, \
- ARRAY_SIZE(parent_names), reg, \
+ ARRAY_SIZE(parent_names), reg, 0, \
flags | CLK_OPS_PARENT_ENABLE)
#define imx8m_clk_composite(name, parent_names, reg) \
@@ -274,4 +304,42 @@ struct clk *imx8m_clk_composite_flags(const char *name,
#define imx8m_clk_composite_critical(name, parent_names, reg) \
__imx8m_clk_composite(name, parent_names, reg, CLK_IS_CRITICAL)
+#include <soc/imx/clk-fracn-gppll.h>
+
+struct clk *imx93_clk_composite_flags(const char *name,
+ const char * const *parent_names,
+ int num_parents,
+ void __iomem *reg,
+ u32 domain_id,
+ unsigned long flags);
+#define imx93_clk_composite(name, parent_names, num_parents, reg, domain_id) \
+ imx93_clk_composite_flags(name, parent_names, num_parents, reg, domain_id \
+ CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE)
+
+struct clk *imx93_clk_gate(struct device *dev, const char *name, const char *parent_name,
+ unsigned long flags, void __iomem *reg, u32 bit_idx, u32 val,
+ u32 mask, u32 domain_id, unsigned int *share_count);
+
+/*
+ * Names of the above functions used in the Linux Kernel. Added here
+ * to be able to use the same names in barebox to reduce the diffs
+ * between barebox and Linux clk drivers.
+ */
+#define imx_clk_hw_mux imx_clk_mux
+#define imx_clk_hw_pll14xx imx_clk_pll14xx
+#define imx_clk_hw_gate imx_clk_gate
+#define imx_clk_hw_fixed_factor imx_clk_fixed_factor
+#define imx_clk_hw_mux_flags imx_clk_mux_flags
+#define imx_clk_hw_divider2 imx_clk_divider2
+#define imx_clk_hw_mux2_flags imx_clk_mux2_flags
+#define imx_clk_hw_gate4_flags imx_clk_gate4_flags
+#define imx_clk_hw_gate4 imx_clk_gate4
+#define imx_clk_hw_cpu imx_clk_cpu
+#define imx_clk_hw_gate2 imx_clk_gate2
+#define imx8m_clk_hw_composite_flags imx8m_clk_composite_flags
+#define imx8m_clk_hw_composite imx8m_clk_composite
+#define imx8m_clk_hw_composite_critical imx8m_clk_composite_critical
+#define imx_clk_hw_gate2_shared2 imx_clk_gate2_shared2
+#define imx_clk_hw_mux2 imx_clk_mux2
+
#endif /* __IMX_CLK_H */
diff --git a/drivers/clk/loongson/Makefile b/drivers/clk/loongson/Makefile
new file mode 100644
index 0000000000..bd452bad8f
--- /dev/null
+++ b/drivers/clk/loongson/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_BOARD_LOONGSON_TECH_LS1B) += clk-ls1b200.o
+
diff --git a/drivers/clk/loongson/clk-ls1b200.c b/drivers/clk/loongson/clk-ls1b200.c
new file mode 100644
index 0000000000..4e6aa94d52
--- /dev/null
+++ b/drivers/clk/loongson/clk-ls1b200.c
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Based on the ath79 clock code by Antony Pavlov <antonynpavlov@gmail.com>
+ * Barebox drivers/clk/clk-ar933x.c
+ *
+ * Copyright (C) 2020 Du Huanpeng <u74147@gmail.com>
+ */
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+
+#include <dt-bindings/clock/ls1b-clk.h>
+
+#define LS1B_CPU_DIV_SHIFT 20
+#define LS1B_CPU_DIV_WIDTH 4
+
+#define LS1B_DDR_DIV_SHIFT 14
+#define LS1B_DDR_DIV_WIDTH 4
+
+#define LS1B_DC_DIV_SHIFT 26
+#define LS1B_DC_DIV_WIDTH 4
+
+#define LS1B_CLK_APB_MULT 1
+#define LS1B_CLK_APB_DIV2 2
+
+/* register offset */
+#define PLL_FREQ 0
+#define PLL_DIV_PARAM 4
+
+static struct clk *clks[LS1B_CLK_END];
+static struct clk_onecell_data clk_data;
+
+struct clk_ls1b200 {
+ struct clk_hw hw;
+ void __iomem *base;
+ int div_shift;
+ int div_mask;
+ const char *parent;
+};
+
+static unsigned long clk_ls1b200_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+ int n;
+ unsigned long rate;
+ int pll_freq;
+ struct clk_ls1b200 *ls1bclk;
+
+ ls1bclk = container_of(hw, struct clk_ls1b200, hw);
+ pll_freq = __raw_readl(ls1bclk->base);
+
+ n = 12 * 1024;
+ n += (pll_freq & 0x3F) * 1024;
+ n += (pll_freq >> 8) & 0x3FF;
+
+ rate = parent_rate / 2 / 1024;
+ /* avoid overflow. */
+ rate *= n;
+
+ return rate;
+}
+
+struct clk_ops clk_ls1b200_ops = {
+ .recalc_rate = clk_ls1b200_recalc_rate,
+};
+
+static struct clk *clk_ls1b200(const char *name, const char *parent,
+ void __iomem *base, int div_shift, int div_mask)
+{
+ struct clk_ls1b200 *f = xzalloc(sizeof(struct clk_ls1b200));
+
+ f->parent = parent;
+ f->base = base;
+ f->div_shift = div_shift;
+ f->div_mask = div_mask;
+
+ f->hw.clk.ops = &clk_ls1b200_ops;
+ f->hw.clk.name = name;
+ f->hw.clk.parent_names = &f->parent;
+ f->hw.clk.num_parents = 1;
+
+ bclk_register(&f->hw.clk);
+
+ return &f->hw.clk;
+}
+
+static const char * const cpu_mux[] = {"cpu_div", "oscillator", };
+static const char * const ddr_mux[] = {"ddr_div", "oscillator", };
+static const char * const dc_mux[] = {"dc_div", "oscillator", };
+
+static void ls1b200_pll_init(void __iomem *base)
+{
+ clks[LS1B_CLK_PLL] = clk_ls1b200("pll", "oscillator", base + PLL_FREQ, 0, 0);
+
+ clks[LS1B_CLK_CPU_DIV] = clk_divider("cpu_div", "pll", 0,
+ base + PLL_DIV_PARAM, LS1B_CPU_DIV_SHIFT, LS1B_CPU_DIV_WIDTH, CLK_DIVIDER_ONE_BASED);
+ clks[LS1B_CLK_CPU_MUX] = clk_mux("cpu_mux", 0, base + PLL_DIV_PARAM,
+ 8, 1, cpu_mux, ARRAY_SIZE(cpu_mux), 0);
+
+ clks[LS1B_CLK_DDR_DIV] = clk_divider("ddr_div", "pll", 0,
+ base + PLL_DIV_PARAM, LS1B_DDR_DIV_SHIFT, LS1B_DDR_DIV_WIDTH, CLK_DIVIDER_ONE_BASED);
+ clks[LS1B_CLK_DDR_MUX] = clk_mux("ddr_mux", 0, base + PLL_DIV_PARAM,
+ 10, 1, ddr_mux, ARRAY_SIZE(ddr_mux), 0);
+ clks[LS1B_CLK_APB_DIV] = clk_fixed_factor("apb_div", "ddr_mux", LS1B_CLK_APB_MULT, LS1B_CLK_APB_DIV2, 0);
+
+ clks[LS1B_CLK_DIV4] = clk_fixed_factor("dc_div4", "pll", 1, 4, 0);
+
+ clks[LS1B_CLK_DC_DIV] = clk_divider("dc_div", "dc_div4", 0,
+ base + PLL_DIV_PARAM, LS1B_DC_DIV_SHIFT, LS1B_DC_DIV_WIDTH, CLK_DIVIDER_ONE_BASED);
+ clks[LS1B_CLK_DC_MUX] = clk_mux("dc_mux", 0, base + PLL_DIV_PARAM,
+ 10, 1, dc_mux, ARRAY_SIZE(dc_mux), 0);
+}
+
+static int ls1b200_clk_probe(struct device *dev)
+{
+ struct resource *iores;
+ void __iomem *base;
+
+ iores = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(iores))
+ return PTR_ERR(iores);
+ base = IOMEM(iores->start);
+
+ /* now got the controller base address */
+ ls1b200_pll_init(base);
+
+ clk_data.clks = clks;
+ clk_data.clk_num = ARRAY_SIZE(clks);
+ of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, &clk_data);
+
+ return 0;
+}
+
+static __maybe_unused struct of_device_id ls1b200_clk_dt_ids[] = {
+ {
+ .compatible = "loongson,ls1b-pll",
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, ls1b200_clk_dt_ids);
+
+static struct driver ls1b200_clk_driver = {
+ .probe = ls1b200_clk_probe,
+ .name = "ls1b-clk",
+ .of_compatible = DRV_OF_COMPAT(ls1b200_clk_dt_ids),
+};
+
+postcore_platform_driver(ls1b200_clk_driver);
diff --git a/drivers/clk/mvebu/armada-38x.c b/drivers/clk/mvebu/armada-38x.c
index 627de7de6c..80865965e1 100644
--- a/drivers/clk/mvebu/armada-38x.c
+++ b/drivers/clk/mvebu/armada-38x.c
@@ -17,7 +17,7 @@
/*
* Core Clocks
*
- * Armada XP Sample At Reset is a 64 bit bitfiled split in two
+ * Armada XP Sample At Reset is a 64 bit bitfield split in two
* register of 32 bits
*/
diff --git a/drivers/clk/mvebu/armada-xp.c b/drivers/clk/mvebu/armada-xp.c
index d79f846d3f..f0276d32f5 100644
--- a/drivers/clk/mvebu/armada-xp.c
+++ b/drivers/clk/mvebu/armada-xp.c
@@ -16,7 +16,7 @@
/*
* Core Clocks
*
- * Armada XP Sample At Reset is a 64 bit bitfiled split in two
+ * Armada XP Sample At Reset is a 64 bit bitfield split in two
* register of 32 bits
*/
diff --git a/drivers/clk/mvebu/common.c b/drivers/clk/mvebu/common.c
index c7de00ac77..4ed2193e58 100644
--- a/drivers/clk/mvebu/common.c
+++ b/drivers/clk/mvebu/common.c
@@ -38,11 +38,12 @@ static struct of_device_id mvebu_coreclk_ids[] = {
.data = &mv88f6180_coreclks },
{ }
};
+MODULE_DEVICE_TABLE(of, mvebu_coreclk_ids);
-static int mvebu_coreclk_probe(struct device_d *dev)
+static int mvebu_coreclk_probe(struct device *dev)
{
struct resource *iores;
- struct device_node *np = dev->device_node;
+ struct device_node *np = dev->of_node;
const struct of_device_id *match;
const struct coreclk_soc_desc *desc;
const char *tclk_name = "tclk";
@@ -96,17 +97,13 @@ static int mvebu_coreclk_probe(struct device_d *dev)
return of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
}
-static struct driver_d mvebu_coreclk_driver = {
+static struct driver mvebu_coreclk_driver = {
.probe = mvebu_coreclk_probe,
.name = "mvebu-core-clk",
.of_compatible = DRV_OF_COMPAT(mvebu_coreclk_ids),
};
-static int mvebu_coreclk_init(void)
-{
- return platform_driver_register(&mvebu_coreclk_driver);
-}
-core_initcall(mvebu_coreclk_init);
+core_platform_driver(mvebu_coreclk_driver);
/*
* Clock Gating Control
@@ -151,11 +148,12 @@ static struct of_device_id mvebu_clk_gating_ids[] = {
.data = &kirkwood_gating_desc },
{ }
};
+MODULE_DEVICE_TABLE(of, mvebu_clk_gating_ids);
-static int mvebu_clk_gating_probe(struct device_d *dev)
+static int mvebu_clk_gating_probe(struct device *dev)
{
struct resource *iores;
- struct device_node *np = dev->device_node;
+ struct device_node *np = dev->of_node;
const struct of_device_id *match;
const struct clk_gating_soc_desc *desc;
struct clk_gating_ctrl *ctrl;
@@ -201,14 +199,10 @@ static int mvebu_clk_gating_probe(struct device_d *dev)
return of_clk_add_provider(np, clk_gating_get_src, ctrl);
}
-static struct driver_d mvebu_clk_gating_driver = {
+static struct driver mvebu_clk_gating_driver = {
.probe = mvebu_clk_gating_probe,
.name = "mvebu-clk-gating",
.of_compatible = DRV_OF_COMPAT(mvebu_clk_gating_ids),
};
-static int mvebu_clk_gating_init(void)
-{
- return platform_driver_register(&mvebu_clk_gating_driver);
-}
-postcore_initcall(mvebu_clk_gating_init);
+postcore_platform_driver(mvebu_clk_gating_driver);
diff --git a/drivers/clk/mvebu/corediv.c b/drivers/clk/mvebu/corediv.c
index f740161e45..7ca53faca4 100644
--- a/drivers/clk/mvebu/corediv.c
+++ b/drivers/clk/mvebu/corediv.c
@@ -51,7 +51,7 @@ struct clk_corediv_soc_desc {
* existing in the current SoC.
*/
struct clk_corediv {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *reg;
const struct clk_corediv_desc *desc;
const struct clk_corediv_soc_desc *soc_desc;
@@ -70,11 +70,11 @@ static const struct clk_corediv_desc mvebu_corediv_desc[] = {
#define CORE_CLK_DIV_RATIO_MASK 0xff
-#define to_corediv_clk(p) container_of(p, struct clk_corediv, clk)
+#define to_corediv_clk(p) container_of(p, struct clk_corediv, hw)
-static int clk_corediv_is_enabled(struct clk *clk)
+static int clk_corediv_is_enabled(struct clk_hw *hw)
{
- struct clk_corediv *corediv = to_corediv_clk(clk);
+ struct clk_corediv *corediv = to_corediv_clk(hw);
const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc;
const struct clk_corediv_desc *desc = corediv->desc;
u32 enable_mask = BIT(desc->fieldbit) << soc_desc->enable_bit_offset;
@@ -82,9 +82,9 @@ static int clk_corediv_is_enabled(struct clk *clk)
return !!(readl(corediv->reg) & enable_mask);
}
-static int clk_corediv_enable(struct clk *clk)
+static int clk_corediv_enable(struct clk_hw *hw)
{
- struct clk_corediv *corediv = to_corediv_clk(clk);
+ struct clk_corediv *corediv = to_corediv_clk(hw);
const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc;
const struct clk_corediv_desc *desc = corediv->desc;
u32 reg;
@@ -96,9 +96,9 @@ static int clk_corediv_enable(struct clk *clk)
return 0;
}
-static void clk_corediv_disable(struct clk *clk)
+static void clk_corediv_disable(struct clk_hw *hw)
{
- struct clk_corediv *corediv = to_corediv_clk(clk);
+ struct clk_corediv *corediv = to_corediv_clk(hw);
const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc;
const struct clk_corediv_desc *desc = corediv->desc;
u32 reg;
@@ -108,10 +108,10 @@ static void clk_corediv_disable(struct clk *clk)
writel(reg, corediv->reg);
}
-static unsigned long clk_corediv_recalc_rate(struct clk *clk,
+static unsigned long clk_corediv_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_corediv *corediv = to_corediv_clk(clk);
+ struct clk_corediv *corediv = to_corediv_clk(hw);
const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc;
const struct clk_corediv_desc *desc = corediv->desc;
u32 reg, div;
@@ -121,7 +121,7 @@ static unsigned long clk_corediv_recalc_rate(struct clk *clk,
return parent_rate / div;
}
-static long clk_corediv_round_rate(struct clk *clk, unsigned long rate,
+static long clk_corediv_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
/* Valid ratio are 1:4, 1:5, 1:6 and 1:8 */
@@ -136,10 +136,10 @@ static long clk_corediv_round_rate(struct clk *clk, unsigned long rate,
return *parent_rate / div;
}
-static int clk_corediv_set_rate(struct clk *clk, unsigned long rate,
+static int clk_corediv_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_corediv *corediv = to_corediv_clk(clk);
+ struct clk_corediv *corediv = to_corediv_clk(hw);
const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc;
const struct clk_corediv_desc *desc = corediv->desc;
u32 reg, div;
@@ -193,11 +193,12 @@ static struct of_device_id mvebu_corediv_clk_ids[] = {
.data = &armada370_corediv_soc },
{ }
};
+MODULE_DEVICE_TABLE(of, mvebu_corediv_clk_ids);
-static int mvebu_corediv_clk_probe(struct device_d *dev)
+static int mvebu_corediv_clk_probe(struct device *dev)
{
struct resource *iores;
- struct device_node *np = dev->device_node;
+ struct device_node *np = dev->of_node;
const struct of_device_id *match;
const struct clk_corediv_soc_desc *soc_desc;
struct clk_corediv *corediv;
@@ -225,7 +226,7 @@ static int mvebu_corediv_clk_probe(struct device_d *dev)
for (n = 0; n < clk_data.clk_num; n++) {
const char *clk_name;
- struct clk *clk = &corediv->clk;
+ struct clk *clk = &corediv->hw.clk;
if (of_property_read_string_index(np,
"clock-output-names", n, &clk_name)) {
@@ -242,20 +243,16 @@ static int mvebu_corediv_clk_probe(struct device_d *dev)
corediv->desc = &soc_desc->descs[n];
corediv->reg = base;
clk_data.clks[n] = clk;
- WARN_ON(IS_ERR_VALUE(clk_register(clk)));
+ WARN_ON(IS_ERR_VALUE(bclk_register(clk)));
}
return of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
}
-static struct driver_d mvebu_corediv_clk_driver = {
+static struct driver mvebu_corediv_clk_driver = {
.probe = mvebu_corediv_clk_probe,
.name = "mvebu-corediv-clk",
.of_compatible = DRV_OF_COMPAT(mvebu_corediv_clk_ids),
};
-static int mvebu_corediv_clk_init(void)
-{
- return platform_driver_register(&mvebu_corediv_clk_driver);
-}
-postcore_initcall(mvebu_corediv_clk_init);
+postcore_platform_driver(mvebu_corediv_clk_driver);
diff --git a/drivers/clk/mxs/clk-div.c b/drivers/clk/mxs/clk-div.c
index 104587a8dc..17083a051a 100644
--- a/drivers/clk/mxs/clk-div.c
+++ b/drivers/clk/mxs/clk-div.c
@@ -28,40 +28,40 @@ struct clk_div {
u8 busy;
};
-static inline struct clk_div *to_clk_div(struct clk *clk)
+static inline struct clk_div *to_clk_div(struct clk_hw *hw)
{
- struct clk_divider *divider = container_of(clk, struct clk_divider, clk);
+ struct clk_divider *divider = to_clk_divider(hw);
return container_of(divider, struct clk_div, divider);
}
-static unsigned long clk_div_recalc_rate(struct clk *clk,
+static unsigned long clk_div_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_div *div = to_clk_div(clk);
+ struct clk_div *div = to_clk_div(hw);
- return div->ops->recalc_rate(&div->divider.clk, parent_rate);
+ return div->ops->recalc_rate(&div->divider.hw, parent_rate);
}
-static long clk_div_round_rate(struct clk *clk, unsigned long rate,
+static long clk_div_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
- struct clk_div *div = to_clk_div(clk);
+ struct clk_div *div = to_clk_div(hw);
- return div->ops->round_rate(&div->divider.clk, rate, prate);
+ return div->ops->round_rate(&div->divider.hw, rate, prate);
}
-static int clk_div_set_rate(struct clk *clk, unsigned long rate,
+static int clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_div *div = to_clk_div(clk);
+ struct clk_div *div = to_clk_div(hw);
int ret;
- ret = div->ops->set_rate(&div->divider.clk, rate, parent_rate);
+ ret = div->ops->set_rate(&div->divider.hw, rate, parent_rate);
if (ret)
return ret;
- if (clk_is_enabled(clk))
+ if (clk_hw_is_enabled(hw))
while (readl(div->reg) & 1 << div->busy);
return 0;
@@ -82,10 +82,10 @@ struct clk *mxs_clk_div(const char *name, const char *parent_name,
div = xzalloc(sizeof(*div));
div->parent = parent_name;
- div->divider.clk.name = name;
- div->divider.clk.ops = &clk_div_ops;
- div->divider.clk.parent_names = &div->parent;
- div->divider.clk.num_parents = 1;
+ div->divider.hw.clk.name = name;
+ div->divider.hw.clk.ops = &clk_div_ops;
+ div->divider.hw.clk.parent_names = &div->parent;
+ div->divider.hw.clk.num_parents = 1;
div->reg = reg;
div->busy = busy;
@@ -96,9 +96,9 @@ struct clk *mxs_clk_div(const char *name, const char *parent_name,
div->divider.flags = CLK_DIVIDER_ONE_BASED;
div->ops = &clk_divider_ops;
- ret = clk_register(&div->divider.clk);
+ ret = bclk_register(&div->divider.hw.clk);
if (ret)
return ERR_PTR(ret);
- return &div->divider.clk;
+ return &div->divider.hw.clk;
}
diff --git a/drivers/clk/mxs/clk-frac.c b/drivers/clk/mxs/clk-frac.c
index 21e572ff6f..6fb479dfad 100644
--- a/drivers/clk/mxs/clk-frac.c
+++ b/drivers/clk/mxs/clk-frac.c
@@ -7,7 +7,7 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <io.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
@@ -23,7 +23,7 @@
* when the divider is adjusted.
*/
struct clk_frac {
- struct clk clk;
+ struct clk_hw hw;
const char *parent;
void __iomem *reg;
u8 shift;
@@ -31,12 +31,12 @@ struct clk_frac {
u8 busy;
};
-#define to_clk_frac(_hw) container_of(_hw, struct clk_frac, clk)
+#define to_clk_frac(_hw) container_of(_hw, struct clk_frac, hw)
-static unsigned long clk_frac_recalc_rate(struct clk *clk,
+static unsigned long clk_frac_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_frac *frac = to_clk_frac(clk);
+ struct clk_frac *frac = to_clk_frac(hw);
u32 div;
div = readl(frac->reg) >> frac->shift;
@@ -45,10 +45,10 @@ static unsigned long clk_frac_recalc_rate(struct clk *clk,
return (parent_rate >> frac->width) * div;
}
-static long clk_frac_round_rate(struct clk *clk, unsigned long rate,
+static long clk_frac_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
- struct clk_frac *frac = to_clk_frac(clk);
+ struct clk_frac *frac = to_clk_frac(hw);
unsigned long parent_rate = *prate;
u32 div;
u64 tmp;
@@ -67,10 +67,10 @@ static long clk_frac_round_rate(struct clk *clk, unsigned long rate,
return (parent_rate >> frac->width) * div;
}
-static int clk_frac_set_rate(struct clk *clk, unsigned long rate,
+static int clk_frac_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_frac *frac = to_clk_frac(clk);
+ struct clk_frac *frac = to_clk_frac(hw);
u32 div, val;
u64 tmp;
@@ -90,7 +90,7 @@ static int clk_frac_set_rate(struct clk *clk, unsigned long rate,
val |= div << frac->shift;
writel(val, frac->reg);
- if (clk_is_enabled(clk))
+ if (clk_hw_is_enabled(hw))
while (readl(frac->reg) & 1 << frac->busy);
return 0;
@@ -113,18 +113,18 @@ struct clk *mxs_clk_frac(const char *name, const char *parent_name,
return ERR_PTR(-ENOMEM);
frac->parent = parent_name;
- frac->clk.name = name;
- frac->clk.ops = &clk_frac_ops;
- frac->clk.parent_names = &frac->parent;
- frac->clk.num_parents = 1;
+ frac->hw.clk.name = name;
+ frac->hw.clk.ops = &clk_frac_ops;
+ frac->hw.clk.parent_names = &frac->parent;
+ frac->hw.clk.num_parents = 1;
frac->reg = reg;
frac->shift = shift;
frac->width = width;
- ret = clk_register(&frac->clk);
+ ret = bclk_register(&frac->hw.clk);
if (ret)
return ERR_PTR(ret);
- return &frac->clk;
+ return &frac->hw.clk;
}
diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c
index dae8e348e2..d931adda38 100644
--- a/drivers/clk/mxs/clk-imx23.c
+++ b/drivers/clk/mxs/clk-imx23.c
@@ -10,7 +10,7 @@
#include <io.h>
#include <linux/clkdev.h>
#include <linux/err.h>
-#include <mach/imx23-regs.h>
+#include <mach/mxs/imx23-regs.h>
#include "clk.h"
@@ -112,7 +112,7 @@ static int __init mx23_clocks_init(void __iomem *regs)
return 0;
}
-static int imx23_ccm_probe(struct device_d *dev)
+static int imx23_ccm_probe(struct device *dev)
{
struct resource *iores;
void __iomem *regs;
@@ -134,15 +134,12 @@ static __maybe_unused struct of_device_id imx23_ccm_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, imx23_ccm_dt_ids);
-static struct driver_d imx23_ccm_driver = {
+static struct driver imx23_ccm_driver = {
.probe = imx23_ccm_probe,
.name = "imx23-clkctrl",
.of_compatible = DRV_OF_COMPAT(imx23_ccm_dt_ids),
};
-static int imx23_ccm_init(void)
-{
- return platform_driver_register(&imx23_ccm_driver);
-}
-postcore_initcall(imx23_ccm_init);
+postcore_platform_driver(imx23_ccm_driver);
diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
index bf65a4a3b8..c2faddb6f4 100644
--- a/drivers/clk/mxs/clk-imx28.c
+++ b/drivers/clk/mxs/clk-imx28.c
@@ -10,7 +10,7 @@
#include <io.h>
#include <linux/clkdev.h>
#include <linux/err.h>
-#include <mach/imx28-regs.h>
+#include <mach/mxs/imx28-regs.h>
#include <of_address.h>
#include "clk.h"
@@ -67,7 +67,7 @@ enum imx28_clk {
static struct clk *clks[clk_max];
static struct clk_onecell_data clk_data;
-static int __init mx28_clocks_init(struct device_d *dev, void __iomem *regs)
+static int __init mx28_clocks_init(struct device *dev, void __iomem *regs)
{
struct device_node *dcnp;
@@ -145,11 +145,13 @@ static int __init mx28_clocks_init(struct device_d *dev, void __iomem *regs)
clk_set_rate(clks[ssp2], 96000000);
clk_set_rate(clks[ssp3], 96000000);
clk_set_parent(clks[lcdif_sel], clks[ref_pix]);
+ clk_set_parent(clks[gpmi_sel], clks[ref_gpmi]);
- if (dev->device_node) {
+ if (dev->of_node) {
clk_data.clks = clks;
clk_data.clk_num = clk_max;
- of_clk_add_provider(dev->device_node, of_clk_src_onecell_get, &clk_data);
+ of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
+ &clk_data);
} else {
clkdev_add_physbase(clks[ssp0], IMX_SSP0_BASE, NULL);
clkdev_add_physbase(clks[ssp1], IMX_SSP1_BASE, NULL);
@@ -173,7 +175,7 @@ static int __init mx28_clocks_init(struct device_d *dev, void __iomem *regs)
return 0;
}
-static int imx28_ccm_probe(struct device_d *dev)
+static int imx28_ccm_probe(struct device *dev)
{
struct resource *iores;
void __iomem *regs;
@@ -195,15 +197,12 @@ static __maybe_unused struct of_device_id imx28_ccm_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, imx28_ccm_dt_ids);
-static struct driver_d imx28_ccm_driver = {
+static struct driver imx28_ccm_driver = {
.probe = imx28_ccm_probe,
.name = "imx28-clkctrl",
.of_compatible = DRV_OF_COMPAT(imx28_ccm_dt_ids),
};
-static int imx28_ccm_init(void)
-{
- return platform_driver_register(&imx28_ccm_driver);
-}
-postcore_initcall(imx28_ccm_init);
+postcore_platform_driver(imx28_ccm_driver);
diff --git a/drivers/clk/mxs/clk-lcdif.c b/drivers/clk/mxs/clk-lcdif.c
index 246e68068d..a395701262 100644
--- a/drivers/clk/mxs/clk-lcdif.c
+++ b/drivers/clk/mxs/clk-lcdif.c
@@ -7,18 +7,18 @@
#include "clk.h"
struct clk_lcdif {
- struct clk clk;
+ struct clk_hw hw;
struct clk *frac, *div, *gate;
const char *parent;
};
-#define to_clk_lcdif(_hw) container_of(_hw, struct clk_lcdif, clk)
+#define to_clk_lcdif(_hw) container_of(_hw, struct clk_lcdif, hw)
-static int clk_lcdif_set_rate(struct clk *clk, unsigned long rate,
+static int clk_lcdif_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long unused)
{
- struct clk_lcdif *lcdif = to_clk_lcdif(clk);
+ struct clk_lcdif *lcdif = to_clk_lcdif(hw);
unsigned long frac, div, best_div = 1;
int delta, best_delta = 0x7fffffff;
unsigned long frate, rrate, best_frate;
@@ -63,14 +63,14 @@ struct clk *mxs_clk_lcdif(const char *name, struct clk *frac, struct clk *div,
lcdif->frac = frac;
lcdif->div = div;
lcdif->gate = gate;
- lcdif->clk.name = name;
- lcdif->clk.ops = &clk_lcdif_ops;
- lcdif->clk.parent_names = &lcdif->parent;
- lcdif->clk.num_parents = 1;
+ lcdif->hw.clk.name = name;
+ lcdif->hw.clk.ops = &clk_lcdif_ops;
+ lcdif->hw.clk.parent_names = &lcdif->parent;
+ lcdif->hw.clk.num_parents = 1;
- ret = clk_register(&lcdif->clk);
+ ret = bclk_register(&lcdif->hw.clk);
if (ret)
return ERR_PTR(ret);
- return &lcdif->clk;
+ return &lcdif->hw.clk;
}
diff --git a/drivers/clk/mxs/clk-pll.c b/drivers/clk/mxs/clk-pll.c
index 7527a77731..2c55ab7d8b 100644
--- a/drivers/clk/mxs/clk-pll.c
+++ b/drivers/clk/mxs/clk-pll.c
@@ -24,18 +24,18 @@
* and the shift of gate bit is always 31.
*/
struct clk_pll {
- struct clk clk;
+ struct clk_hw hw;
const char *parent;
void __iomem *base;
u8 power;
unsigned long rate;
};
-#define to_clk_pll(_hw) container_of(_hw, struct clk_pll, clk)
+#define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw)
-static int clk_pll_enable(struct clk *clk)
+static int clk_pll_enable(struct clk_hw *hw)
{
- struct clk_pll *pll = to_clk_pll(clk);
+ struct clk_pll *pll = to_clk_pll(hw);
writel(1 << pll->power, pll->base + SET);
@@ -46,18 +46,18 @@ static int clk_pll_enable(struct clk *clk)
return 0;
}
-static void clk_pll_disable(struct clk *clk)
+static void clk_pll_disable(struct clk_hw *hw)
{
- struct clk_pll *pll = to_clk_pll(clk);
+ struct clk_pll *pll = to_clk_pll(hw);
writel(1 << 31, pll->base + SET);
writel(1 << pll->power, pll->base + CLR);
}
-static int clk_pll_is_enabled(struct clk *clk)
+static int clk_pll_is_enabled(struct clk_hw *hw)
{
- struct clk_pll *pll = to_clk_pll(clk);
+ struct clk_pll *pll = to_clk_pll(hw);
u32 val;
val = readl(pll->base);
@@ -68,10 +68,10 @@ static int clk_pll_is_enabled(struct clk *clk)
return 1;
}
-static unsigned long clk_pll_recalc_rate(struct clk *clk,
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_pll *pll = to_clk_pll(clk);
+ struct clk_pll *pll = to_clk_pll(hw);
return pll->rate;
}
@@ -92,18 +92,18 @@ struct clk *mxs_clk_pll(const char *name, const char *parent_name,
pll = xzalloc(sizeof(*pll));
pll->parent = parent_name;
- pll->clk.name = name;
- pll->clk.ops = &clk_pll_ops;
- pll->clk.parent_names = &pll->parent;
- pll->clk.num_parents = 1;
+ pll->hw.clk.name = name;
+ pll->hw.clk.ops = &clk_pll_ops;
+ pll->hw.clk.parent_names = &pll->parent;
+ pll->hw.clk.num_parents = 1;
pll->base = base;
pll->rate = rate;
pll->power = power;
- ret = clk_register(&pll->clk);
+ ret = bclk_register(&pll->hw.clk);
if (ret)
ERR_PTR(ret);
- return &pll->clk;
+ return &pll->hw.clk;
}
diff --git a/drivers/clk/mxs/clk-ref.c b/drivers/clk/mxs/clk-ref.c
index 16a2fc2991..d483c9c6b2 100644
--- a/drivers/clk/mxs/clk-ref.c
+++ b/drivers/clk/mxs/clk-ref.c
@@ -7,7 +7,7 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <io.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
@@ -23,20 +23,20 @@
* as pll rate * (18 / FRAC), where FRAC = 18 ~ 35.
*/
struct clk_ref {
- struct clk clk;
+ struct clk_hw hw;
const char *parent;
void __iomem *reg;
u8 idx;
};
-#define to_clk_ref(_hw) container_of(_hw, struct clk_ref, clk)
+#define to_clk_ref(_hw) container_of(_hw, struct clk_ref, hw)
#define SET 0x4
#define CLR 0x8
-static int clk_ref_is_enabled(struct clk *clk)
+static int clk_ref_is_enabled(struct clk_hw *hw)
{
- struct clk_ref *ref = to_clk_ref(clk);
+ struct clk_ref *ref = to_clk_ref(hw);
u32 reg = readl(ref->reg);
if (reg & 1 << ((ref->idx + 1) * 8 - 1))
@@ -45,26 +45,26 @@ static int clk_ref_is_enabled(struct clk *clk)
return 1;
}
-static int clk_ref_enable(struct clk *clk)
+static int clk_ref_enable(struct clk_hw *hw)
{
- struct clk_ref *ref = to_clk_ref(clk);
+ struct clk_ref *ref = to_clk_ref(hw);
writel(1 << ((ref->idx + 1) * 8 - 1), ref->reg + CLR);
return 0;
}
-static void clk_ref_disable(struct clk *clk)
+static void clk_ref_disable(struct clk_hw *hw)
{
- struct clk_ref *ref = to_clk_ref(clk);
+ struct clk_ref *ref = to_clk_ref(hw);
writel(1 << ((ref->idx + 1) * 8 - 1), ref->reg + SET);
}
-static unsigned long clk_ref_recalc_rate(struct clk *clk,
+static unsigned long clk_ref_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_ref *ref = to_clk_ref(clk);
+ struct clk_ref *ref = to_clk_ref(hw);
u64 tmp = parent_rate;
u8 frac = (readl(ref->reg) >> (ref->idx * 8)) & 0x3f;
@@ -74,7 +74,7 @@ static unsigned long clk_ref_recalc_rate(struct clk *clk,
return tmp;
}
-static long clk_ref_round_rate(struct clk *clk, unsigned long rate,
+static long clk_ref_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
unsigned long parent_rate = *prate;
@@ -97,10 +97,10 @@ static long clk_ref_round_rate(struct clk *clk, unsigned long rate,
return tmp;
}
-static int clk_ref_set_rate(struct clk *clk, unsigned long rate,
+static int clk_ref_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct clk_ref *ref = to_clk_ref(clk);
+ struct clk_ref *ref = to_clk_ref(hw);
u64 tmp = parent_rate;
u32 val;
u32 frac, shift = ref->idx * 8;
@@ -140,17 +140,17 @@ struct clk *mxs_clk_ref(const char *name, const char *parent_name,
ref = xzalloc(sizeof(*ref));
ref->parent = parent_name;
- ref->clk.name = name;
- ref->clk.ops = &clk_ref_ops;
- ref->clk.parent_names = &ref->parent;
- ref->clk.num_parents = 1;
+ ref->hw.clk.name = name;
+ ref->hw.clk.ops = &clk_ref_ops;
+ ref->hw.clk.parent_names = &ref->parent;
+ ref->hw.clk.num_parents = 1;
ref->reg = reg;
ref->idx = idx;
- ret = clk_register(&ref->clk);
+ ret = bclk_register(&ref->hw.clk);
if (ret)
return ERR_PTR(ret);
- return &ref->clk;
+ return &ref->hw.clk;
}
diff --git a/drivers/clk/mxs/clk.h b/drivers/clk/mxs/clk.h
index 60f2408cba..a93361a9ea 100644
--- a/drivers/clk/mxs/clk.h
+++ b/drivers/clk/mxs/clk.h
@@ -35,7 +35,7 @@ static inline struct clk *mxs_clk_fixed(const char *name, int rate)
static inline struct clk *mxs_clk_gate(const char *name,
const char *parent_name, void __iomem *reg, u8 shift)
{
- return clk_gate_inverted(name, parent_name, reg, shift, 0);
+ return clk_gate_inverted(name, parent_name, reg, shift, CLK_SET_RATE_PARENT);
}
static inline struct clk *mxs_clk_mux(const char *name, void __iomem *reg,
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index 5fcf0c2515..f01014da0c 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -1,4 +1,8 @@
# SPDX-License-Identifier: GPL-2.0-only
-obj-y += clk-cpu.o clk-pll.o clk.o
+obj-y += clk-cpu.o clk-pll.o clk.o clk-muxgrf.o clk-mmc-phase.o clk-inverter.o
+obj-$(CONFIG_RESET_CONTROLLER) += softrst.o
obj-$(CONFIG_ARCH_RK3188) += clk-rk3188.o
obj-$(CONFIG_ARCH_RK3288) += clk-rk3288.o
+obj-$(CONFIG_ARCH_RK3399) += clk-rk3399.o
+obj-$(CONFIG_ARCH_RK3568) += clk-rk3568.o
+obj-$(CONFIG_ARCH_RK3588) += clk-rk3588.o rst-rk3588.o
diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c
index 71a64f71f6..8b5d4a0330 100644
--- a/drivers/clk/rockchip/clk-cpu.c
+++ b/drivers/clk/rockchip/clk-cpu.c
@@ -34,8 +34,10 @@
#include <malloc.h>
#include <io.h>
#include <xfuncs.h>
-#include "clk.h"
#include <linux/barebox-wrapper.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+#include "clk.h"
/**
* struct rockchip_cpuclk: information about clock supplied to a CPU core.
@@ -43,31 +45,34 @@
* @alt_parent: alternate parent clock to use when switching the speed
* of the primary parent clock.
* @reg_base: base register for cpu-clock values.
+ * @clk_nb: clock notifier registered for changes in clock speed of the
+ * primary parent clock.
* @rate_count: number of rates in the rate_table
* @rate_table: pll-rates and their associated dividers
* @reg_data: cpu-specific register settings
+ * @lock: clock lock
*/
struct rockchip_cpuclk {
- struct clk hw;
-
+ struct clk_hw hw;
struct clk *alt_parent;
void __iomem *reg_base;
unsigned int rate_count;
struct rockchip_cpuclk_rate_table *rate_table;
const struct rockchip_cpuclk_reg_data *reg_data;
+ spinlock_t *lock;
};
#define to_rockchip_cpuclk_hw(hw) container_of(hw, struct rockchip_cpuclk, hw)
-static unsigned long rockchip_cpuclk_recalc_rate(struct clk *hw,
+static unsigned long rockchip_cpuclk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct rockchip_cpuclk *cpuclk = to_rockchip_cpuclk_hw(hw);
const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data;
- u32 clksel0 = readl(cpuclk->reg_base + reg_data->core_reg);
+ u32 clksel0 = readl_relaxed(cpuclk->reg_base + reg_data->core_reg[0]);
- clksel0 >>= reg_data->div_core_shift;
- clksel0 &= reg_data->div_core_mask;
+ clksel0 >>= reg_data->div_core_shift[0];
+ clksel0 &= reg_data->div_core_mask[0];
return parent_rate / (clksel0 + 1);
}
@@ -76,17 +81,18 @@ static const struct clk_ops rockchip_cpuclk_ops = {
};
struct clk *rockchip_clk_register_cpuclk(const char *name,
- const char **parent_names, u8 num_parents,
+ const char *const *parent_names, u8 num_parents,
const struct rockchip_cpuclk_reg_data *reg_data,
const struct rockchip_cpuclk_rate_table *rates,
- int nrates, void __iomem *reg_base)
+ int nrates, void __iomem *reg_base, spinlock_t *lock)
{
struct rockchip_cpuclk *cpuclk;
- struct clk *clk;
+ struct clk_init_data init;
+ struct clk *clk, *cclk;
int ret;
- if (num_parents != 2) {
- pr_err("%s: needs two parent clocks\n", __func__);
+ if (num_parents < 2) {
+ pr_err("%s: needs at least two parent clocks\n", __func__);
return ERR_PTR(-EINVAL);
}
@@ -94,21 +100,28 @@ struct clk *rockchip_clk_register_cpuclk(const char *name,
if (!cpuclk)
return ERR_PTR(-ENOMEM);
- cpuclk->hw.name = name;
- cpuclk->hw.parent_names = &parent_names[0];
- cpuclk->hw.num_parents = 1;
- cpuclk->hw.ops = &rockchip_cpuclk_ops;
+ init.name = name;
+ init.parent_names = &parent_names[reg_data->mux_core_main];
+ init.num_parents = 1;
+ init.ops = &rockchip_cpuclk_ops;
/* only allow rate changes when we have a rate table */
- cpuclk->hw.flags = (nrates > 0) ? CLK_SET_RATE_PARENT : 0;
+ init.flags = (nrates > 0) ? CLK_SET_RATE_PARENT : 0;
+
+ /* disallow automatic parent changes by ccf */
+ init.flags |= CLK_SET_RATE_NO_REPARENT;
+
+ init.flags |= CLK_GET_RATE_NOCACHE;
cpuclk->reg_base = reg_base;
+ cpuclk->lock = lock;
cpuclk->reg_data = reg_data;
+ cpuclk->hw.init = &init;
- cpuclk->alt_parent = __clk_lookup(parent_names[1]);
+ cpuclk->alt_parent = __clk_lookup(parent_names[reg_data->mux_core_alt]);
if (!cpuclk->alt_parent) {
- pr_err("%s: could not lookup alternate parent\n",
- __func__);
+ pr_err("%s: could not lookup alternate parent: (%d)\n",
+ __func__, reg_data->mux_core_alt);
ret = -EINVAL;
goto free_cpuclk;
}
@@ -120,37 +133,40 @@ struct clk *rockchip_clk_register_cpuclk(const char *name,
goto free_cpuclk;
}
- clk = __clk_lookup(parent_names[0]);
+ clk = __clk_lookup(parent_names[reg_data->mux_core_main]);
if (!clk) {
- pr_err("%s: could not lookup parent clock %s\n",
- __func__, parent_names[0]);
+ pr_err("%s: could not lookup parent clock: (%d) %s\n",
+ __func__, reg_data->mux_core_main,
+ parent_names[reg_data->mux_core_main]);
ret = -EINVAL;
- goto free_cpuclk;
+ goto free_alt_parent;
}
if (nrates > 0) {
cpuclk->rate_count = nrates;
- cpuclk->rate_table = xmemdup(rates,
- sizeof(*rates) * nrates
- );
+ cpuclk->rate_table = kmemdup(rates,
+ sizeof(*rates) * nrates,
+ GFP_KERNEL);
if (!cpuclk->rate_table) {
- pr_err("%s: could not allocate memory for cpuclk rates\n",
- __func__);
ret = -ENOMEM;
- goto free_cpuclk;
+ goto unregister_notifier;
}
}
- ret = clk_register(&cpuclk->hw);
- if (ret) {
+ cclk = clk_register(NULL, &cpuclk->hw);
+ if (IS_ERR(cclk)) {
pr_err("%s: could not register cpuclk %s\n", __func__, name);
+ ret = PTR_ERR(cclk);
goto free_rate_table;
}
- return &cpuclk->hw;
+ return cclk;
free_rate_table:
kfree(cpuclk->rate_table);
+unregister_notifier:
+free_alt_parent:
+ clk_disable(cpuclk->alt_parent);
free_cpuclk:
kfree(cpuclk);
return ERR_PTR(ret);
diff --git a/drivers/clk/rockchip/clk-inverter.c b/drivers/clk/rockchip/clk-inverter.c
new file mode 100644
index 0000000000..ea72d8c6b2
--- /dev/null
+++ b/drivers/clk/rockchip/clk-inverter.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2015 Heiko Stuebner <heiko@sntech.de>
+ */
+
+#include <common.h>
+#include <of.h>
+#include <malloc.h>
+#include <io.h>
+#include <xfuncs.h>
+#include <linux/barebox-wrapper.h>
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/spinlock.h>
+#include "clk.h"
+
+struct rockchip_inv_clock {
+ struct clk_hw hw;
+ void __iomem *reg;
+ int shift;
+ int flags;
+ spinlock_t *lock;
+};
+
+#define to_inv_clock(_hw) container_of(_hw, struct rockchip_inv_clock, hw)
+
+#define INVERTER_MASK 0x1
+
+static int rockchip_inv_get_phase(struct clk_hw *hw)
+{
+ struct rockchip_inv_clock *inv_clock = to_inv_clock(hw);
+ u32 val;
+
+ val = readl(inv_clock->reg) >> inv_clock->shift;
+ val &= INVERTER_MASK;
+ return val ? 180 : 0;
+}
+
+static int rockchip_inv_set_phase(struct clk_hw *hw, int degrees)
+{
+ struct rockchip_inv_clock *inv_clock = to_inv_clock(hw);
+ u32 val;
+
+ if (degrees % 180 == 0) {
+ val = !!degrees;
+ } else {
+ pr_err("%s: unsupported phase %d for %s\n",
+ __func__, degrees, clk_hw_get_name(hw));
+ return -EINVAL;
+ }
+
+ if (inv_clock->flags & ROCKCHIP_INVERTER_HIWORD_MASK) {
+ writel(HIWORD_UPDATE(val, INVERTER_MASK, inv_clock->shift),
+ inv_clock->reg);
+ } else {
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(inv_clock->lock, flags);
+
+ reg = readl(inv_clock->reg);
+ reg &= ~BIT(inv_clock->shift);
+ reg |= val;
+ writel(reg, inv_clock->reg);
+
+ spin_unlock_irqrestore(inv_clock->lock, flags);
+ }
+
+ return 0;
+}
+
+static const struct clk_ops rockchip_inv_clk_ops = {
+ .get_phase = rockchip_inv_get_phase,
+ .set_phase = rockchip_inv_set_phase,
+};
+
+struct clk *rockchip_clk_register_inverter(const char *name,
+ const char *const *parent_names, u8 num_parents,
+ void __iomem *reg, int shift, int flags,
+ spinlock_t *lock)
+{
+ struct clk_init_data init;
+ struct rockchip_inv_clock *inv_clock;
+ struct clk *clk;
+
+ inv_clock = kzalloc(sizeof(*inv_clock), GFP_KERNEL);
+ if (!inv_clock)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.num_parents = num_parents;
+ init.flags = CLK_SET_RATE_PARENT;
+ init.parent_names = parent_names;
+ init.ops = &rockchip_inv_clk_ops;
+
+ inv_clock->hw.init = &init;
+ inv_clock->reg = reg;
+ inv_clock->shift = shift;
+ inv_clock->flags = flags;
+ inv_clock->lock = lock;
+
+ clk = clk_register(NULL, &inv_clock->hw);
+ if (IS_ERR(clk))
+ kfree(inv_clock);
+
+ return clk;
+}
diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c
new file mode 100644
index 0000000000..822189a2fd
--- /dev/null
+++ b/drivers/clk/rockchip/clk-mmc-phase.c
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2014 Google, Inc
+ * Author: Alexandru M Stan <amstan@chromium.org>
+ */
+
+#include <common.h>
+#include <of.h>
+#include <malloc.h>
+#include <io.h>
+#include <xfuncs.h>
+#include <linux/barebox-wrapper.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+#include "clk.h"
+
+struct rockchip_mmc_clock {
+ struct clk_hw hw;
+ void __iomem *reg;
+ int id;
+ int shift;
+ int cached_phase;
+};
+
+#define to_mmc_clock(_hw) container_of(_hw, struct rockchip_mmc_clock, hw)
+
+#define RK3288_MMC_CLKGEN_DIV 2
+
+static unsigned long rockchip_mmc_recalc(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return parent_rate / RK3288_MMC_CLKGEN_DIV;
+}
+
+#define ROCKCHIP_MMC_DELAY_SEL BIT(10)
+#define ROCKCHIP_MMC_DEGREE_MASK 0x3
+#define ROCKCHIP_MMC_DELAYNUM_OFFSET 2
+#define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
+
+#define PSECS_PER_SEC 1000000000000LL
+
+/*
+ * Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
+ * simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
+ */
+#define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
+
+static int rockchip_mmc_get_phase(struct clk_hw *hw)
+{
+ struct rockchip_mmc_clock *mmc_clock = to_mmc_clock(hw);
+ unsigned long rate = clk_hw_get_rate(hw);
+ u32 raw_value;
+ u16 degrees;
+ u32 delay_num = 0;
+
+ /* Constant signal, no measurable phase shift */
+ if (!rate)
+ return 0;
+
+ raw_value = readl(mmc_clock->reg) >> (mmc_clock->shift);
+
+ degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
+
+ if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
+ /* degrees/delaynum * 1000000 */
+ unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
+ 36 * (rate / 10000);
+
+ delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
+ delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
+ degrees += DIV_ROUND_CLOSEST(delay_num * factor, 1000000);
+ }
+
+ return degrees % 360;
+}
+
+static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
+{
+ struct rockchip_mmc_clock *mmc_clock = to_mmc_clock(hw);
+ unsigned long rate = clk_hw_get_rate(hw);
+ u8 nineties, remainder;
+ u8 delay_num;
+ u32 raw_value;
+ u32 delay;
+
+ /*
+ * The below calculation is based on the output clock from
+ * MMC host to the card, which expects the phase clock inherits
+ * the clock rate from its parent, namely the output clock
+ * provider of MMC host. However, things may go wrong if
+ * (1) It is orphan.
+ * (2) It is assigned to the wrong parent.
+ *
+ * This check help debug the case (1), which seems to be the
+ * most likely problem we often face and which makes it difficult
+ * for people to debug unstable mmc tuning results.
+ */
+ if (!rate) {
+ pr_err("%s: invalid clk rate\n", __func__);
+ return -EINVAL;
+ }
+
+ nineties = degrees / 90;
+ remainder = (degrees % 90);
+
+ /*
+ * Due to the inexact nature of the "fine" delay, we might
+ * actually go non-monotonic. We don't go _too_ monotonic
+ * though, so we should be OK. Here are options of how we may
+ * work:
+ *
+ * Ideally we end up with:
+ * 1.0, 2.0, ..., 69.0, 70.0, ..., 89.0, 90.0
+ *
+ * On one extreme (if delay is actually 44ps):
+ * .73, 1.5, ..., 50.6, 51.3, ..., 65.3, 90.0
+ * The other (if delay is actually 77ps):
+ * 1.3, 2.6, ..., 88.6. 89.8, ..., 114.0, 90
+ *
+ * It's possible we might make a delay that is up to 25
+ * degrees off from what we think we're making. That's OK
+ * though because we should be REALLY far from any bad range.
+ */
+
+ /*
+ * Convert to delay; do a little extra work to make sure we
+ * don't overflow 32-bit / 64-bit numbers.
+ */
+ delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
+ delay *= remainder;
+ delay = DIV_ROUND_CLOSEST(delay,
+ (rate / 1000) * 36 *
+ (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
+
+ delay_num = (u8) min_t(u32, delay, 255);
+
+ raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
+ raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
+ raw_value |= nineties;
+ writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift),
+ mmc_clock->reg);
+
+ pr_debug("%s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d\n",
+ clk_hw_get_name(hw), degrees, delay_num,
+ mmc_clock->reg, raw_value>>(mmc_clock->shift),
+ rockchip_mmc_get_phase(hw)
+ );
+
+ return 0;
+}
+
+static const struct clk_ops rockchip_mmc_clk_ops = {
+ .recalc_rate = rockchip_mmc_recalc,
+ .get_phase = rockchip_mmc_get_phase,
+ .set_phase = rockchip_mmc_set_phase,
+};
+
+struct clk *rockchip_clk_register_mmc(const char *name,
+ const char *const *parent_names, u8 num_parents,
+ void __iomem *reg, int shift)
+{
+ struct clk_init_data init;
+ struct rockchip_mmc_clock *mmc_clock;
+ struct clk *clk;
+ int ret;
+
+ mmc_clock = kzalloc(sizeof(*mmc_clock), GFP_KERNEL);
+ if (!mmc_clock)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.flags = 0;
+ init.num_parents = num_parents;
+ init.parent_names = parent_names;
+ init.ops = &rockchip_mmc_clk_ops;
+
+ mmc_clock->hw.init = &init;
+ mmc_clock->reg = reg;
+ mmc_clock->shift = shift;
+
+ clk = clk_register(NULL, &mmc_clock->hw);
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ goto err_register;
+ }
+
+ return clk;
+
+err_register:
+ kfree(mmc_clock);
+ return ERR_PTR(ret);
+}
diff --git a/drivers/clk/rockchip/clk-muxgrf.c b/drivers/clk/rockchip/clk-muxgrf.c
new file mode 100644
index 0000000000..e81761422f
--- /dev/null
+++ b/drivers/clk/rockchip/clk-muxgrf.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <common.h>
+#include <of.h>
+#include <malloc.h>
+#include <io.h>
+#include <xfuncs.h>
+#include <linux/barebox-wrapper.h>
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/spinlock.h>
+#include "clk.h"
+
+struct rockchip_muxgrf_clock {
+ struct clk_hw hw;
+ struct regmap *regmap;
+ u32 reg;
+ u32 shift;
+ u32 width;
+ int flags;
+};
+
+#define to_muxgrf_clock(_hw) container_of(_hw, struct rockchip_muxgrf_clock, hw)
+
+static int rockchip_muxgrf_get_parent(struct clk_hw *hw)
+{
+ struct rockchip_muxgrf_clock *mux = to_muxgrf_clock(hw);
+ unsigned int mask = GENMASK(mux->width - 1, 0);
+ unsigned int val;
+
+ regmap_read(mux->regmap, mux->reg, &val);
+
+ val >>= mux->shift;
+ val &= mask;
+
+ return val;
+}
+
+static int rockchip_muxgrf_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct rockchip_muxgrf_clock *mux = to_muxgrf_clock(hw);
+ unsigned int mask = GENMASK(mux->width + mux->shift - 1, mux->shift);
+ unsigned int val;
+
+ val = index;
+ val <<= mux->shift;
+
+ if (mux->flags & CLK_MUX_HIWORD_MASK)
+ return regmap_write(mux->regmap, mux->reg, val | (mask << 16));
+ else
+ return regmap_update_bits(mux->regmap, mux->reg, mask, val);
+}
+
+static const struct clk_ops rockchip_muxgrf_clk_ops = {
+ .get_parent = rockchip_muxgrf_get_parent,
+ .set_parent = rockchip_muxgrf_set_parent,
+};
+
+struct clk *rockchip_clk_register_muxgrf(const char *name,
+ const char *const *parent_names, u8 num_parents,
+ int flags, struct regmap *regmap, int reg,
+ int shift, int width, int mux_flags)
+{
+ struct rockchip_muxgrf_clock *muxgrf_clock;
+ struct clk_init_data init;
+ struct clk *clk;
+
+ if (IS_ERR(regmap)) {
+ pr_err("%s: regmap not available\n", __func__);
+ return ERR_PTR(-ENOTSUPP);
+ }
+
+ muxgrf_clock = kzalloc(sizeof(*muxgrf_clock), GFP_KERNEL);
+ if (!muxgrf_clock)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.flags = flags;
+ init.num_parents = num_parents;
+ init.parent_names = parent_names;
+ init.ops = &rockchip_muxgrf_clk_ops;
+
+ muxgrf_clock->hw.init = &init;
+ muxgrf_clock->regmap = regmap;
+ muxgrf_clock->reg = reg;
+ muxgrf_clock->shift = shift;
+ muxgrf_clock->width = width;
+ muxgrf_clock->flags = mux_flags;
+
+ clk = clk_register(NULL, &muxgrf_clock->hw);
+ if (IS_ERR(clk))
+ kfree(muxgrf_clock);
+
+ return clk;
+}
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index 8d3fd6cf1c..b4152b03b1 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -2,9 +2,12 @@
/*
* Copyright (c) 2014 MundoReader S.L.
* Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
+ * Author: Xing Zheng <zhengxing@rock-chips.com>
*/
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <common.h>
#include <io.h>
#include <linux/list.h>
@@ -14,16 +17,19 @@
#include <linux/barebox-wrapper.h>
#include "clk.h"
#include <xfuncs.h>
+#include <linux/regmap.h>
+#include <linux/iopoll.h>
-#define PLL_MODE_MASK 0x3
+#define PLL_MODE_WIDTH 2
#define PLL_MODE_SLOW 0x0
#define PLL_MODE_NORM 0x1
#define PLL_MODE_DEEP 0x2
+#define PLL_RK3328_MODE_WIDTH 1
struct rockchip_clk_pll {
- struct clk hw;
+ struct clk_hw hw;
- struct clk pll_mux;
+ struct clk_mux pll_mux;
const struct clk_ops *pll_mux_ops;
void __iomem *reg_base;
@@ -33,7 +39,9 @@ struct rockchip_clk_pll {
u8 flags;
const struct rockchip_pll_rate_table *rate_table;
unsigned int rate_count;
- char pll_name[20];
+ spinlock_t *lock;
+
+ struct rockchip_clk_provider *ctx;
};
#define to_rockchip_clk_pll(_hw) container_of(_hw, struct rockchip_clk_pll, hw)
@@ -52,7 +60,7 @@ static const struct rockchip_pll_rate_table *rockchip_get_pll_settings(
return NULL;
}
-static long rockchip_pll_round_rate(struct clk *hw,
+static long rockchip_pll_round_rate(struct clk_hw *hw,
unsigned long drate, unsigned long *prate)
{
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
@@ -74,26 +82,282 @@ static long rockchip_pll_round_rate(struct clk *hw,
* The calling set_rate function is responsible for making sure the
* grf regmap is available.
*/
-#define RK3188_PLL_LOCK_REG 0x200080ac
-
static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)
{
- int delay = 24000000;
- int val;
+ struct regmap *grf = pll->ctx->grf;
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read_poll_timeout(grf, pll->lock_offset, val,
+ val & BIT(pll->lock_shift), 1000);
+ if (ret)
+ pr_err("%s: timeout waiting for pll to lock\n", __func__);
+
+ return ret;
+}
+
+/*
+ * PLL used in RK3036
+ */
+
+#define RK3036_PLLCON(i) (i * 0x4)
+#define RK3036_PLLCON0_FBDIV_MASK 0xfff
+#define RK3036_PLLCON0_FBDIV_SHIFT 0
+#define RK3036_PLLCON0_POSTDIV1_MASK 0x7
+#define RK3036_PLLCON0_POSTDIV1_SHIFT 12
+#define RK3036_PLLCON1_REFDIV_MASK 0x3f
+#define RK3036_PLLCON1_REFDIV_SHIFT 0
+#define RK3036_PLLCON1_POSTDIV2_MASK 0x7
+#define RK3036_PLLCON1_POSTDIV2_SHIFT 6
+#define RK3036_PLLCON1_LOCK_STATUS BIT(10)
+#define RK3036_PLLCON1_DSMPD_MASK 0x1
+#define RK3036_PLLCON1_DSMPD_SHIFT 12
+#define RK3036_PLLCON1_PWRDOWN BIT(13)
+#define RK3036_PLLCON2_FRAC_MASK 0xffffff
+#define RK3036_PLLCON2_FRAC_SHIFT 0
+
+static int rockchip_rk3036_pll_wait_lock(struct rockchip_clk_pll *pll)
+{
+ u32 pllcon;
+ int ret;
+
+ /*
+ * Lock time typical 250, max 500 input clock cycles @24MHz
+ * So define a very safe maximum of 1000us, meaning 24000 cycles.
+ */
+ ret = readl_poll_timeout(pll->reg_base + RK3036_PLLCON(1),
+ pllcon,
+ pllcon & RK3036_PLLCON1_LOCK_STATUS,
+ 1000);
+ if (ret)
+ pr_err("%s: timeout waiting for pll to lock\n", __func__);
+
+ return ret;
+}
+
+static void rockchip_rk3036_pll_get_params(struct rockchip_clk_pll *pll,
+ struct rockchip_pll_rate_table *rate)
+{
+ u32 pllcon;
+
+ pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(0));
+ rate->fbdiv = ((pllcon >> RK3036_PLLCON0_FBDIV_SHIFT)
+ & RK3036_PLLCON0_FBDIV_MASK);
+ rate->postdiv1 = ((pllcon >> RK3036_PLLCON0_POSTDIV1_SHIFT)
+ & RK3036_PLLCON0_POSTDIV1_MASK);
+
+ pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(1));
+ rate->refdiv = ((pllcon >> RK3036_PLLCON1_REFDIV_SHIFT)
+ & RK3036_PLLCON1_REFDIV_MASK);
+ rate->postdiv2 = ((pllcon >> RK3036_PLLCON1_POSTDIV2_SHIFT)
+ & RK3036_PLLCON1_POSTDIV2_MASK);
+ rate->dsmpd = ((pllcon >> RK3036_PLLCON1_DSMPD_SHIFT)
+ & RK3036_PLLCON1_DSMPD_MASK);
+
+ pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2));
+ rate->frac = ((pllcon >> RK3036_PLLCON2_FRAC_SHIFT)
+ & RK3036_PLLCON2_FRAC_MASK);
+}
+
+static unsigned long rockchip_rk3036_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long prate)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ struct rockchip_pll_rate_table cur;
+ u64 rate64 = prate;
+
+ rockchip_rk3036_pll_get_params(pll, &cur);
+
+ rate64 *= cur.fbdiv;
+ do_div(rate64, cur.refdiv);
+
+ if (cur.dsmpd == 0) {
+ /* fractional mode */
+ u64 frac_rate64 = prate * cur.frac;
+
+ do_div(frac_rate64, cur.refdiv);
+ rate64 += frac_rate64 >> 24;
+ }
+
+ do_div(rate64, cur.postdiv1);
+ do_div(rate64, cur.postdiv2);
+
+ return (unsigned long)rate64;
+}
+
+static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll,
+ const struct rockchip_pll_rate_table *rate)
+{
+ const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
+ struct clk_mux *pll_mux = &pll->pll_mux;
+ struct rockchip_pll_rate_table cur;
+ u32 pllcon;
+ int rate_change_remuxed = 0;
+ int cur_parent;
+ int ret;
+
+ pr_debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
+ __func__, rate->rate, rate->fbdiv, rate->postdiv1, rate->refdiv,
+ rate->postdiv2, rate->dsmpd, rate->frac);
+
+ rockchip_rk3036_pll_get_params(pll, &cur);
+ cur.rate = 0;
+
+ cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
+ if (cur_parent == PLL_MODE_NORM) {
+ pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
+ rate_change_remuxed = 1;
+ }
+
+ /* update pll values */
+ writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3036_PLLCON0_FBDIV_MASK,
+ RK3036_PLLCON0_FBDIV_SHIFT) |
+ HIWORD_UPDATE(rate->postdiv1, RK3036_PLLCON0_POSTDIV1_MASK,
+ RK3036_PLLCON0_POSTDIV1_SHIFT),
+ pll->reg_base + RK3036_PLLCON(0));
+
+ writel_relaxed(HIWORD_UPDATE(rate->refdiv, RK3036_PLLCON1_REFDIV_MASK,
+ RK3036_PLLCON1_REFDIV_SHIFT) |
+ HIWORD_UPDATE(rate->postdiv2, RK3036_PLLCON1_POSTDIV2_MASK,
+ RK3036_PLLCON1_POSTDIV2_SHIFT) |
+ HIWORD_UPDATE(rate->dsmpd, RK3036_PLLCON1_DSMPD_MASK,
+ RK3036_PLLCON1_DSMPD_SHIFT),
+ pll->reg_base + RK3036_PLLCON(1));
+
+ /* GPLL CON2 is not HIWORD_MASK */
+ pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2));
+ pllcon &= ~(RK3036_PLLCON2_FRAC_MASK << RK3036_PLLCON2_FRAC_SHIFT);
+ pllcon |= rate->frac << RK3036_PLLCON2_FRAC_SHIFT;
+ writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2));
/* wait for the pll to lock */
- while (delay > 0) {
- val = readl(RK3188_PLL_LOCK_REG);
- if (val & BIT(pll->lock_shift))
+ ret = rockchip_rk3036_pll_wait_lock(pll);
+ if (ret) {
+ pr_warn("%s: pll update unsuccessful, trying to restore old params\n",
+ __func__);
+ rockchip_rk3036_pll_set_params(pll, &cur);
+ }
+
+ if (rate_change_remuxed)
+ pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
+
+ return ret;
+}
+
+static int rockchip_rk3036_pll_set_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long prate)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ const struct rockchip_pll_rate_table *rate;
+
+ pr_debug("%s: changing %s to %lu with a parent rate of %lu\n",
+ __func__, clk_hw_get_name(hw), drate, prate);
+
+ /* Get required rate settings from table */
+ rate = rockchip_get_pll_settings(pll, drate);
+ if (!rate) {
+ pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+ drate, clk_hw_get_name(hw));
+ return -EINVAL;
+ }
+
+ return rockchip_rk3036_pll_set_params(pll, rate);
+}
+
+static int rockchip_rk3036_pll_enable(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+ writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0),
+ pll->reg_base + RK3036_PLLCON(1));
+ rockchip_rk3036_pll_wait_lock(pll);
+
+ return 0;
+}
+
+static void rockchip_rk3036_pll_disable(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+ writel(HIWORD_UPDATE(RK3036_PLLCON1_PWRDOWN,
+ RK3036_PLLCON1_PWRDOWN, 0),
+ pll->reg_base + RK3036_PLLCON(1));
+}
+
+static int rockchip_rk3036_pll_is_enabled(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ u32 pllcon = readl(pll->reg_base + RK3036_PLLCON(1));
+
+ return !(pllcon & RK3036_PLLCON1_PWRDOWN);
+}
+
+static int rockchip_rk3036_pll_init(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ const struct rockchip_pll_rate_table *rate;
+ struct rockchip_pll_rate_table cur;
+ unsigned long drate;
+
+ if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
+ return 0;
+
+ drate = clk_hw_get_rate(hw);
+ rate = rockchip_get_pll_settings(pll, drate);
+
+ /* when no rate setting for the current rate, rely on clk_set_rate */
+ if (!rate)
+ return 0;
+
+ rockchip_rk3036_pll_get_params(pll, &cur);
+
+ pr_debug("%s: pll %s@%lu: Hz\n", __func__, clk_hw_get_name(hw),
+ drate);
+ pr_debug("old - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
+ cur.fbdiv, cur.postdiv1, cur.refdiv, cur.postdiv2,
+ cur.dsmpd, cur.frac);
+ pr_debug("new - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
+ rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2,
+ rate->dsmpd, rate->frac);
+
+ if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 ||
+ rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 ||
+ rate->dsmpd != cur.dsmpd ||
+ (!cur.dsmpd && (rate->frac != cur.frac))) {
+ struct clk *parent = clk_get_parent(clk_hw_to_clk(hw));
+
+ if (!parent) {
+ pr_warn("%s: parent of %s not available\n",
+ __func__, clk_hw_get_name(hw));
return 0;
- delay--;
+ }
+
+ pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",
+ __func__, clk_hw_get_name(hw));
+ rockchip_rk3036_pll_set_params(pll, rate);
}
- pr_err("%s: timeout waiting for pll to lock\n", __func__);
- return -ETIMEDOUT;
+ return 0;
}
-/**
+static const struct clk_ops rockchip_rk3036_pll_clk_norate_ops = {
+ .recalc_rate = rockchip_rk3036_pll_recalc_rate,
+ .enable = rockchip_rk3036_pll_enable,
+ .disable = rockchip_rk3036_pll_disable,
+ .is_enabled = rockchip_rk3036_pll_is_enabled,
+};
+
+static const struct clk_ops rockchip_rk3036_pll_clk_ops = {
+ .recalc_rate = rockchip_rk3036_pll_recalc_rate,
+ .round_rate = rockchip_pll_round_rate,
+ .set_rate = rockchip_rk3036_pll_set_rate,
+ .enable = rockchip_rk3036_pll_enable,
+ .disable = rockchip_rk3036_pll_disable,
+ .is_enabled = rockchip_rk3036_pll_is_enabled,
+ .init = rockchip_rk3036_pll_init,
+};
+
+/*
* PLL used in RK3066, RK3188 and RK3288
*/
@@ -106,75 +370,75 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)
#define RK3066_PLLCON0_NR_SHIFT 8
#define RK3066_PLLCON1_NF_MASK 0x1fff
#define RK3066_PLLCON1_NF_SHIFT 0
-#define RK3066_PLLCON2_BWADJ_MASK 0xfff
-#define RK3066_PLLCON2_BWADJ_SHIFT 0
+#define RK3066_PLLCON2_NB_MASK 0xfff
+#define RK3066_PLLCON2_NB_SHIFT 0
#define RK3066_PLLCON3_RESET (1 << 5)
#define RK3066_PLLCON3_PWRDOWN (1 << 1)
#define RK3066_PLLCON3_BYPASS (1 << 0)
-static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk *hw,
+static void rockchip_rk3066_pll_get_params(struct rockchip_clk_pll *pll,
+ struct rockchip_pll_rate_table *rate)
+{
+ u32 pllcon;
+
+ pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0));
+ rate->nr = ((pllcon >> RK3066_PLLCON0_NR_SHIFT)
+ & RK3066_PLLCON0_NR_MASK) + 1;
+ rate->no = ((pllcon >> RK3066_PLLCON0_OD_SHIFT)
+ & RK3066_PLLCON0_OD_MASK) + 1;
+
+ pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1));
+ rate->nf = ((pllcon >> RK3066_PLLCON1_NF_SHIFT)
+ & RK3066_PLLCON1_NF_MASK) + 1;
+
+ pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(2));
+ rate->nb = ((pllcon >> RK3066_PLLCON2_NB_SHIFT)
+ & RK3066_PLLCON2_NB_MASK) + 1;
+}
+
+static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk_hw *hw,
unsigned long prate)
{
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
- u64 nf, nr, no, rate64 = prate;
+ struct rockchip_pll_rate_table cur;
+ u64 rate64 = prate;
u32 pllcon;
- pllcon = readl(pll->reg_base + RK3066_PLLCON(3));
+ pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(3));
if (pllcon & RK3066_PLLCON3_BYPASS) {
pr_debug("%s: pll %s is bypassed\n", __func__,
- __clk_get_name(hw));
+ clk_hw_get_name(hw));
return prate;
}
- pllcon = readl(pll->reg_base + RK3066_PLLCON(1));
- nf = (pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK;
+ rockchip_rk3066_pll_get_params(pll, &cur);
- pllcon = readl(pll->reg_base + RK3066_PLLCON(0));
- nr = (pllcon >> RK3066_PLLCON0_NR_SHIFT) & RK3066_PLLCON0_NR_MASK;
- no = (pllcon >> RK3066_PLLCON0_OD_SHIFT) & RK3066_PLLCON0_OD_MASK;
-
- rate64 *= (nf + 1);
- do_div(rate64, nr + 1);
- do_div(rate64, no + 1);
-
- pr_debug("%s: %s rate=%lu\n",
- __func__, hw->name, (unsigned long)rate64);
+ rate64 *= cur.nf;
+ do_div(rate64, cur.nr);
+ do_div(rate64, cur.no);
return (unsigned long)rate64;
}
-static int rockchip_rk3066_pll_set_rate(struct clk *hw, unsigned long drate,
- unsigned long prate)
+static int rockchip_rk3066_pll_set_params(struct rockchip_clk_pll *pll,
+ const struct rockchip_pll_rate_table *rate)
{
- struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
- const struct rockchip_pll_rate_table *rate;
- unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate);
- struct clk *pll_mux = &pll->pll_mux;
const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
+ struct clk_mux *pll_mux = &pll->pll_mux;
+ struct rockchip_pll_rate_table cur;
int rate_change_remuxed = 0;
int cur_parent;
int ret;
- if (old_rate == drate)
- return 0;
-
- pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n",
- __func__, __clk_get_name(hw), old_rate, drate, prate);
-
- /* Get required rate settings from table */
- rate = rockchip_get_pll_settings(pll, drate);
- if (!rate) {
- pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
- drate, __clk_get_name(hw));
- return -EINVAL;
- }
-
pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n",
__func__, rate->rate, rate->nr, rate->no, rate->nf);
- cur_parent = pll_mux_ops->get_parent(pll_mux);
+ rockchip_rk3066_pll_get_params(pll, &cur);
+ cur.rate = 0;
+
+ cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
if (cur_parent == PLL_MODE_NORM) {
- pll_mux_ops->set_parent(pll_mux, PLL_MODE_SLOW);
+ pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
rate_change_remuxed = 1;
}
@@ -189,11 +453,11 @@ static int rockchip_rk3066_pll_set_rate(struct clk *hw, unsigned long drate,
RK3066_PLLCON0_OD_SHIFT),
pll->reg_base + RK3066_PLLCON(0));
- writel(HIWORD_UPDATE(rate->nf - 1, RK3066_PLLCON1_NF_MASK,
+ writel_relaxed(HIWORD_UPDATE(rate->nf - 1, RK3066_PLLCON1_NF_MASK,
RK3066_PLLCON1_NF_SHIFT),
pll->reg_base + RK3066_PLLCON(1));
- writel(HIWORD_UPDATE(rate->bwadj, RK3066_PLLCON2_BWADJ_MASK,
- RK3066_PLLCON2_BWADJ_SHIFT),
+ writel_relaxed(HIWORD_UPDATE(rate->nb - 1, RK3066_PLLCON2_NB_MASK,
+ RK3066_PLLCON2_NB_SHIFT),
pll->reg_base + RK3066_PLLCON(2));
/* leave reset and wait the reset_delay */
@@ -204,28 +468,49 @@ static int rockchip_rk3066_pll_set_rate(struct clk *hw, unsigned long drate,
/* wait for the pll to lock */
ret = rockchip_pll_wait_lock(pll);
if (ret) {
- pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
- __func__, old_rate);
- rockchip_rk3066_pll_set_rate(hw, old_rate, prate);
+ pr_warn("%s: pll update unsuccessful, trying to restore old params\n",
+ __func__);
+ rockchip_rk3066_pll_set_params(pll, &cur);
}
if (rate_change_remuxed)
- pll_mux_ops->set_parent(pll_mux, PLL_MODE_NORM);
+ pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
return ret;
}
-static int rockchip_rk3066_pll_enable(struct clk *hw)
+static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long prate)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ const struct rockchip_pll_rate_table *rate;
+
+ pr_debug("%s: changing %s to %lu with a parent rate of %lu\n",
+ __func__, clk_hw_get_name(hw), drate, prate);
+
+ /* Get required rate settings from table */
+ rate = rockchip_get_pll_settings(pll, drate);
+ if (!rate) {
+ pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+ drate, clk_hw_get_name(hw));
+ return -EINVAL;
+ }
+
+ return rockchip_rk3066_pll_set_params(pll, rate);
+}
+
+static int rockchip_rk3066_pll_enable(struct clk_hw *hw)
{
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
writel(HIWORD_UPDATE(0, RK3066_PLLCON3_PWRDOWN, 0),
pll->reg_base + RK3066_PLLCON(3));
+ rockchip_pll_wait_lock(pll);
return 0;
}
-static void rockchip_rk3066_pll_disable(struct clk *hw)
+static void rockchip_rk3066_pll_disable(struct clk_hw *hw)
{
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
@@ -234,7 +519,7 @@ static void rockchip_rk3066_pll_disable(struct clk *hw)
pll->reg_base + RK3066_PLLCON(3));
}
-static int rockchip_rk3066_pll_is_enabled(struct clk *hw)
+static int rockchip_rk3066_pll_is_enabled(struct clk_hw *hw)
{
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
u32 pllcon = readl(pll->reg_base + RK3066_PLLCON(3));
@@ -242,6 +527,38 @@ static int rockchip_rk3066_pll_is_enabled(struct clk *hw)
return !(pllcon & RK3066_PLLCON3_PWRDOWN);
}
+static int rockchip_rk3066_pll_init(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ const struct rockchip_pll_rate_table *rate;
+ struct rockchip_pll_rate_table cur;
+ unsigned long drate;
+
+ if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
+ return 0;
+
+ drate = clk_hw_get_rate(hw);
+ rate = rockchip_get_pll_settings(pll, drate);
+
+ /* when no rate setting for the current rate, rely on clk_set_rate */
+ if (!rate)
+ return 0;
+
+ rockchip_rk3066_pll_get_params(pll, &cur);
+
+ pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), nb(%d:%d)\n",
+ __func__, clk_hw_get_name(hw), drate, rate->nr, cur.nr,
+ rate->no, cur.no, rate->nf, cur.nf, rate->nb, cur.nb);
+ if (rate->nr != cur.nr || rate->no != cur.no || rate->nf != cur.nf
+ || rate->nb != cur.nb) {
+ pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",
+ __func__, clk_hw_get_name(hw));
+ rockchip_rk3066_pll_set_params(pll, rate);
+ }
+
+ return 0;
+}
+
static const struct clk_ops rockchip_rk3066_pll_clk_norate_ops = {
.recalc_rate = rockchip_rk3066_pll_recalc_rate,
.enable = rockchip_rk3066_pll_enable,
@@ -256,44 +573,562 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = {
.enable = rockchip_rk3066_pll_enable,
.disable = rockchip_rk3066_pll_disable,
.is_enabled = rockchip_rk3066_pll_is_enabled,
+ .init = rockchip_rk3066_pll_init,
+};
+
+/*
+ * PLL used in RK3399
+ */
+
+#define RK3399_PLLCON(i) (i * 0x4)
+#define RK3399_PLLCON0_FBDIV_MASK 0xfff
+#define RK3399_PLLCON0_FBDIV_SHIFT 0
+#define RK3399_PLLCON1_REFDIV_MASK 0x3f
+#define RK3399_PLLCON1_REFDIV_SHIFT 0
+#define RK3399_PLLCON1_POSTDIV1_MASK 0x7
+#define RK3399_PLLCON1_POSTDIV1_SHIFT 8
+#define RK3399_PLLCON1_POSTDIV2_MASK 0x7
+#define RK3399_PLLCON1_POSTDIV2_SHIFT 12
+#define RK3399_PLLCON2_FRAC_MASK 0xffffff
+#define RK3399_PLLCON2_FRAC_SHIFT 0
+#define RK3399_PLLCON2_LOCK_STATUS BIT(31)
+#define RK3399_PLLCON3_PWRDOWN BIT(0)
+#define RK3399_PLLCON3_DSMPD_MASK 0x1
+#define RK3399_PLLCON3_DSMPD_SHIFT 3
+
+static int rockchip_rk3399_pll_wait_lock(struct rockchip_clk_pll *pll)
+{
+ u32 pllcon;
+ int ret;
+
+ /*
+ * Lock time typical 250, max 500 input clock cycles @24MHz
+ * So define a very safe maximum of 1000us, meaning 24000 cycles.
+ */
+ ret = readl_relaxed_poll_timeout(pll->reg_base + RK3399_PLLCON(2),
+ pllcon,
+ pllcon & RK3399_PLLCON2_LOCK_STATUS,
+ 1000);
+ if (ret)
+ pr_err("%s: timeout waiting for pll to lock\n", __func__);
+
+ return ret;
+}
+
+static void rockchip_rk3399_pll_get_params(struct rockchip_clk_pll *pll,
+ struct rockchip_pll_rate_table *rate)
+{
+ u32 pllcon;
+
+ pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(0));
+ rate->fbdiv = ((pllcon >> RK3399_PLLCON0_FBDIV_SHIFT)
+ & RK3399_PLLCON0_FBDIV_MASK);
+
+ pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(1));
+ rate->refdiv = ((pllcon >> RK3399_PLLCON1_REFDIV_SHIFT)
+ & RK3399_PLLCON1_REFDIV_MASK);
+ rate->postdiv1 = ((pllcon >> RK3399_PLLCON1_POSTDIV1_SHIFT)
+ & RK3399_PLLCON1_POSTDIV1_MASK);
+ rate->postdiv2 = ((pllcon >> RK3399_PLLCON1_POSTDIV2_SHIFT)
+ & RK3399_PLLCON1_POSTDIV2_MASK);
+
+ pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2));
+ rate->frac = ((pllcon >> RK3399_PLLCON2_FRAC_SHIFT)
+ & RK3399_PLLCON2_FRAC_MASK);
+
+ pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(3));
+ rate->dsmpd = ((pllcon >> RK3399_PLLCON3_DSMPD_SHIFT)
+ & RK3399_PLLCON3_DSMPD_MASK);
+}
+
+static unsigned long rockchip_rk3399_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long prate)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ struct rockchip_pll_rate_table cur;
+ u64 rate64 = prate;
+
+ rockchip_rk3399_pll_get_params(pll, &cur);
+
+ rate64 *= cur.fbdiv;
+ do_div(rate64, cur.refdiv);
+
+ if (cur.dsmpd == 0) {
+ /* fractional mode */
+ u64 frac_rate64 = prate * cur.frac;
+
+ do_div(frac_rate64, cur.refdiv);
+ rate64 += frac_rate64 >> 24;
+ }
+
+ do_div(rate64, cur.postdiv1);
+ do_div(rate64, cur.postdiv2);
+
+ return (unsigned long)rate64;
+}
+
+static int rockchip_rk3399_pll_set_params(struct rockchip_clk_pll *pll,
+ const struct rockchip_pll_rate_table *rate)
+{
+ const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
+ struct clk_mux *pll_mux = &pll->pll_mux;
+ struct rockchip_pll_rate_table cur;
+ u32 pllcon;
+ int rate_change_remuxed = 0;
+ int cur_parent;
+ int ret;
+
+ pr_debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
+ __func__, rate->rate, rate->fbdiv, rate->postdiv1, rate->refdiv,
+ rate->postdiv2, rate->dsmpd, rate->frac);
+
+ rockchip_rk3399_pll_get_params(pll, &cur);
+ cur.rate = 0;
+
+ cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
+ if (cur_parent == PLL_MODE_NORM) {
+ pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
+ rate_change_remuxed = 1;
+ }
+
+ /* update pll values */
+ writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3399_PLLCON0_FBDIV_MASK,
+ RK3399_PLLCON0_FBDIV_SHIFT),
+ pll->reg_base + RK3399_PLLCON(0));
+
+ writel_relaxed(HIWORD_UPDATE(rate->refdiv, RK3399_PLLCON1_REFDIV_MASK,
+ RK3399_PLLCON1_REFDIV_SHIFT) |
+ HIWORD_UPDATE(rate->postdiv1, RK3399_PLLCON1_POSTDIV1_MASK,
+ RK3399_PLLCON1_POSTDIV1_SHIFT) |
+ HIWORD_UPDATE(rate->postdiv2, RK3399_PLLCON1_POSTDIV2_MASK,
+ RK3399_PLLCON1_POSTDIV2_SHIFT),
+ pll->reg_base + RK3399_PLLCON(1));
+
+ /* xPLL CON2 is not HIWORD_MASK */
+ pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2));
+ pllcon &= ~(RK3399_PLLCON2_FRAC_MASK << RK3399_PLLCON2_FRAC_SHIFT);
+ pllcon |= rate->frac << RK3399_PLLCON2_FRAC_SHIFT;
+ writel_relaxed(pllcon, pll->reg_base + RK3399_PLLCON(2));
+
+ writel_relaxed(HIWORD_UPDATE(rate->dsmpd, RK3399_PLLCON3_DSMPD_MASK,
+ RK3399_PLLCON3_DSMPD_SHIFT),
+ pll->reg_base + RK3399_PLLCON(3));
+
+ /* wait for the pll to lock */
+ ret = rockchip_rk3399_pll_wait_lock(pll);
+ if (ret) {
+ pr_warn("%s: pll update unsuccessful, trying to restore old params\n",
+ __func__);
+ rockchip_rk3399_pll_set_params(pll, &cur);
+ }
+
+ if (rate_change_remuxed)
+ pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
+
+ return ret;
+}
+
+static int rockchip_rk3399_pll_set_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long prate)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ const struct rockchip_pll_rate_table *rate;
+
+ pr_debug("%s: changing %s to %lu with a parent rate of %lu\n",
+ __func__, clk_hw_get_name(hw), drate, prate);
+
+ /* Get required rate settings from table */
+ rate = rockchip_get_pll_settings(pll, drate);
+ if (!rate) {
+ pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+ drate, clk_hw_get_name(hw));
+ return -EINVAL;
+ }
+
+ return rockchip_rk3399_pll_set_params(pll, rate);
+}
+
+static int rockchip_rk3399_pll_enable(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+ writel(HIWORD_UPDATE(0, RK3399_PLLCON3_PWRDOWN, 0),
+ pll->reg_base + RK3399_PLLCON(3));
+ rockchip_rk3399_pll_wait_lock(pll);
+
+ return 0;
+}
+
+static void rockchip_rk3399_pll_disable(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+ writel(HIWORD_UPDATE(RK3399_PLLCON3_PWRDOWN,
+ RK3399_PLLCON3_PWRDOWN, 0),
+ pll->reg_base + RK3399_PLLCON(3));
+}
+
+static int rockchip_rk3399_pll_is_enabled(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ u32 pllcon = readl(pll->reg_base + RK3399_PLLCON(3));
+
+ return !(pllcon & RK3399_PLLCON3_PWRDOWN);
+}
+
+static int rockchip_rk3399_pll_init(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ const struct rockchip_pll_rate_table *rate;
+ struct rockchip_pll_rate_table cur;
+ unsigned long drate;
+
+ if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
+ return 0;
+
+ drate = clk_hw_get_rate(hw);
+ rate = rockchip_get_pll_settings(pll, drate);
+
+ /* when no rate setting for the current rate, rely on clk_set_rate */
+ if (!rate)
+ return 0;
+
+ rockchip_rk3399_pll_get_params(pll, &cur);
+
+ pr_debug("%s: pll %s@%lu: Hz\n", __func__, clk_hw_get_name(hw),
+ drate);
+ pr_debug("old - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
+ cur.fbdiv, cur.postdiv1, cur.refdiv, cur.postdiv2,
+ cur.dsmpd, cur.frac);
+ pr_debug("new - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
+ rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2,
+ rate->dsmpd, rate->frac);
+
+ if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 ||
+ rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 ||
+ rate->dsmpd != cur.dsmpd ||
+ (!cur.dsmpd && (rate->frac != cur.frac))) {
+ struct clk *parent = clk_get_parent(clk_hw_to_clk(hw));
+
+ if (!parent) {
+ pr_warn("%s: parent of %s not available\n",
+ __func__, clk_hw_get_name(hw));
+ return 0;
+ }
+
+ pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",
+ __func__, clk_hw_get_name(hw));
+ rockchip_rk3399_pll_set_params(pll, rate);
+ }
+
+ return 0;
+}
+
+static const struct clk_ops rockchip_rk3399_pll_clk_norate_ops = {
+ .recalc_rate = rockchip_rk3399_pll_recalc_rate,
+ .enable = rockchip_rk3399_pll_enable,
+ .disable = rockchip_rk3399_pll_disable,
+ .is_enabled = rockchip_rk3399_pll_is_enabled,
+};
+
+static const struct clk_ops rockchip_rk3399_pll_clk_ops = {
+ .recalc_rate = rockchip_rk3399_pll_recalc_rate,
+ .round_rate = rockchip_pll_round_rate,
+ .set_rate = rockchip_rk3399_pll_set_rate,
+ .enable = rockchip_rk3399_pll_enable,
+ .disable = rockchip_rk3399_pll_disable,
+ .is_enabled = rockchip_rk3399_pll_is_enabled,
+ .init = rockchip_rk3399_pll_init,
+};
+
+/*
+ * PLL used in RK3588
+ */
+
+#define RK3588_PLLCON(i) (i * 0x4)
+#define RK3588_PLLCON0_M_MASK 0x3ff
+#define RK3588_PLLCON0_M_SHIFT 0
+#define RK3588_PLLCON1_P_MASK 0x3f
+#define RK3588_PLLCON1_P_SHIFT 0
+#define RK3588_PLLCON1_S_MASK 0x7
+#define RK3588_PLLCON1_S_SHIFT 6
+#define RK3588_PLLCON2_K_MASK 0xffff
+#define RK3588_PLLCON2_K_SHIFT 0
+#define RK3588_PLLCON1_PWRDOWN BIT(13)
+#define RK3588_PLLCON6_LOCK_STATUS BIT(15)
+
+static int rockchip_rk3588_pll_wait_lock(struct rockchip_clk_pll *pll)
+{
+ u32 pllcon;
+ int ret;
+
+ /*
+ * Lock time typical 250, max 500 input clock cycles @24MHz
+ * So define a very safe maximum of 1000us, meaning 24000 cycles.
+ */
+ ret = readl_poll_timeout(pll->reg_base + RK3588_PLLCON(6),
+ pllcon,
+ pllcon & RK3588_PLLCON6_LOCK_STATUS,
+ 1000);
+ if (ret)
+ pr_err("%s: timeout waiting for pll to lock\n", __func__);
+
+ return ret;
+}
+
+static void rockchip_rk3588_pll_get_params(struct rockchip_clk_pll *pll,
+ struct rockchip_pll_rate_table *rate)
+{
+ u32 pllcon;
+
+ pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(0));
+ rate->m = ((pllcon >> RK3588_PLLCON0_M_SHIFT) & RK3588_PLLCON0_M_MASK);
+
+ pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(1));
+ rate->p = ((pllcon >> RK3588_PLLCON1_P_SHIFT) & RK3588_PLLCON1_P_MASK);
+ rate->s = ((pllcon >> RK3588_PLLCON1_S_SHIFT) & RK3588_PLLCON1_S_MASK);
+
+ pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(2));
+ rate->k = ((pllcon >> RK3588_PLLCON2_K_SHIFT) & RK3588_PLLCON2_K_MASK);
+}
+
+static unsigned long rockchip_rk3588_pll_recalc_rate(struct clk_hw *hw, unsigned long prate)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ struct rockchip_pll_rate_table cur;
+ u64 rate64 = prate, postdiv;
+
+ rockchip_rk3588_pll_get_params(pll, &cur);
+
+ rate64 *= cur.m;
+ do_div(rate64, cur.p);
+
+ if (cur.k) {
+ /* fractional mode */
+ u64 frac_rate64 = prate * cur.k;
+
+ postdiv = cur.p * 65535;
+ do_div(frac_rate64, postdiv);
+ rate64 += frac_rate64;
+ }
+ rate64 = rate64 >> cur.s;
+
+ return (unsigned long)rate64;
+}
+
+static int rockchip_rk3588_pll_set_params(struct rockchip_clk_pll *pll,
+ const struct rockchip_pll_rate_table *rate)
+{
+ const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
+ struct clk_mux *pll_mux = &pll->pll_mux;
+ struct rockchip_pll_rate_table cur;
+ int rate_change_remuxed = 0;
+ int cur_parent;
+ int ret;
+
+ pr_debug("%s: rate settings for %lu p: %d, m: %d, s: %d, k: %d\n",
+ __func__, rate->rate, rate->p, rate->m, rate->s, rate->k);
+
+ rockchip_rk3588_pll_get_params(pll, &cur);
+ cur.rate = 0;
+
+ if (pll->type == pll_rk3588) {
+ cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
+ if (cur_parent == PLL_MODE_NORM) {
+ pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
+ rate_change_remuxed = 1;
+ }
+ }
+
+ /* set pll power down */
+ writel(HIWORD_UPDATE(RK3588_PLLCON1_PWRDOWN,
+ RK3588_PLLCON1_PWRDOWN, 0),
+ pll->reg_base + RK3399_PLLCON(1));
+
+ /* update pll values */
+ writel_relaxed(HIWORD_UPDATE(rate->m, RK3588_PLLCON0_M_MASK, RK3588_PLLCON0_M_SHIFT),
+ pll->reg_base + RK3399_PLLCON(0));
+
+ writel_relaxed(HIWORD_UPDATE(rate->p, RK3588_PLLCON1_P_MASK, RK3588_PLLCON1_P_SHIFT) |
+ HIWORD_UPDATE(rate->s, RK3588_PLLCON1_S_MASK, RK3588_PLLCON1_S_SHIFT),
+ pll->reg_base + RK3399_PLLCON(1));
+
+ writel_relaxed(HIWORD_UPDATE(rate->k, RK3588_PLLCON2_K_MASK, RK3588_PLLCON2_K_SHIFT),
+ pll->reg_base + RK3399_PLLCON(2));
+
+ /* set pll power up */
+ writel(HIWORD_UPDATE(0, RK3588_PLLCON1_PWRDOWN, 0),
+ pll->reg_base + RK3588_PLLCON(1));
+
+ /* wait for the pll to lock */
+ ret = rockchip_rk3588_pll_wait_lock(pll);
+ if (ret) {
+ pr_warn("%s: pll update unsuccessful, trying to restore old params\n",
+ __func__);
+ rockchip_rk3588_pll_set_params(pll, &cur);
+ }
+
+ if ((pll->type == pll_rk3588) && rate_change_remuxed)
+ pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
+
+ return ret;
+}
+
+static int rockchip_rk3588_pll_set_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long prate)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ const struct rockchip_pll_rate_table *rate;
+
+ pr_debug("%s: changing %s to %lu with a parent rate of %lu\n",
+ __func__, clk_hw_get_name(hw), drate, prate);
+
+ /* Get required rate settings from table */
+ rate = rockchip_get_pll_settings(pll, drate);
+ if (!rate) {
+ pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+ drate, clk_hw_get_name(hw));
+ return -EINVAL;
+ }
+
+ return rockchip_rk3588_pll_set_params(pll, rate);
+}
+
+static int rockchip_rk3588_pll_enable(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+ writel(HIWORD_UPDATE(0, RK3588_PLLCON1_PWRDOWN, 0),
+ pll->reg_base + RK3588_PLLCON(1));
+ rockchip_rk3588_pll_wait_lock(pll);
+
+ return 0;
+}
+
+static void rockchip_rk3588_pll_disable(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+ writel(HIWORD_UPDATE(RK3588_PLLCON1_PWRDOWN, RK3588_PLLCON1_PWRDOWN, 0),
+ pll->reg_base + RK3588_PLLCON(1));
+}
+
+static int rockchip_rk3588_pll_is_enabled(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ u32 pllcon = readl(pll->reg_base + RK3588_PLLCON(1));
+
+ return !(pllcon & RK3588_PLLCON1_PWRDOWN);
+}
+
+static int rockchip_rk3588_pll_init(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+ if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
+ return 0;
+
+ return 0;
+}
+
+static const struct clk_ops rockchip_rk3588_pll_clk_norate_ops = {
+ .recalc_rate = rockchip_rk3588_pll_recalc_rate,
+ .enable = rockchip_rk3588_pll_enable,
+ .disable = rockchip_rk3588_pll_disable,
+ .is_enabled = rockchip_rk3588_pll_is_enabled,
+};
+
+static const struct clk_ops rockchip_rk3588_pll_clk_ops = {
+ .recalc_rate = rockchip_rk3588_pll_recalc_rate,
+ .round_rate = rockchip_pll_round_rate,
+ .set_rate = rockchip_rk3588_pll_set_rate,
+ .enable = rockchip_rk3588_pll_enable,
+ .disable = rockchip_rk3588_pll_disable,
+ .is_enabled = rockchip_rk3588_pll_is_enabled,
+ .init = rockchip_rk3588_pll_init,
};
/*
* Common registering of pll clocks
*/
-struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
- const char *name, const char **parent_names, u8 num_parents,
- void __iomem *base, int con_offset, int grf_lock_offset,
+struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
+ enum rockchip_pll_type pll_type,
+ const char *name, const char *const *parent_names,
+ u8 num_parents, int con_offset, int grf_lock_offset,
int lock_shift, int mode_offset, int mode_shift,
struct rockchip_pll_rate_table *rate_table,
- u8 clk_pll_flags)
+ unsigned long flags, u8 clk_pll_flags)
{
- const char **pll_parents;
+ const char *pll_parents[3];
+ struct clk_init_data init;
struct rockchip_clk_pll *pll;
- struct clk *pll_mux;
- struct clk *mux_clk;
- int ret;
+ struct clk_mux *pll_mux;
+ struct clk *pll_clk, *mux_clk;
+ char pll_name[20];
- if (num_parents != 2) {
+ if ((pll_type != pll_rk3328 && num_parents != 2) ||
+ (pll_type == pll_rk3328 && num_parents != 1)) {
pr_err("%s: needs two parent clocks\n", __func__);
return ERR_PTR(-EINVAL);
}
+ /* name the actual pll */
+ snprintf(pll_name, sizeof(pll_name), "pll_%s", name);
+
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
if (!pll)
return ERR_PTR(-ENOMEM);
- pll_parents = kzalloc(sizeof(char *)*3, GFP_KERNEL);
- if (!pll_parents)
- return ERR_PTR(-ENOMEM);
+ /* create the mux on top of the real pll */
+ pll->pll_mux_ops = &clk_mux_ops;
+ pll_mux = &pll->pll_mux;
+ pll_mux->reg = ctx->reg_base + mode_offset;
+ pll_mux->shift = mode_shift;
+ if (pll_type == pll_rk3328)
+ pll_mux->width = PLL_RK3328_MODE_WIDTH;
+ else
+ pll_mux->width = PLL_MODE_WIDTH;
+ pll_mux->flags = 0;
+ pll_mux->lock = &ctx->lock;
+ pll_mux->hw.init = &init;
+
+ if (pll_type == pll_rk3036 ||
+ pll_type == pll_rk3066 ||
+ pll_type == pll_rk3328 ||
+ pll_type == pll_rk3399 ||
+ pll_type == pll_rk3588 ||
+ pll_type == pll_rk3588_core)
+ pll_mux->flags |= CLK_MUX_HIWORD_MASK;
- /* name the actual pll */
- snprintf(pll->pll_name, sizeof(pll->pll_name), "pll_%s", name);
- pll->hw.name = pll->pll_name;
+ init.name = name;
+ init.flags = CLK_SET_RATE_PARENT;
+ init.ops = pll->pll_mux_ops;
+ init.parent_names = pll_parents;
+
+ /* the actual muxing is xin24m, pll-output, xin32k */
+ pll_parents[0] = parent_names[0];
+ pll_parents[1] = pll_name;
+
+ if (pll_type == pll_rk3328) {
+ init.num_parents = 2;
+ } else {
+ pll_parents[2] = parent_names[1];
+ init.num_parents = ARRAY_SIZE(pll_parents);
+ }
+
+ mux_clk = clk_register(NULL, &pll_mux->hw);
+ if (IS_ERR(mux_clk))
+ goto err_mux;
+
+ /* now create the actual pll */
+ init.name = pll_name;
+
+ /* keep all plls untouched for now */
+ init.flags = flags | CLK_IGNORE_UNUSED;
- pll->hw.parent_names = &parent_names[0];
- pll->hw.num_parents = 1;
+ init.parent_names = &parent_names[0];
+ init.num_parents = 1;
if (rate_table) {
int len;
@@ -303,61 +1138,71 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
len++;
pll->rate_count = len;
- pll->rate_table = xmemdup(rate_table,
+ pll->rate_table = kmemdup(rate_table,
pll->rate_count *
- sizeof(struct rockchip_pll_rate_table)
- );
+ sizeof(struct rockchip_pll_rate_table),
+ GFP_KERNEL);
WARN(!pll->rate_table,
"%s: could not allocate rate table for %s\n",
__func__, name);
}
switch (pll_type) {
+ case pll_rk3036:
+ case pll_rk3328:
+ if (!pll->rate_table)
+ init.ops = &rockchip_rk3036_pll_clk_norate_ops;
+ else
+ init.ops = &rockchip_rk3036_pll_clk_ops;
+ break;
case pll_rk3066:
+ if (!pll->rate_table || IS_ERR(ctx->grf))
+ init.ops = &rockchip_rk3066_pll_clk_norate_ops;
+ else
+ init.ops = &rockchip_rk3066_pll_clk_ops;
+ break;
+ case pll_rk3399:
if (!pll->rate_table)
- pll->hw.ops = &rockchip_rk3066_pll_clk_norate_ops;
+ init.ops = &rockchip_rk3399_pll_clk_norate_ops;
else
- pll->hw.ops = &rockchip_rk3066_pll_clk_ops;
+ init.ops = &rockchip_rk3399_pll_clk_ops;
+ break;
+ case pll_rk3588:
+ case pll_rk3588_core:
+ if (!pll->rate_table)
+ init.ops = &rockchip_rk3588_pll_clk_norate_ops;
+ else
+ init.ops = &rockchip_rk3588_pll_clk_ops;
+ init.flags = flags;
break;
default:
pr_warn("%s: Unknown pll type for pll clk %s\n",
__func__, name);
}
+ pll->hw.init = &init;
pll->type = pll_type;
- pll->reg_base = base + con_offset;
+ pll->reg_base = ctx->reg_base + con_offset;
pll->lock_offset = grf_lock_offset;
pll->lock_shift = lock_shift;
pll->flags = clk_pll_flags;
-
- ret = clk_register(&pll->hw);
- if (ret) {
- pr_err("%s: failed to register pll clock %s : %d\n",
- __func__, name, ret);
- mux_clk = &pll->hw;
- goto err_exit;
+ pll->lock = &ctx->lock;
+ pll->ctx = ctx;
+
+ pll_clk = clk_register(NULL, &pll->hw);
+ if (IS_ERR(pll_clk)) {
+ pr_err("%s: failed to register pll clock %s : %ld\n",
+ __func__, name, PTR_ERR(pll_clk));
+ goto err_pll;
}
- /* the actual muxing is xin24m, pll-output, xin32k */
- pll_parents[0] = parent_names[0];
- pll_parents[1] = pll->pll_name;
- pll_parents[2] = parent_names[1];
-
- pll_mux = clk_mux_alloc(name, CLK_SET_RATE_PARENT, base + mode_offset, mode_shift,
- PLL_MODE_MASK, pll_parents, 3, 0);
- pll->pll_mux_ops = pll_mux->ops;
- mux_clk = pll_mux;
-
- if (pll_type == pll_rk3066)
- pll_mux->flags |= CLK_MUX_HIWORD_MASK;
-
- ret = clk_register(pll_mux);
- if (ret)
- goto err_exit;
-
return mux_clk;
-err_exit:
+err_pll:
+ kfree(pll->rate_table);
+ clk_unregister(mux_clk);
+ mux_clk = pll_clk;
+err_mux:
kfree(pll);
return mux_clk;
}
diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
index 61dfb27ef4..8597a9d229 100644
--- a/drivers/clk/rockchip/clk-rk3188.c
+++ b/drivers/clk/rockchip/clk-rk3188.c
@@ -20,7 +20,7 @@ enum rk3188_plls {
apll, cpll, dpll, gpll,
};
-struct rockchip_pll_rate_table rk3188_pll_rates[] = {
+static struct rockchip_pll_rate_table rk3188_pll_rates[] = {
RK3066_PLL_RATE(2208000000, 1, 92, 1),
RK3066_PLL_RATE(2184000000, 1, 91, 1),
RK3066_PLL_RATE(2160000000, 1, 90, 1),
@@ -82,6 +82,7 @@ struct rockchip_pll_rate_table rk3188_pll_rates[] = {
RK3066_PLL_RATE( 504000000, 1, 84, 4),
RK3066_PLL_RATE( 456000000, 1, 76, 4),
RK3066_PLL_RATE( 408000000, 1, 68, 4),
+ RK3066_PLL_RATE( 400000000, 3, 100, 2),
RK3066_PLL_RATE( 384000000, 2, 128, 4),
RK3066_PLL_RATE( 360000000, 1, 60, 4),
RK3066_PLL_RATE( 312000000, 1, 52, 4),
@@ -145,10 +146,14 @@ static struct rockchip_cpuclk_rate_table rk3066_cpuclk_rates[] __initdata = {
};
static const struct rockchip_cpuclk_reg_data rk3066_cpuclk_data = {
- .core_reg = RK2928_CLKSEL_CON(0),
- .div_core_shift = 0,
- .div_core_mask = 0x1f,
+ .core_reg[0] = RK2928_CLKSEL_CON(0),
+ .div_core_shift[0] = 0,
+ .div_core_mask[0] = 0x1f,
+ .num_cores = 1,
+ .mux_core_alt = 1,
+ .mux_core_main = 0,
.mux_core_shift = 8,
+ .mux_core_mask = 0x1,
};
#define RK3188_DIV_ACLK_CORE_MASK 0x7
@@ -181,10 +186,14 @@ static struct rockchip_cpuclk_rate_table rk3188_cpuclk_rates[] __initdata = {
};
static const struct rockchip_cpuclk_reg_data rk3188_cpuclk_data = {
- .core_reg = RK2928_CLKSEL_CON(0),
- .div_core_shift = 9,
- .div_core_mask = 0x1f,
+ .core_reg[0] = RK2928_CLKSEL_CON(0),
+ .div_core_shift[0] = 9,
+ .div_core_mask[0] = 0x1f,
+ .num_cores = 1,
+ .mux_core_alt = 1,
+ .mux_core_main = 0,
.mux_core_shift = 8,
+ .mux_core_mask = 0x1,
};
PNAME(mux_pll_p) = { "xin24m", "xin32k" };
@@ -195,7 +204,7 @@ PNAME(mux_pll_src_cpll_gpll_p) = { "cpll", "gpll" };
PNAME(mux_aclk_cpu_p) = { "apll", "gpll" };
PNAME(mux_sclk_cif0_p) = { "cif0_pre", "xin24m" };
PNAME(mux_sclk_i2s0_p) = { "i2s0_pre", "i2s0_frac", "xin12m" };
-PNAME(mux_sclk_spdif_p) = { "spdif_src", "spdif_frac", "xin12m" };
+PNAME(mux_sclk_spdif_p) = { "spdif_pre", "spdif_frac", "xin12m" };
PNAME(mux_sclk_uart0_p) = { "uart0_pre", "uart0_frac", "xin24m" };
PNAME(mux_sclk_uart1_p) = { "uart1_pre", "uart1_frac", "xin24m" };
PNAME(mux_sclk_uart2_p) = { "uart2_pre", "uart2_frac", "xin24m" };
@@ -229,6 +238,7 @@ static struct rockchip_pll_clock rk3188_pll_clks[] __initdata = {
#define MFLAGS CLK_MUX_HIWORD_MASK
#define DFLAGS CLK_DIVIDER_HIWORD_MASK
#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
/* 2 ^ (val + 1) */
static struct clk_div_table div_core_peri_t[] = {
@@ -239,6 +249,30 @@ static struct clk_div_table div_core_peri_t[] = {
{ /* sentinel */ },
};
+static struct rockchip_clk_branch common_hsadc_out_fracmux __initdata =
+ MUX(0, "sclk_hsadc_out", mux_sclk_hsadc_p, 0,
+ RK2928_CLKSEL_CON(22), 4, 2, MFLAGS);
+
+static struct rockchip_clk_branch common_spdif_fracmux __initdata =
+ MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, CLK_SET_RATE_PARENT,
+ RK2928_CLKSEL_CON(5), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch common_uart0_fracmux __initdata =
+ MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, CLK_SET_RATE_PARENT,
+ RK2928_CLKSEL_CON(13), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch common_uart1_fracmux __initdata =
+ MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, CLK_SET_RATE_PARENT,
+ RK2928_CLKSEL_CON(14), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch common_uart2_fracmux __initdata =
+ MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, CLK_SET_RATE_PARENT,
+ RK2928_CLKSEL_CON(15), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch common_uart3_fracmux __initdata =
+ MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, CLK_SET_RATE_PARENT,
+ RK2928_CLKSEL_CON(16), 8, 2, MFLAGS);
+
static struct rockchip_clk_branch common_clk_branches[] __initdata = {
/*
* Clock-Architecture Diagram 2
@@ -251,15 +285,15 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
RK2928_CLKSEL_CON(0), 6, 2, DFLAGS | CLK_DIVIDER_READ_ONLY,
div_core_peri_t, RK2928_CLKGATE_CON(0), 0, GFLAGS),
- COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_p, 0,
+ COMPOSITE(ACLK_VEPU, "aclk_vepu", mux_pll_src_cpll_gpll_p, 0,
RK2928_CLKSEL_CON(32), 7, 1, MFLAGS, 0, 5, DFLAGS,
RK2928_CLKGATE_CON(3), 9, GFLAGS),
- GATE(0, "hclk_vepu", "aclk_vepu", 0,
+ GATE(HCLK_VEPU, "hclk_vepu", "aclk_vepu", 0,
RK2928_CLKGATE_CON(3), 10, GFLAGS),
- COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_p, 0,
+ COMPOSITE(ACLK_VDPU, "aclk_vdpu", mux_pll_src_cpll_gpll_p, 0,
RK2928_CLKSEL_CON(32), 15, 1, MFLAGS, 8, 5, DFLAGS,
RK2928_CLKGATE_CON(3), 11, GFLAGS),
- GATE(0, "hclk_vdpu", "aclk_vdpu", 0,
+ GATE(HCLK_VDPU, "hclk_vdpu", "aclk_vdpu", 0,
RK2928_CLKGATE_CON(3), 12, GFLAGS),
GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED,
@@ -268,14 +302,14 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
RK2928_CLKSEL_CON(26), 8, 1, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
RK2928_CLKGATE_CON(0), 2, GFLAGS),
- GATE(0, "aclk_cpu", "aclk_cpu_pre", 0,
+ GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_pre", 0,
RK2928_CLKGATE_CON(0), 3, GFLAGS),
GATE(0, "atclk_cpu", "pclk_cpu_pre", 0,
RK2928_CLKGATE_CON(0), 6, GFLAGS),
- GATE(0, "pclk_cpu", "pclk_cpu_pre", 0,
+ GATE(PCLK_CPU, "pclk_cpu", "pclk_cpu_pre", 0,
RK2928_CLKGATE_CON(0), 5, GFLAGS),
- GATE(0, "hclk_cpu", "hclk_cpu_pre", CLK_IGNORE_UNUSED,
+ GATE(HCLK_CPU, "hclk_cpu", "hclk_cpu_pre", CLK_IGNORE_UNUSED,
RK2928_CLKGATE_CON(0), 4, GFLAGS),
COMPOSITE(0, "aclk_lcdc0_pre", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED,
@@ -285,12 +319,12 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
RK2928_CLKSEL_CON(31), 15, 1, MFLAGS, 8, 5, DFLAGS,
RK2928_CLKGATE_CON(1), 4, GFLAGS),
- GATE(0, "aclk_peri", "aclk_peri_pre", 0,
+ GATE(ACLK_PERI, "aclk_peri", "aclk_peri_pre", 0,
RK2928_CLKGATE_CON(2), 1, GFLAGS),
- COMPOSITE_NOMUX(0, "hclk_peri", "aclk_peri_pre", 0,
+ COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_pre", 0,
RK2928_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
RK2928_CLKGATE_CON(2), 2, GFLAGS),
- COMPOSITE_NOMUX(0, "pclk_peri", "aclk_peri_pre", 0,
+ COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_pre", 0,
RK2928_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
RK2928_CLKGATE_CON(2), 3, GFLAGS),
@@ -304,14 +338,18 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
GATE(0, "pclkin_cif0", "ext_cif0", 0,
RK2928_CLKGATE_CON(3), 3, GFLAGS),
+ INVERTER(0, "pclk_cif0", "pclkin_cif0",
+ RK2928_CLKSEL_CON(30), 8, IFLAGS),
+
+ FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
/*
* the 480m are generated inside the usb block from these clocks,
* but they are also a source for the hsicphy clock.
*/
- GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED,
+ GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED,
RK2928_CLKGATE_CON(1), 5, GFLAGS),
- GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED,
+ GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", CLK_IGNORE_UNUSED,
RK2928_CLKGATE_CON(1), 6, GFLAGS),
COMPOSITE(0, "mac_src", mux_mac_p, 0,
@@ -319,17 +357,18 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
RK2928_CLKGATE_CON(2), 5, GFLAGS),
MUX(SCLK_MAC, "sclk_macref", mux_sclk_macref_p, CLK_SET_RATE_PARENT,
RK2928_CLKSEL_CON(21), 4, 1, MFLAGS),
- GATE(0, "sclk_mac_lbtest", "sclk_macref",
- RK2928_CLKGATE_CON(2), 12, 0, GFLAGS),
+ GATE(0, "sclk_mac_lbtest", "sclk_macref", 0,
+ RK2928_CLKGATE_CON(2), 12, GFLAGS),
COMPOSITE(0, "hsadc_src", mux_pll_src_gpll_cpll_p, 0,
RK2928_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS,
RK2928_CLKGATE_CON(2), 6, GFLAGS),
- COMPOSITE_FRAC(0, "hsadc_frac", "hsadc_src", 0,
+ COMPOSITE_FRACMUX(0, "hsadc_frac", "hsadc_src", 0,
RK2928_CLKSEL_CON(23), 0,
- RK2928_CLKGATE_CON(2), 7, GFLAGS),
- MUX(SCLK_HSADC, "sclk_hsadc", mux_sclk_hsadc_p, 0,
- RK2928_CLKSEL_CON(22), 4, 2, MFLAGS),
+ RK2928_CLKGATE_CON(2), 7, GFLAGS,
+ &common_hsadc_out_fracmux),
+ INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
+ RK2928_CLKSEL_CON(22), 7, IFLAGS),
COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0,
RK2928_CLKSEL_CON(24), 8, 8, DFLAGS,
@@ -338,18 +377,17 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0,
RK2928_CLKSEL_CON(5), 0, 7, DFLAGS,
RK2928_CLKGATE_CON(0), 13, GFLAGS),
- COMPOSITE_FRAC(0, "spdif_frac", "spdif_pll", 0,
+ COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_pre", CLK_SET_RATE_PARENT,
RK2928_CLKSEL_CON(9), 0,
- RK2928_CLKGATE_CON(0), 14, GFLAGS),
- MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0,
- RK2928_CLKSEL_CON(5), 8, 2, MFLAGS),
+ RK2928_CLKGATE_CON(0), 14, GFLAGS,
+ &common_spdif_fracmux),
/*
* Clock-Architecture Diagram 4
*/
- GATE(SCLK_SMC, "sclk_smc", "hclk_peri",
- RK2928_CLKGATE_CON(2), 4, 0, GFLAGS),
+ GATE(SCLK_SMC, "sclk_smc", "hclk_peri", 0,
+ RK2928_CLKGATE_CON(2), 4, GFLAGS),
COMPOSITE_NOMUX(SCLK_SPI0, "sclk_spi0", "pclk_peri", 0,
RK2928_CLKSEL_CON(25), 0, 7, DFLAGS,
@@ -373,35 +411,31 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
COMPOSITE_NOMUX(0, "uart0_pre", "uart_src", 0,
RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
RK2928_CLKGATE_CON(1), 8, GFLAGS),
- COMPOSITE_FRAC(0, "uart0_frac", "uart0_pre", 0,
+ COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_pre", CLK_SET_RATE_PARENT,
RK2928_CLKSEL_CON(17), 0,
- RK2928_CLKGATE_CON(1), 9, GFLAGS),
- MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, 0,
- RK2928_CLKSEL_CON(13), 8, 2, MFLAGS),
+ RK2928_CLKGATE_CON(1), 9, GFLAGS,
+ &common_uart0_fracmux),
COMPOSITE_NOMUX(0, "uart1_pre", "uart_src", 0,
RK2928_CLKSEL_CON(14), 0, 7, DFLAGS,
RK2928_CLKGATE_CON(1), 10, GFLAGS),
- COMPOSITE_FRAC(0, "uart1_frac", "uart1_pre", 0,
+ COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_pre", CLK_SET_RATE_PARENT,
RK2928_CLKSEL_CON(18), 0,
- RK2928_CLKGATE_CON(1), 11, GFLAGS),
- MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, 0,
- RK2928_CLKSEL_CON(14), 8, 2, MFLAGS),
+ RK2928_CLKGATE_CON(1), 11, GFLAGS,
+ &common_uart1_fracmux),
COMPOSITE_NOMUX(0, "uart2_pre", "uart_src", 0,
RK2928_CLKSEL_CON(15), 0, 7, DFLAGS,
RK2928_CLKGATE_CON(1), 12, GFLAGS),
- COMPOSITE_FRAC(0, "uart2_frac", "uart2_pre", 0,
+ COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_pre", CLK_SET_RATE_PARENT,
RK2928_CLKSEL_CON(19), 0,
- RK2928_CLKGATE_CON(1), 13, GFLAGS),
- MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, 0,
- RK2928_CLKSEL_CON(15), 8, 2, MFLAGS),
+ RK2928_CLKGATE_CON(1), 13, GFLAGS,
+ &common_uart2_fracmux),
COMPOSITE_NOMUX(0, "uart3_pre", "uart_src", 0,
RK2928_CLKSEL_CON(16), 0, 7, DFLAGS,
RK2928_CLKGATE_CON(1), 14, GFLAGS),
- COMPOSITE_FRAC(0, "uart3_frac", "uart3_pre", 0,
+ COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_pre", CLK_SET_RATE_PARENT,
RK2928_CLKSEL_CON(20), 0,
- RK2928_CLKGATE_CON(1), 15, GFLAGS),
- MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, 0,
- RK2928_CLKSEL_CON(16), 8, 2, MFLAGS),
+ RK2928_CLKGATE_CON(1), 15, GFLAGS,
+ &common_uart3_fracmux),
GATE(SCLK_JTAG, "jtag", "ext_jtag", 0, RK2928_CLKGATE_CON(1), 3, GFLAGS),
@@ -418,7 +452,6 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
/* hclk_cpu gates */
GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", 0, RK2928_CLKGATE_CON(5), 6, GFLAGS),
- GATE(HCLK_I2S0, "hclk_i2s0", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS),
GATE(HCLK_SPDIF, "hclk_spdif", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 1, GFLAGS),
GATE(0, "hclk_cpubus", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 8, GFLAGS),
/* hclk_ahb2apb is part of a clk branch */
@@ -468,8 +501,8 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS),
GATE(PCLK_EFUSE, "pclk_efuse", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 2, GFLAGS),
GATE(PCLK_TZPC, "pclk_tzpc", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 3, GFLAGS),
- GATE(0, "pclk_ddrupctl", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 7, GFLAGS),
- GATE(0, "pclk_ddrpubl", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS),
+ GATE(PCLK_DDRUPCTL, "pclk_ddrupctl", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 7, GFLAGS),
+ GATE(PCLK_PUBL, "pclk_ddrpubl", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS),
GATE(0, "pclk_dbg", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 1, GFLAGS),
GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 4, GFLAGS),
GATE(PCLK_PMU, "pclk_pmu", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 5, GFLAGS),
@@ -511,6 +544,18 @@ static struct clk_div_table div_aclk_cpu_t[] = {
{ /* sentinel */ },
};
+static struct rockchip_clk_branch rk3066a_i2s0_fracmux __initdata =
+ MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, CLK_SET_RATE_PARENT,
+ RK2928_CLKSEL_CON(2), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3066a_i2s1_fracmux __initdata =
+ MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, CLK_SET_RATE_PARENT,
+ RK2928_CLKSEL_CON(3), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3066a_i2s2_fracmux __initdata =
+ MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, CLK_SET_RATE_PARENT,
+ RK2928_CLKSEL_CON(4), 8, 2, MFLAGS);
+
static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
DIVTBL(0, "aclk_cpu_pre", "armclk", 0,
RK2928_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, div_aclk_cpu_t),
@@ -535,12 +580,12 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
COMPOSITE(0, "dclk_lcdc0_src", mux_pll_src_cpll_gpll_p, 0,
RK2928_CLKSEL_CON(27), 0, 1, MFLAGS, 8, 8, DFLAGS,
RK2928_CLKGATE_CON(3), 1, GFLAGS),
- MUX(DCLK_LCDC0, "dclk_lcdc0", mux_rk3066_lcdc0_p, 0,
+ MUX(DCLK_LCDC0, "dclk_lcdc0", mux_rk3066_lcdc0_p, CLK_SET_RATE_PARENT,
RK2928_CLKSEL_CON(27), 4, 1, MFLAGS),
COMPOSITE(0, "dclk_lcdc1_src", mux_pll_src_cpll_gpll_p, 0,
RK2928_CLKSEL_CON(28), 0, 1, MFLAGS, 8, 8, DFLAGS,
RK2928_CLKGATE_CON(3), 2, GFLAGS),
- MUX(DCLK_LCDC1, "dclk_lcdc1", mux_rk3066_lcdc1_p, 0,
+ MUX(DCLK_LCDC1, "dclk_lcdc1", mux_rk3066_lcdc1_p, CLK_SET_RATE_PARENT,
RK2928_CLKSEL_CON(28), 4, 1, MFLAGS),
COMPOSITE_NOMUX(0, "cif1_pre", "cif_src", 0,
@@ -551,6 +596,8 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
GATE(0, "pclkin_cif1", "ext_cif1", 0,
RK2928_CLKGATE_CON(3), 4, GFLAGS),
+ INVERTER(0, "pclk_cif1", "pclkin_cif1",
+ RK2928_CLKSEL_CON(30), 12, IFLAGS),
COMPOSITE(0, "aclk_gpu_src", mux_pll_src_cpll_gpll_p, 0,
RK2928_CLKSEL_CON(33), 8, 1, MFLAGS, 0, 5, DFLAGS,
@@ -561,7 +608,7 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
GATE(SCLK_TIMER2, "timer2", "xin24m", 0,
RK2928_CLKGATE_CON(3), 2, GFLAGS),
- COMPOSITE_NOMUX(0, "sclk_tsadc", "xin24m", 0,
+ COMPOSITE_NOMUX(SCLK_TSADC, "sclk_tsadc", "xin24m", 0,
RK2928_CLKSEL_CON(34), 0, 16, DFLAGS,
RK2928_CLKGATE_CON(2), 15, GFLAGS),
@@ -570,37 +617,35 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0,
RK2928_CLKSEL_CON(2), 0, 7, DFLAGS,
RK2928_CLKGATE_CON(0), 7, GFLAGS),
- COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0,
+ COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", CLK_SET_RATE_PARENT,
RK2928_CLKSEL_CON(6), 0,
- RK2928_CLKGATE_CON(0), 8, GFLAGS),
- MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
- RK2928_CLKSEL_CON(2), 8, 2, MFLAGS),
+ RK2928_CLKGATE_CON(0), 8, GFLAGS,
+ &rk3066a_i2s0_fracmux),
COMPOSITE_NOMUX(0, "i2s1_pre", "i2s_src", 0,
RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
RK2928_CLKGATE_CON(0), 9, GFLAGS),
- COMPOSITE_FRAC(0, "i2s1_frac", "i2s1_pre", 0,
+ COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_pre", CLK_SET_RATE_PARENT,
RK2928_CLKSEL_CON(7), 0,
- RK2928_CLKGATE_CON(0), 10, GFLAGS),
- MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, 0,
- RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
+ RK2928_CLKGATE_CON(0), 10, GFLAGS,
+ &rk3066a_i2s1_fracmux),
COMPOSITE_NOMUX(0, "i2s2_pre", "i2s_src", 0,
RK2928_CLKSEL_CON(4), 0, 7, DFLAGS,
RK2928_CLKGATE_CON(0), 11, GFLAGS),
- COMPOSITE_FRAC(0, "i2s2_frac", "i2s2_pre", 0,
+ COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_pre", CLK_SET_RATE_PARENT,
RK2928_CLKSEL_CON(8), 0,
- RK2928_CLKGATE_CON(0), 12, GFLAGS),
- MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0,
- RK2928_CLKSEL_CON(4), 8, 2, MFLAGS),
+ RK2928_CLKGATE_CON(0), 12, GFLAGS,
+ &rk3066a_i2s2_fracmux),
- GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
- GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS),
- GATE(0, "hclk_cif1", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 6, GFLAGS),
- GATE(0, "hclk_hdmi", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS),
+ GATE(HCLK_I2S0, "hclk_i2s0", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS),
+ GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS),
+ GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
+ GATE(HCLK_CIF1, "hclk_cif1", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 6, GFLAGS),
+ GATE(HCLK_HDMI, "hclk_hdmi", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS),
GATE(HCLK_OTG1, "hclk_usbotg1", "hclk_peri", CLK_IGNORE_UNUSED,
RK2928_CLKGATE_CON(5), 14, GFLAGS),
- GATE(0, "aclk_cif1", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 7, GFLAGS),
+ GATE(ACLK_CIF1, "aclk_cif1", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 7, GFLAGS),
GATE(PCLK_TIMER1, "pclk_timer1", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 8, GFLAGS),
GATE(PCLK_TIMER2, "pclk_timer2", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 9, GFLAGS),
@@ -621,9 +666,13 @@ static struct clk_div_table div_rk3188_aclk_core_t[] = {
{ /* sentinel */ },
};
-PNAME(mux_hsicphy_p) = { "sclk_otgphy0", "sclk_otgphy1",
+PNAME(mux_hsicphy_p) = { "sclk_otgphy0_480m", "sclk_otgphy1_480m",
"gpll", "cpll" };
+static struct rockchip_clk_branch rk3188_i2s0_fracmux __initdata =
+ MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, CLK_SET_RATE_PARENT,
+ RK2928_CLKSEL_CON(3), 8, 2, MFLAGS);
+
static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
COMPOSITE_NOMUX_DIVTBL(0, "aclk_core", "armclk", CLK_IGNORE_UNUSED,
RK2928_CLKSEL_CON(1), 3, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
@@ -677,12 +726,12 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0,
RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
RK2928_CLKGATE_CON(0), 9, GFLAGS),
- COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0,
+ COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", CLK_SET_RATE_PARENT,
RK2928_CLKSEL_CON(7), 0,
- RK2928_CLKGATE_CON(0), 10, GFLAGS),
- MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
- RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
+ RK2928_CLKGATE_CON(0), 10, GFLAGS,
+ &rk3188_i2s0_fracmux),
+ GATE(HCLK_I2S0, "hclk_i2s0", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS),
GATE(0, "hclk_imem0", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS),
GATE(0, "hclk_imem1", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 15, GFLAGS),
@@ -698,142 +747,104 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
GATE(ACLK_GPS, "aclk_gps", "aclk_peri", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS),
};
-static const char *rk3188_critical_clocks[] __initconst = {
+static const char *const rk3188_critical_clocks[] __initconst = {
"aclk_cpu",
"aclk_peri",
"hclk_peri",
+ "pclk_cpu",
+ "pclk_peri",
+ "hclk_cpubus",
+ "hclk_vio_bus",
+ "sclk_mac_lbtest",
};
-
-static void __init rockchip_reparent_clk(char *clock, char *new_parent)
-{
- struct clk *clk1, *clk2;
- unsigned long rate;
- int ret;
-
- clk1 = __clk_lookup(clock);
- clk2 = __clk_lookup(new_parent);
- if (!IS_ERR(clk1) && !IS_ERR(clk2)) {
- rate = clk_get_rate(clk1);
-
- ret = clk_set_parent(clk1, clk2);
- if (ret < 0)
- pr_err("%s: could not reparent %s to %s, ret=%d\n",
- __func__, clock, new_parent, ret);
-
- clk_set_rate(clk1, rate);
- } else {
- pr_err("%s: missing clocks to reparent %s to %s\n",
- __func__, clock, new_parent);
- }
-}
-
-static void __init rockchip_clk_set_rate(char *clock, unsigned long rate)
-{
- struct clk *clk;
-
- clk = __clk_lookup(clock);
- if(clk && !IS_ERR(clk)) {
- clk_set_rate(clk, rate);
- return;
- }
- pr_err("%s: missing clock %s when setting initial rate to %lu\n",
- __func__, clock, rate);
-}
-
-static void __init rockchip_clk_set_defaults(void)
-{
- struct rockchip_initial_rate {
- char *name;
- unsigned long rate;
- };
- int i;
-
- struct rockchip_initial_rate rates[] = {
- {"gpll", 891000000},
- {"cpll", 600000000},
- {"aclk_cpu", 300000000},
- {"hclk_cpu", 150000000},
- {"pclk_cpu", 75000000},
- {"hclk_ahb2apb", 75000000},
- {"aclk_peri_pre", 150000000},
- {"hclk_peri", 150000000},
- {"pclk_peri", 75000000},
- };
-
- rockchip_reparent_clk("aclk_cpu_pre", "gpll");
- rockchip_reparent_clk("mac_src", "dpll");
- rockchip_reparent_clk("aclk_peri_pre", "cpll");
-
- for(i = 0; i < ARRAY_SIZE(rates); i++)
- rockchip_clk_set_rate(rates[i].name, rates[i].rate);
-}
-
-static void __init rk3188_common_clk_init(struct device_node *np)
+static struct rockchip_clk_provider *__init rk3188_common_clk_init(struct device_node *np)
{
+ struct rockchip_clk_provider *ctx;
void __iomem *reg_base;
- struct clk *clk;
reg_base = of_iomap(np, 0);
if (!reg_base) {
pr_err("%s: could not map cru region\n", __func__);
- return;
+ return ERR_PTR(-ENOMEM);
}
- rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
-
- /* Fixed-clock should be registered before all others */
- clk=clk_fixed("xin24m",24000000);
- if (IS_ERR(clk))
- pr_warn("%s: could not register clock xin24m: %ld\n",
- __func__, PTR_ERR(clk));
-
- /* xin12m is created by an cru-internal divider */
- clk = clk_fixed_factor("xin12m", "xin24m", 1, 2, 0);
- if (IS_ERR(clk))
- pr_warn("%s: could not register clock xin12m: %ld\n",
- __func__, PTR_ERR(clk));
-
- clk = clk_fixed_factor("usb480m", "xin24m", 20, 1, 0);
- if (IS_ERR(clk))
- pr_warn("%s: could not register clock usb480m: %ld\n",
- __func__, PTR_ERR(clk));
+ ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+ if (IS_ERR(ctx)) {
+ pr_err("%s: rockchip clk init failed\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
- rockchip_clk_register_branches(common_clk_branches,
+ rockchip_clk_register_branches(ctx, common_clk_branches,
ARRAY_SIZE(common_clk_branches));
- rockchip_clk_protect_critical(rk3188_critical_clocks,
- ARRAY_SIZE(rk3188_critical_clocks));
+
+ return ctx;
}
static void __init rk3066a_clk_init(struct device_node *np)
{
- rk3188_common_clk_init(np);
- rockchip_clk_register_plls(rk3066_pll_clks,
+ struct rockchip_clk_provider *ctx;
+
+ ctx = rk3188_common_clk_init(np);
+ if (IS_ERR(ctx))
+ return;
+
+ rockchip_clk_register_plls(ctx, rk3066_pll_clks,
ARRAY_SIZE(rk3066_pll_clks),
RK3066_GRF_SOC_STATUS);
- rockchip_clk_register_branches(rk3066a_clk_branches,
+ rockchip_clk_register_branches(ctx, rk3066a_clk_branches,
ARRAY_SIZE(rk3066a_clk_branches));
- rockchip_clk_register_armclk(ARMCLK, "armclk",
+ rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
&rk3066_cpuclk_data, rk3066_cpuclk_rates,
ARRAY_SIZE(rk3066_cpuclk_rates));
+ rockchip_clk_protect_critical(rk3188_critical_clocks,
+ ARRAY_SIZE(rk3188_critical_clocks));
+ rockchip_clk_of_add_provider(np, ctx);
}
CLK_OF_DECLARE(rk3066a_cru, "rockchip,rk3066a-cru", rk3066a_clk_init);
static void __init rk3188a_clk_init(struct device_node *np)
{
- rk3188_common_clk_init(np);
- rockchip_clk_register_plls(rk3188_pll_clks,
+ struct rockchip_clk_provider *ctx;
+ struct clk *clk1, *clk2;
+ unsigned long rate;
+ int ret;
+
+ ctx = rk3188_common_clk_init(np);
+ if (IS_ERR(ctx))
+ return;
+
+ rockchip_clk_register_plls(ctx, rk3188_pll_clks,
ARRAY_SIZE(rk3188_pll_clks),
RK3188_GRF_SOC_STATUS);
- rockchip_clk_register_branches(rk3188_clk_branches,
+ rockchip_clk_register_branches(ctx, rk3188_clk_branches,
ARRAY_SIZE(rk3188_clk_branches));
- rockchip_clk_register_armclk(ARMCLK, "armclk",
+ rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
&rk3188_cpuclk_data, rk3188_cpuclk_rates,
ARRAY_SIZE(rk3188_cpuclk_rates));
- rockchip_clk_set_defaults();
+ /* reparent aclk_cpu_pre from apll */
+ clk1 = __clk_lookup("aclk_cpu_pre");
+ clk2 = __clk_lookup("gpll");
+ if (clk1 && clk2) {
+ rate = clk_get_rate(clk1);
+
+ ret = clk_set_parent(clk1, clk2);
+ if (ret < 0)
+ pr_warn("%s: could not reparent aclk_cpu_pre to gpll\n",
+ __func__);
+
+ clk_set_rate(clk1, rate);
+ } else {
+ pr_warn("%s: missing clocks to reparent aclk_cpu_pre to gpll\n",
+ __func__);
+ }
+
+ rockchip_clk_protect_critical(rk3188_critical_clocks,
+ ARRAY_SIZE(rk3188_critical_clocks));
+ rockchip_clk_of_add_provider(np, ctx);
}
CLK_OF_DECLARE(rk3188a_cru, "rockchip,rk3188a-cru", rk3188a_clk_init);
@@ -850,7 +861,7 @@ static void __init rk3188_clk_init(struct device_node *np)
rate = pll->rate_table;
while (rate->rate > 0) {
- rate->bwadj = 0;
+ rate->nb = 1;
rate++;
}
}
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index b6c122d393..fc9554e0f3 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -16,6 +16,11 @@
#define RK3288_GRF_SOC_CON(x) (0x244 + x * 4)
#define RK3288_GRF_SOC_STATUS1 0x284
+enum rk3288_variant {
+ RK3288_CRU,
+ RK3288W_CRU,
+};
+
enum rk3288_plls {
apll, dpll, cpll, gpll, npll,
};
@@ -76,24 +81,44 @@ static struct rockchip_pll_rate_table rk3288_pll_rates[] = {
RK3066_PLL_RATE( 768000000, 1, 64, 2),
RK3066_PLL_RATE( 742500000, 8, 495, 2),
RK3066_PLL_RATE( 696000000, 1, 58, 2),
+ RK3066_PLL_RATE_NB(621000000, 1, 207, 8, 1),
RK3066_PLL_RATE( 600000000, 1, 50, 2),
- RK3066_PLL_RATE_BWADJ(594000000, 1, 198, 8, 1),
+ RK3066_PLL_RATE_NB(594000000, 1, 198, 8, 1),
RK3066_PLL_RATE( 552000000, 1, 46, 2),
RK3066_PLL_RATE( 504000000, 1, 84, 4),
RK3066_PLL_RATE( 500000000, 3, 125, 2),
RK3066_PLL_RATE( 456000000, 1, 76, 4),
+ RK3066_PLL_RATE( 428000000, 1, 107, 6),
RK3066_PLL_RATE( 408000000, 1, 68, 4),
RK3066_PLL_RATE( 400000000, 3, 100, 2),
+ RK3066_PLL_RATE_NB( 394000000, 1, 197, 12, 1),
RK3066_PLL_RATE( 384000000, 2, 128, 4),
RK3066_PLL_RATE( 360000000, 1, 60, 4),
+ RK3066_PLL_RATE_NB( 356000000, 1, 178, 12, 1),
+ RK3066_PLL_RATE_NB( 324000000, 1, 189, 14, 1),
RK3066_PLL_RATE( 312000000, 1, 52, 4),
- RK3066_PLL_RATE( 300000000, 1, 50, 4),
- RK3066_PLL_RATE( 297000000, 2, 198, 8),
+ RK3066_PLL_RATE_NB( 308000000, 1, 154, 12, 1),
+ RK3066_PLL_RATE_NB( 303000000, 1, 202, 16, 1),
+ RK3066_PLL_RATE( 300000000, 1, 75, 6),
+ RK3066_PLL_RATE_NB( 297750000, 2, 397, 16, 1),
+ RK3066_PLL_RATE_NB( 293250000, 2, 391, 16, 1),
+ RK3066_PLL_RATE_NB( 292500000, 1, 195, 16, 1),
+ RK3066_PLL_RATE( 273600000, 1, 114, 10),
+ RK3066_PLL_RATE_NB( 273000000, 1, 182, 16, 1),
+ RK3066_PLL_RATE_NB( 270000000, 1, 180, 16, 1),
+ RK3066_PLL_RATE_NB( 266250000, 2, 355, 16, 1),
+ RK3066_PLL_RATE_NB( 256500000, 1, 171, 16, 1),
RK3066_PLL_RATE( 252000000, 1, 84, 8),
- RK3066_PLL_RATE( 216000000, 1, 72, 8),
- RK3066_PLL_RATE( 148500000, 2, 99, 8),
+ RK3066_PLL_RATE_NB( 250500000, 1, 167, 16, 1),
+ RK3066_PLL_RATE_NB( 243428571, 1, 142, 14, 1),
+ RK3066_PLL_RATE( 238000000, 1, 119, 12),
+ RK3066_PLL_RATE_NB( 219750000, 2, 293, 16, 1),
+ RK3066_PLL_RATE_NB( 216000000, 1, 144, 16, 1),
+ RK3066_PLL_RATE_NB( 213000000, 1, 142, 16, 1),
+ RK3066_PLL_RATE( 195428571, 1, 114, 14),
+ RK3066_PLL_RATE( 160000000, 1, 80, 12),
+ RK3066_PLL_RATE( 157500000, 1, 105, 16),
RK3066_PLL_RATE( 126000000, 1, 84, 16),
- RK3066_PLL_RATE( 48000000, 1, 64, 32),
{ /* sentinel */ },
};
@@ -155,10 +180,14 @@ static struct rockchip_cpuclk_rate_table rk3288_cpuclk_rates[] __initdata = {
};
static const struct rockchip_cpuclk_reg_data rk3288_cpuclk_data = {
- .core_reg = RK3288_CLKSEL_CON(0),
- .div_core_shift = 8,
- .div_core_mask = 0x1f,
+ .core_reg[0] = RK3288_CLKSEL_CON(0),
+ .div_core_shift[0] = 8,
+ .div_core_mask[0] = 0x1f,
+ .num_cores = 1,
+ .mux_core_alt = 1,
+ .mux_core_main = 0,
.mux_core_shift = 15,
+ .mux_core_mask = 0x1,
};
PNAME(mux_pll_p) = { "xin24m", "xin32k" };
@@ -169,8 +198,8 @@ PNAME(mux_aclk_cpu_src_p) = { "cpll_aclk_cpu", "gpll_aclk_cpu" };
PNAME(mux_pll_src_cpll_gpll_p) = { "cpll", "gpll" };
PNAME(mux_pll_src_npll_cpll_gpll_p) = { "npll", "cpll", "gpll" };
PNAME(mux_pll_src_cpll_gpll_npll_p) = { "cpll", "gpll", "npll" };
-PNAME(mux_pll_src_cpll_gpll_usb480m_p) = { "cpll", "gpll", "usbphy480m_src" };
-PNAME(mux_pll_src_cpll_gll_usb_npll_p) = { "cpll", "gpll", "usbphy480m_src", "npll" };
+PNAME(mux_pll_src_cpll_gpll_usb480m_p) = { "cpll", "gpll", "unstable:usbphy480m_src" };
+PNAME(mux_pll_src_cpll_gll_usb_npll_p) = { "cpll", "gpll", "unstable:usbphy480m_src", "npll" };
PNAME(mux_mmc_src_p) = { "cpll", "gpll", "xin24m", "xin24m" };
PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" };
@@ -188,8 +217,9 @@ PNAME(mux_hsadcout_p) = { "hsadc_src", "ext_hsadc" };
PNAME(mux_edp_24m_p) = { "ext_edp_24m", "xin24m" };
PNAME(mux_tspout_p) = { "cpll", "gpll", "npll", "xin27m" };
-PNAME(mux_usbphy480m_p) = { "sclk_otgphy1", "sclk_otgphy2",
- "sclk_otgphy0" };
+PNAME(mux_aclk_vcodec_pre_p) = { "aclk_vdpu", "aclk_vepu" };
+PNAME(mux_usbphy480m_p) = { "sclk_otgphy1_480m", "sclk_otgphy2_480m",
+ "sclk_otgphy0_480m" };
PNAME(mux_hsicphy480m_p) = { "cpll", "gpll", "usbphy480m_src" };
PNAME(mux_hsicphy12m_p) = { "hsicphy12m_xin12m", "hsicphy12m_usbphy" };
@@ -216,6 +246,39 @@ static struct clk_div_table div_hclk_cpu_t[] = {
#define MFLAGS CLK_MUX_HIWORD_MASK
#define DFLAGS CLK_DIVIDER_HIWORD_MASK
#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
+
+static struct rockchip_clk_branch rk3288_i2s_fracmux __initdata =
+ MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
+ RK3288_CLKSEL_CON(4), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3288_spdif_fracmux __initdata =
+ MUX(0, "spdif_mux", mux_spdif_p, CLK_SET_RATE_PARENT,
+ RK3288_CLKSEL_CON(5), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3288_spdif_8ch_fracmux __initdata =
+ MUX(0, "spdif_8ch_mux", mux_spdif_8ch_p, CLK_SET_RATE_PARENT,
+ RK3288_CLKSEL_CON(40), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3288_uart0_fracmux __initdata =
+ MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+ RK3288_CLKSEL_CON(13), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3288_uart1_fracmux __initdata =
+ MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+ RK3288_CLKSEL_CON(14), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3288_uart2_fracmux __initdata =
+ MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+ RK3288_CLKSEL_CON(15), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3288_uart3_fracmux __initdata =
+ MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT,
+ RK3288_CLKSEL_CON(16), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3288_uart4_fracmux __initdata =
+ MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT,
+ RK3288_CLKSEL_CON(3), 8, 2, MFLAGS);
static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
/*
@@ -287,20 +350,21 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
RK3288_CLKGATE_CON(0), 4, GFLAGS),
GATE(0, "c2c_host", "aclk_cpu_src", 0,
RK3288_CLKGATE_CON(13), 8, GFLAGS),
- COMPOSITE_NOMUX(0, "crypto", "aclk_cpu_pre", 0,
+ COMPOSITE_NOMUX(SCLK_CRYPTO, "crypto", "aclk_cpu_pre", 0,
RK3288_CLKSEL_CON(26), 6, 2, DFLAGS,
RK3288_CLKGATE_CON(5), 4, GFLAGS),
GATE(0, "aclk_bus_2pmu", "aclk_cpu_pre", CLK_IGNORE_UNUSED,
RK3288_CLKGATE_CON(0), 7, GFLAGS),
+ FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
+
COMPOSITE(0, "i2s_src", mux_pll_src_cpll_gpll_p, 0,
RK3288_CLKSEL_CON(4), 15, 1, MFLAGS, 0, 7, DFLAGS,
RK3288_CLKGATE_CON(4), 1, GFLAGS),
- COMPOSITE_FRAC(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
+ COMPOSITE_FRACMUX(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(8), 0,
- RK3288_CLKGATE_CON(4), 2, GFLAGS),
- MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
- RK3288_CLKSEL_CON(4), 8, 2, MFLAGS),
+ RK3288_CLKGATE_CON(4), 2, GFLAGS,
+ &rk3288_i2s_fracmux),
COMPOSITE_NODIV(SCLK_I2S0_OUT, "i2s0_clkout", mux_i2s_clkout_p, 0,
RK3288_CLKSEL_CON(4), 12, 1, MFLAGS,
RK3288_CLKGATE_CON(4), 0, GFLAGS),
@@ -309,27 +373,28 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
MUX(0, "spdif_src", mux_pll_src_cpll_gpll_p, 0,
RK3288_CLKSEL_CON(5), 15, 1, MFLAGS),
- COMPOSITE_NOMUX(0, "spdif_pre", "spdif_src", 0,
+ COMPOSITE_NOMUX(0, "spdif_pre", "spdif_src", CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(5), 0, 7, DFLAGS,
RK3288_CLKGATE_CON(4), 4, GFLAGS),
- COMPOSITE_FRAC(0, "spdif_frac", "spdif_src", 0,
+ COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_src", CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(9), 0,
- RK3288_CLKGATE_CON(4), 5, GFLAGS),
- COMPOSITE_NODIV(SCLK_SPDIF, "sclk_spdif", mux_spdif_p, 0,
- RK3288_CLKSEL_CON(5), 8, 2, MFLAGS,
+ RK3288_CLKGATE_CON(4), 5, GFLAGS,
+ &rk3288_spdif_fracmux),
+ GATE(SCLK_SPDIF, "sclk_spdif", "spdif_mux", CLK_SET_RATE_PARENT,
RK3288_CLKGATE_CON(4), 6, GFLAGS),
- COMPOSITE_NOMUX(0, "spdif_8ch_pre", "spdif_src", 0,
+ COMPOSITE_NOMUX(0, "spdif_8ch_pre", "spdif_src", CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(40), 0, 7, DFLAGS,
RK3288_CLKGATE_CON(4), 7, GFLAGS),
- COMPOSITE_FRAC(0, "spdif_8ch_frac", "spdif_8ch_pre", 0,
+ COMPOSITE_FRACMUX(0, "spdif_8ch_frac", "spdif_8ch_pre", CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(41), 0,
- RK3288_CLKGATE_CON(4), 8, GFLAGS),
- COMPOSITE_NODIV(SCLK_SPDIF8CH, "sclk_spdif_8ch", mux_spdif_8ch_p, 0,
- RK3288_CLKSEL_CON(40), 8, 2, MFLAGS,
+ RK3288_CLKGATE_CON(4), 8, GFLAGS,
+ &rk3288_spdif_8ch_fracmux),
+ GATE(SCLK_SPDIF8CH, "sclk_spdif_8ch", "spdif_8ch_mux", CLK_SET_RATE_PARENT,
RK3288_CLKGATE_CON(4), 9, GFLAGS),
GATE(0, "sclk_acc_efuse", "xin24m", 0,
RK3288_CLKGATE_CON(0), 12, GFLAGS),
+
GATE(SCLK_TIMER0, "sclk_timer0", "xin24m", 0,
RK3288_CLKGATE_CON(1), 0, GFLAGS),
GATE(SCLK_TIMER1, "sclk_timer1", "xin24m", 0,
@@ -342,6 +407,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
RK3288_CLKGATE_CON(1), 4, GFLAGS),
GATE(SCLK_TIMER5, "sclk_timer5", "xin24m", 0,
RK3288_CLKGATE_CON(1), 5, GFLAGS),
+
/*
* Clock-Architecture Diagram 2
*/
@@ -352,26 +418,20 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb480m_p, 0,
RK3288_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS,
RK3288_CLKGATE_CON(3), 11, GFLAGS),
- /*
- * We use aclk_vdpu by default GRF_SOC_CON0[7] setting in system,
- * so we ignore the mux and make clocks nodes as following,
- */
- GATE(ACLK_VCODEC, "aclk_vcodec", "aclk_vdpu", 0,
+ MUXGRF(0, "aclk_vcodec_pre", mux_aclk_vcodec_pre_p, CLK_SET_RATE_PARENT,
+ RK3288_GRF_SOC_CON(0), 7, 1, MFLAGS),
+ GATE(ACLK_VCODEC, "aclk_vcodec", "aclk_vcodec_pre", 0,
RK3288_CLKGATE_CON(9), 0, GFLAGS),
- /*
- * We introduce a virtul node of hclk_vodec_pre_v to split one clock
- * struct with a gate and a fix divider into two node in software.
- */
- GATE(0, "hclk_vcodec_pre_v", "aclk_vdpu", 0,
+
+ FACTOR_GATE(0, "hclk_vcodec_pre", "aclk_vcodec_pre", 0, 1, 4,
RK3288_CLKGATE_CON(3), 10, GFLAGS),
+
GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_vcodec_pre", 0,
RK3288_CLKGATE_CON(9), 1, GFLAGS),
COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
RK3288_CLKSEL_CON(31), 6, 2, MFLAGS, 0, 5, DFLAGS,
RK3288_CLKGATE_CON(3), 0, GFLAGS),
- DIV(0, "hclk_vio", "aclk_vio0", 0,
- RK3288_CLKSEL_CON(28), 8, 5, DFLAGS),
COMPOSITE(0, "aclk_vio1", mux_pll_src_cpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
RK3288_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS,
RK3288_CLKGATE_CON(3), 2, GFLAGS),
@@ -425,7 +485,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0,
RK3288_CLKSEL_CON(26), 8, 1, MFLAGS,
RK3288_CLKGATE_CON(3), 7, GFLAGS),
- COMPOSITE_NOGATE(0, "sclk_vip_out", mux_vip_out_p, 0,
+ COMPOSITE_NOGATE(SCLK_VIP_OUT, "sclk_vip_out", mux_vip_out_p, 0,
RK3288_CLKSEL_CON(26), 15, 1, MFLAGS, 9, 5, DFLAGS),
DIV(0, "pclk_pd_alive", "gpll", 0,
@@ -496,11 +556,11 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
RK3288_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS,
RK3288_CLKGATE_CON(4), 10, GFLAGS),
- GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", CLK_IGNORE_UNUSED,
+ GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED,
RK3288_CLKGATE_CON(13), 4, GFLAGS),
- GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", CLK_IGNORE_UNUSED,
+ GATE(SCLK_OTGPHY1, "sclk_otgphy1", "xin24m", CLK_IGNORE_UNUSED,
RK3288_CLKGATE_CON(13), 5, GFLAGS),
- GATE(SCLK_OTGPHY2, "sclk_otgphy2", "usb480m", CLK_IGNORE_UNUSED,
+ GATE(SCLK_OTGPHY2, "sclk_otgphy2", "xin24m", CLK_IGNORE_UNUSED,
RK3288_CLKGATE_CON(13), 6, GFLAGS),
GATE(SCLK_OTG_ADP, "sclk_otg_adp", "xin32k", CLK_IGNORE_UNUSED,
RK3288_CLKGATE_CON(13), 7, GFLAGS),
@@ -526,45 +586,40 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
COMPOSITE(0, "uart0_src", mux_pll_src_cpll_gll_usb_npll_p, 0,
RK3288_CLKSEL_CON(13), 13, 2, MFLAGS, 0, 7, DFLAGS,
RK3288_CLKGATE_CON(1), 8, GFLAGS),
- COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
+ COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(17), 0,
- RK3288_CLKGATE_CON(1), 9, GFLAGS),
- MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
- RK3288_CLKSEL_CON(13), 8, 2, MFLAGS),
+ RK3288_CLKGATE_CON(1), 9, GFLAGS,
+ &rk3288_uart0_fracmux),
MUX(0, "uart_src", mux_pll_src_cpll_gpll_p, 0,
RK3288_CLKSEL_CON(13), 15, 1, MFLAGS),
COMPOSITE_NOMUX(0, "uart1_src", "uart_src", 0,
RK3288_CLKSEL_CON(14), 0, 7, DFLAGS,
RK3288_CLKGATE_CON(1), 10, GFLAGS),
- COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
+ COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(18), 0,
- RK3288_CLKGATE_CON(1), 11, GFLAGS),
- MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
- RK3288_CLKSEL_CON(14), 8, 2, MFLAGS),
+ RK3288_CLKGATE_CON(1), 11, GFLAGS,
+ &rk3288_uart1_fracmux),
COMPOSITE_NOMUX(0, "uart2_src", "uart_src", 0,
RK3288_CLKSEL_CON(15), 0, 7, DFLAGS,
RK3288_CLKGATE_CON(1), 12, GFLAGS),
- COMPOSITE_FRAC(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
+ COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(19), 0,
- RK3288_CLKGATE_CON(1), 13, GFLAGS),
- MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
- RK3288_CLKSEL_CON(15), 8, 2, MFLAGS),
+ RK3288_CLKGATE_CON(1), 13, GFLAGS,
+ &rk3288_uart2_fracmux),
COMPOSITE_NOMUX(0, "uart3_src", "uart_src", 0,
RK3288_CLKSEL_CON(16), 0, 7, DFLAGS,
RK3288_CLKGATE_CON(1), 14, GFLAGS),
- COMPOSITE_FRAC(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT,
+ COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(20), 0,
- RK3288_CLKGATE_CON(1), 15, GFLAGS),
- MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT,
- RK3288_CLKSEL_CON(16), 8, 2, MFLAGS),
+ RK3288_CLKGATE_CON(1), 15, GFLAGS,
+ &rk3288_uart3_fracmux),
COMPOSITE_NOMUX(0, "uart4_src", "uart_src", 0,
RK3288_CLKSEL_CON(3), 0, 7, DFLAGS,
RK3288_CLKGATE_CON(2), 12, GFLAGS),
- COMPOSITE_FRAC(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT,
+ COMPOSITE_FRACMUX(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT,
RK3288_CLKSEL_CON(7), 0,
- RK3288_CLKGATE_CON(2), 13, GFLAGS),
- MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT,
- RK3288_CLKSEL_CON(3), 8, 2, MFLAGS),
+ RK3288_CLKGATE_CON(2), 13, GFLAGS,
+ &rk3288_uart4_fracmux),
COMPOSITE(0, "mac_pll_src", mux_pll_src_npll_cpll_gpll_p, 0,
RK3288_CLKSEL_CON(21), 0, 2, MFLAGS, 8, 5, DFLAGS,
@@ -585,6 +640,8 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
RK3288_CLKGATE_CON(2), 6, GFLAGS),
MUX(0, "sclk_hsadc_out", mux_hsadcout_p, 0,
RK3288_CLKSEL_CON(22), 4, 1, MFLAGS),
+ INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
+ RK3288_CLKSEL_CON(22), 7, IFLAGS),
GATE(0, "jtag", "ext_jtag", 0,
RK3288_CLKGATE_CON(4), 14, GFLAGS),
@@ -632,11 +689,11 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
GATE(PCLK_PUBL0, "pclk_publ0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 15, GFLAGS),
GATE(PCLK_DDRUPCTL1, "pclk_ddrupctl1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 0, GFLAGS),
GATE(PCLK_PUBL1, "pclk_publ1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 1, GFLAGS),
- GATE(0, "pclk_efuse_1024", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 2, GFLAGS),
+ GATE(PCLK_EFUSE1024, "pclk_efuse_1024", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 2, GFLAGS),
GATE(PCLK_TZPC, "pclk_tzpc", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 3, GFLAGS),
GATE(PCLK_UART2, "pclk_uart2", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 9, GFLAGS),
- GATE(0, "pclk_efuse_256", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 10, GFLAGS),
- GATE(PCLK_RKPWM, "pclk_rkpwm", "pclk_cpu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(11), 11, GFLAGS),
+ GATE(PCLK_EFUSE256, "pclk_efuse_256", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 10, GFLAGS),
+ GATE(PCLK_RKPWM, "pclk_rkpwm", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 11, GFLAGS),
/* ddrctrl [DDR Controller PHY clock] gates */
GATE(0, "nclk_ddrupctl0", "ddrphy", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(11), 4, GFLAGS),
@@ -649,7 +706,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
/* aclk_peri gates */
GATE(0, "aclk_peri_axi_matrix", "aclk_peri", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(6), 2, GFLAGS),
GATE(ACLK_DMAC2, "aclk_dmac2", "aclk_peri", 0, RK3288_CLKGATE_CON(6), 3, GFLAGS),
- GATE(0, "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(7), 11, GFLAGS),
+ GATE(0, "aclk_peri_niu", "aclk_peri", 0, RK3288_CLKGATE_CON(7), 11, GFLAGS),
GATE(ACLK_MMU, "aclk_mmu", "aclk_peri", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(8), 12, GFLAGS),
GATE(ACLK_GMAC, "aclk_gmac", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 0, GFLAGS),
GATE(HCLK_GPS, "hclk_gps", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 2, GFLAGS),
@@ -697,7 +754,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
GATE(SCLK_LCDC_PWM1, "sclk_lcdc_pwm1", "xin24m", 0, RK3288_CLKGATE_CON(13), 11, GFLAGS),
GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0, RK3288_CLKGATE_CON(5), 9, GFLAGS),
GATE(SCLK_PVTM_GPU, "sclk_pvtm_gpu", "xin24m", 0, RK3288_CLKGATE_CON(5), 10, GFLAGS),
- GATE(0, "sclk_mipidsi_24m", "xin24m", 0, RK3288_CLKGATE_CON(5), 15, GFLAGS),
+ GATE(SCLK_MIPIDSI_24M, "sclk_mipidsi_24m", "xin24m", 0, RK3288_CLKGATE_CON(5), 15, GFLAGS),
/* sclk_gpu gates */
GATE(ACLK_GPU, "aclk_gpu", "sclk_gpu", 0, RK3288_CLKGATE_CON(18), 0, GFLAGS),
@@ -712,12 +769,15 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
GATE(PCLK_GPIO5, "pclk_gpio5", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 5, GFLAGS),
GATE(PCLK_GPIO6, "pclk_gpio6", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 6, GFLAGS),
GATE(PCLK_GRF, "pclk_grf", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(14), 11, GFLAGS),
- GATE(0, "pclk_alive_niu", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(14), 12, GFLAGS),
+ GATE(0, "pclk_alive_niu", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 12, GFLAGS),
+
+ /* Watchdog pclk is controlled by RK3288_SGRF_SOC_CON0[1]. */
+ SGRF_GATE(PCLK_WDT, "pclk_wdt", "pclk_pd_alive"),
/* pclk_pd_pmu gates */
GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(17), 0, GFLAGS),
GATE(0, "pclk_intmem1", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(17), 1, GFLAGS),
- GATE(0, "pclk_pmu_niu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(17), 2, GFLAGS),
+ GATE(0, "pclk_pmu_niu", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 2, GFLAGS),
GATE(PCLK_SGRF, "pclk_sgrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(17), 3, GFLAGS),
GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 4, GFLAGS),
@@ -726,7 +786,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
GATE(HCLK_VOP0, "hclk_vop0", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 6, GFLAGS),
GATE(HCLK_VOP1, "hclk_vop1", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 8, GFLAGS),
GATE(HCLK_VIO_AHB_ARBI, "hclk_vio_ahb_arbi", "hclk_vio", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(15), 9, GFLAGS),
- GATE(HCLK_VIO_NIU, "hclk_vio_niu", "hclk_vio", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(15), 10, GFLAGS),
+ GATE(HCLK_VIO_NIU, "hclk_vio_niu", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 10, GFLAGS),
GATE(HCLK_VIP, "hclk_vip", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 15, GFLAGS),
GATE(HCLK_IEP, "hclk_iep", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 3, GFLAGS),
GATE(HCLK_ISP, "hclk_isp", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 1, GFLAGS),
@@ -742,83 +802,106 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
/* aclk_vio0 gates */
GATE(ACLK_VOP0, "aclk_vop0", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 5, GFLAGS),
GATE(ACLK_IEP, "aclk_iep", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 2, GFLAGS),
- GATE(ACLK_VIO0_NIU, "aclk_vio0_niu", "aclk_vio0", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(15), 11, GFLAGS),
+ GATE(ACLK_VIO0_NIU, "aclk_vio0_niu", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 11, GFLAGS),
GATE(ACLK_VIP, "aclk_vip", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 14, GFLAGS),
/* aclk_vio1 gates */
GATE(ACLK_VOP1, "aclk_vop1", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 7, GFLAGS),
GATE(ACLK_ISP, "aclk_isp", "aclk_vio1", 0, RK3288_CLKGATE_CON(16), 2, GFLAGS),
- GATE(ACLK_VIO1_NIU, "aclk_vio1_niu", "aclk_vio1", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(15), 12, GFLAGS),
+ GATE(ACLK_VIO1_NIU, "aclk_vio1_niu", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 12, GFLAGS),
/* aclk_rga_pre gates */
GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 0, GFLAGS),
- GATE(ACLK_RGA_NIU, "aclk_rga_niu", "aclk_rga_pre", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(15), 13, GFLAGS),
+ GATE(ACLK_RGA_NIU, "aclk_rga_niu", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 13, GFLAGS),
/*
* Other ungrouped clocks.
*/
GATE(0, "pclk_vip_in", "ext_vip", 0, RK3288_CLKGATE_CON(16), 0, GFLAGS),
- GATE(0, "pclk_isp_in", "ext_isp", 0, RK3288_CLKGATE_CON(16), 3, GFLAGS),
+ INVERTER(0, "pclk_vip", "pclk_vip_in", RK3288_CLKSEL_CON(29), 4, IFLAGS),
+ GATE(PCLK_ISP_IN, "pclk_isp_in", "ext_isp", 0, RK3288_CLKGATE_CON(16), 3, GFLAGS),
+ INVERTER(0, "pclk_isp", "pclk_isp_in", RK3288_CLKSEL_CON(29), 3, IFLAGS),
+};
+
+static struct rockchip_clk_branch rk3288w_hclkvio_branch[] __initdata = {
+ DIV(0, "hclk_vio", "aclk_vio1", 0,
+ RK3288_CLKSEL_CON(28), 8, 5, DFLAGS),
};
-static const char *rk3288_critical_clocks[] __initconst = {
+static struct rockchip_clk_branch rk3288_hclkvio_branch[] __initdata = {
+ DIV(0, "hclk_vio", "aclk_vio0", 0,
+ RK3288_CLKSEL_CON(28), 8, 5, DFLAGS),
+};
+
+static const char *const rk3288_critical_clocks[] __initconst = {
"aclk_cpu",
"aclk_peri",
+ "aclk_peri_niu",
+ "aclk_vio0_niu",
+ "aclk_vio1_niu",
+ "aclk_rga_niu",
"hclk_peri",
+ "hclk_vio_niu",
+ "pclk_alive_niu",
"pclk_pd_pmu",
+ "pclk_pmu_niu",
+ "pmu_hclk_otg0",
+ /* pwm-regulators on some boards, so handoff-critical later */
+ "pclk_rkpwm",
};
-static int __init rk3288_clk_init(struct device_node *np)
+static void __iomem *rk3288_cru_base;
+
+static void __init rk3288_common_init(struct device_node *np,
+ enum rk3288_variant soc)
{
- void __iomem *reg_base;
- struct clk *clk;
+ struct rockchip_clk_provider *ctx;
- reg_base = of_iomap(np, 0);
- if (!reg_base) {
+ rk3288_cru_base = of_iomap(np, 0);
+ if (!rk3288_cru_base) {
pr_err("%s: could not map cru region\n", __func__);
- return -ENOMEM;
+ return;
}
- rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
-
- /* xin12m is created by an cru-internal divider */
- clk = clk_fixed_factor("xin12m", "xin24m", 1, 2, 0);
- if (IS_ERR(clk))
- pr_warn("%s: could not register clock xin12m: %ld\n",
- __func__, PTR_ERR(clk));
-
- clk = clk_fixed_factor("usb480m", "xin24m", 20, 1, 0);
- if (IS_ERR(clk))
- pr_warn("%s: could not register clock usb480m: %ld\n",
- __func__, PTR_ERR(clk));
-
- clk = clk_fixed_factor("hclk_vcodec_pre",
- "hclk_vcodec_pre_v", 1, 4, 0);
- if (IS_ERR(clk))
- pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n",
- __func__, PTR_ERR(clk));
-
- /* Watchdog pclk is controlled by RK3288_SGRF_SOC_CON0[1]. */
- clk = clk_fixed_factor("pclk_wdt", "pclk_pd_alive", 1, 1, 0);
- if (IS_ERR(clk))
- pr_warn("%s: could not register clock pclk_wdt: %ld\n",
- __func__, PTR_ERR(clk));
- else
- rockchip_clk_add_lookup(clk, PCLK_WDT);
+ ctx = rockchip_clk_init(np, rk3288_cru_base, CLK_NR_CLKS);
+ if (IS_ERR(ctx)) {
+ pr_err("%s: rockchip clk init failed\n", __func__);
+ return;
+ }
- rockchip_clk_register_plls(rk3288_pll_clks,
+ rockchip_clk_register_plls(ctx, rk3288_pll_clks,
ARRAY_SIZE(rk3288_pll_clks),
RK3288_GRF_SOC_STATUS1);
- rockchip_clk_register_branches(rk3288_clk_branches,
+ rockchip_clk_register_branches(ctx, rk3288_clk_branches,
ARRAY_SIZE(rk3288_clk_branches));
+
+ if (soc == RK3288W_CRU)
+ rockchip_clk_register_branches(ctx, rk3288w_hclkvio_branch,
+ ARRAY_SIZE(rk3288w_hclkvio_branch));
+ else
+ rockchip_clk_register_branches(ctx, rk3288_hclkvio_branch,
+ ARRAY_SIZE(rk3288_hclkvio_branch));
+
rockchip_clk_protect_critical(rk3288_critical_clocks,
ARRAY_SIZE(rk3288_critical_clocks));
- rockchip_clk_register_armclk(ARMCLK, "armclk",
+ rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
&rk3288_cpuclk_data, rk3288_cpuclk_rates,
ARRAY_SIZE(rk3288_cpuclk_rates));
- return 0;
+
+ rockchip_clk_of_add_provider(np, ctx);
+}
+
+static void __init rk3288_clk_init(struct device_node *np)
+{
+ rk3288_common_init(np, RK3288_CRU);
}
CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init);
+
+static void __init rk3288w_clk_init(struct device_node *np)
+{
+ rk3288_common_init(np, RK3288W_CRU);
+}
+CLK_OF_DECLARE(rk3288w_cru, "rockchip,rk3288w-cru", rk3288w_clk_init);
diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c
new file mode 100644
index 0000000000..d6c2a04711
--- /dev/null
+++ b/drivers/clk/rockchip/clk-rk3399.c
@@ -0,0 +1,1654 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Xing Zheng <zhengxing@rock-chips.com>
+ */
+
+#include <common.h>
+#include <linux/clk.h>
+#include <of.h>
+#include <of_address.h>
+#include <linux/barebox-wrapper.h>
+#include <init.h>
+#include <linux/spinlock.h>
+#include <of_device.h>
+#include <dt-bindings/clock/rk3399-cru.h>
+#include "clk.h"
+
+enum rk3399_plls {
+ lpll, bpll, dpll, cpll, gpll, npll, vpll,
+};
+
+enum rk3399_pmu_plls {
+ ppll,
+};
+
+static struct rockchip_pll_rate_table rk3399_pll_rates[] = {
+ /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+ RK3036_PLL_RATE(2208000000, 1, 92, 1, 1, 1, 0),
+ RK3036_PLL_RATE(2184000000, 1, 91, 1, 1, 1, 0),
+ RK3036_PLL_RATE(2160000000, 1, 90, 1, 1, 1, 0),
+ RK3036_PLL_RATE(2136000000, 1, 89, 1, 1, 1, 0),
+ RK3036_PLL_RATE(2112000000, 1, 88, 1, 1, 1, 0),
+ RK3036_PLL_RATE(2088000000, 1, 87, 1, 1, 1, 0),
+ RK3036_PLL_RATE(2064000000, 1, 86, 1, 1, 1, 0),
+ RK3036_PLL_RATE(2040000000, 1, 85, 1, 1, 1, 0),
+ RK3036_PLL_RATE(2016000000, 1, 84, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1992000000, 1, 83, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1968000000, 1, 82, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1944000000, 1, 81, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1920000000, 1, 80, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1896000000, 1, 79, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1872000000, 1, 78, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1848000000, 1, 77, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1824000000, 1, 76, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1800000000, 1, 75, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1776000000, 1, 74, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1752000000, 1, 73, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1728000000, 1, 72, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1704000000, 1, 71, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1680000000, 1, 70, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1656000000, 1, 69, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1632000000, 1, 68, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1600000000, 3, 200, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1000000000, 1, 125, 3, 1, 1, 0),
+ RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 800000000, 1, 100, 3, 1, 1, 0),
+ RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 676000000, 3, 169, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
+ RK3036_PLL_RATE( 594000000, 1, 99, 4, 1, 1, 0),
+ RK3036_PLL_RATE( 533250000, 8, 711, 4, 1, 1, 0),
+ RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
+ RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
+ RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
+ RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0),
+ RK3036_PLL_RATE( 297000000, 1, 99, 4, 2, 1, 0),
+ RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0),
+ RK3036_PLL_RATE( 148500000, 1, 99, 4, 4, 1, 0),
+ RK3036_PLL_RATE( 106500000, 1, 71, 4, 4, 1, 0),
+ RK3036_PLL_RATE( 96000000, 1, 64, 4, 4, 1, 0),
+ RK3036_PLL_RATE( 74250000, 2, 99, 4, 4, 1, 0),
+ RK3036_PLL_RATE( 65000000, 1, 65, 6, 4, 1, 0),
+ RK3036_PLL_RATE( 54000000, 1, 54, 6, 4, 1, 0),
+ RK3036_PLL_RATE( 27000000, 1, 27, 6, 4, 1, 0),
+ { /* sentinel */ },
+};
+
+/* CRU parents */
+PNAME(mux_pll_p) = { "xin24m", "xin32k" };
+
+PNAME(mux_armclkl_p) = { "clk_core_l_lpll_src",
+ "clk_core_l_bpll_src",
+ "clk_core_l_dpll_src",
+ "clk_core_l_gpll_src" };
+PNAME(mux_armclkb_p) = { "clk_core_b_lpll_src",
+ "clk_core_b_bpll_src",
+ "clk_core_b_dpll_src",
+ "clk_core_b_gpll_src" };
+PNAME(mux_ddrclk_p) = { "clk_ddrc_lpll_src",
+ "clk_ddrc_bpll_src",
+ "clk_ddrc_dpll_src",
+ "clk_ddrc_gpll_src" };
+PNAME(mux_aclk_cci_p) = { "cpll_aclk_cci_src",
+ "gpll_aclk_cci_src",
+ "npll_aclk_cci_src",
+ "vpll_aclk_cci_src" };
+PNAME(mux_cci_trace_p) = { "cpll_cci_trace",
+ "gpll_cci_trace" };
+PNAME(mux_cs_p) = { "cpll_cs", "gpll_cs",
+ "npll_cs"};
+PNAME(mux_aclk_perihp_p) = { "cpll_aclk_perihp_src",
+ "gpll_aclk_perihp_src" };
+
+PNAME(mux_pll_src_cpll_gpll_p) = { "cpll", "gpll" };
+PNAME(mux_pll_src_cpll_gpll_npll_p) = { "cpll", "gpll", "npll" };
+PNAME(mux_pll_src_cpll_gpll_ppll_p) = { "cpll", "gpll", "ppll" };
+PNAME(mux_pll_src_cpll_gpll_upll_p) = { "cpll", "gpll", "upll" };
+PNAME(mux_pll_src_npll_cpll_gpll_p) = { "npll", "cpll", "gpll" };
+PNAME(mux_pll_src_cpll_gpll_npll_ppll_p) = { "cpll", "gpll", "npll",
+ "ppll" };
+PNAME(mux_pll_src_cpll_gpll_npll_24m_p) = { "cpll", "gpll", "npll",
+ "xin24m" };
+PNAME(mux_pll_src_cpll_gpll_npll_usbphy480m_p) = { "cpll", "gpll", "npll",
+ "clk_usbphy_480m" };
+PNAME(mux_pll_src_ppll_cpll_gpll_npll_p) = { "ppll", "cpll", "gpll",
+ "npll", "upll" };
+PNAME(mux_pll_src_cpll_gpll_npll_upll_24m_p) = { "cpll", "gpll", "npll",
+ "upll", "xin24m" };
+PNAME(mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p) = { "cpll", "gpll", "npll",
+ "ppll", "upll", "xin24m" };
+
+PNAME(mux_pll_src_vpll_cpll_gpll_p) = { "vpll", "cpll", "gpll" };
+PNAME(mux_pll_src_vpll_cpll_gpll_npll_p) = { "vpll", "cpll", "gpll",
+ "npll" };
+PNAME(mux_pll_src_vpll_cpll_gpll_24m_p) = { "vpll", "cpll", "gpll",
+ "xin24m" };
+
+PNAME(mux_dclk_vop0_p) = { "dclk_vop0_div",
+ "dclk_vop0_frac" };
+PNAME(mux_dclk_vop1_p) = { "dclk_vop1_div",
+ "dclk_vop1_frac" };
+
+PNAME(mux_clk_cif_p) = { "clk_cifout_src", "xin24m" };
+
+PNAME(mux_pll_src_24m_usbphy480m_p) = { "xin24m", "clk_usbphy_480m" };
+PNAME(mux_pll_src_24m_pciephy_p) = { "xin24m", "clk_pciephy_ref100m" };
+PNAME(mux_pll_src_24m_32k_cpll_gpll_p) = { "xin24m", "xin32k",
+ "cpll", "gpll" };
+PNAME(mux_pciecore_cru_phy_p) = { "clk_pcie_core_cru",
+ "clk_pcie_core_phy" };
+
+PNAME(mux_aclk_emmc_p) = { "cpll_aclk_emmc_src",
+ "gpll_aclk_emmc_src" };
+
+PNAME(mux_aclk_perilp0_p) = { "cpll_aclk_perilp0_src",
+ "gpll_aclk_perilp0_src" };
+
+PNAME(mux_fclk_cm0s_p) = { "cpll_fclk_cm0s_src",
+ "gpll_fclk_cm0s_src" };
+
+PNAME(mux_hclk_perilp1_p) = { "cpll_hclk_perilp1_src",
+ "gpll_hclk_perilp1_src" };
+
+PNAME(mux_clk_testout1_p) = { "clk_testout1_pll_src", "xin24m" };
+PNAME(mux_clk_testout2_p) = { "clk_testout2_pll_src", "xin24m" };
+
+PNAME(mux_usbphy_480m_p) = { "clk_usbphy0_480m_src",
+ "clk_usbphy1_480m_src" };
+PNAME(mux_aclk_gmac_p) = { "cpll_aclk_gmac_src",
+ "gpll_aclk_gmac_src" };
+PNAME(mux_rmii_p) = { "clk_gmac", "clkin_gmac" };
+PNAME(mux_spdif_p) = { "clk_spdif_div", "clk_spdif_frac",
+ "clkin_i2s", "xin12m" };
+PNAME(mux_i2s0_p) = { "clk_i2s0_div", "clk_i2s0_frac",
+ "clkin_i2s", "xin12m" };
+PNAME(mux_i2s1_p) = { "clk_i2s1_div", "clk_i2s1_frac",
+ "clkin_i2s", "xin12m" };
+PNAME(mux_i2s2_p) = { "clk_i2s2_div", "clk_i2s2_frac",
+ "clkin_i2s", "xin12m" };
+PNAME(mux_i2sch_p) = { "clk_i2s0", "clk_i2s1",
+ "clk_i2s2" };
+PNAME(mux_i2sout_p) = { "clk_i2sout_src", "xin12m" };
+
+PNAME(mux_uart0_p) = { "clk_uart0_div", "clk_uart0_frac", "xin24m" };
+PNAME(mux_uart1_p) = { "clk_uart1_div", "clk_uart1_frac", "xin24m" };
+PNAME(mux_uart2_p) = { "clk_uart2_div", "clk_uart2_frac", "xin24m" };
+PNAME(mux_uart3_p) = { "clk_uart3_div", "clk_uart3_frac", "xin24m" };
+
+/* PMU CRU parents */
+PNAME(mux_ppll_24m_p) = { "ppll", "xin24m" };
+PNAME(mux_24m_ppll_p) = { "xin24m", "ppll" };
+PNAME(mux_fclk_cm0s_pmu_ppll_p) = { "fclk_cm0s_pmu_ppll_src", "xin24m" };
+PNAME(mux_wifi_pmu_p) = { "clk_wifi_div", "clk_wifi_frac" };
+PNAME(mux_uart4_pmu_p) = { "clk_uart4_div", "clk_uart4_frac",
+ "xin24m" };
+PNAME(mux_clk_testout2_2io_p) = { "clk_testout2", "clk_32k_suspend_pmu" };
+
+static struct rockchip_pll_clock rk3399_pll_clks[] __initdata = {
+ [lpll] = PLL(pll_rk3399, PLL_APLLL, "lpll", mux_pll_p, 0, RK3399_PLL_CON(0),
+ RK3399_PLL_CON(3), 8, 31, 0, rk3399_pll_rates),
+ [bpll] = PLL(pll_rk3399, PLL_APLLB, "bpll", mux_pll_p, 0, RK3399_PLL_CON(8),
+ RK3399_PLL_CON(11), 8, 31, 0, rk3399_pll_rates),
+ [dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RK3399_PLL_CON(16),
+ RK3399_PLL_CON(19), 8, 31, 0, NULL),
+ [cpll] = PLL(pll_rk3399, PLL_CPLL, "cpll", mux_pll_p, 0, RK3399_PLL_CON(24),
+ RK3399_PLL_CON(27), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates),
+ [gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RK3399_PLL_CON(32),
+ RK3399_PLL_CON(35), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates),
+ [npll] = PLL(pll_rk3399, PLL_NPLL, "npll", mux_pll_p, 0, RK3399_PLL_CON(40),
+ RK3399_PLL_CON(43), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates),
+ [vpll] = PLL(pll_rk3399, PLL_VPLL, "vpll", mux_pll_p, 0, RK3399_PLL_CON(48),
+ RK3399_PLL_CON(51), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates),
+};
+
+static struct rockchip_pll_clock rk3399_pmu_pll_clks[] __initdata = {
+ [ppll] = PLL(pll_rk3399, PLL_PPLL, "ppll", mux_pll_p, 0, RK3399_PMU_PLL_CON(0),
+ RK3399_PMU_PLL_CON(3), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates),
+};
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
+
+static struct rockchip_clk_branch rk3399_spdif_fracmux __initdata =
+ MUX(0, "clk_spdif_mux", mux_spdif_p, CLK_SET_RATE_PARENT,
+ RK3399_CLKSEL_CON(32), 13, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_i2s0_fracmux __initdata =
+ MUX(0, "clk_i2s0_mux", mux_i2s0_p, CLK_SET_RATE_PARENT,
+ RK3399_CLKSEL_CON(28), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_i2s1_fracmux __initdata =
+ MUX(0, "clk_i2s1_mux", mux_i2s1_p, CLK_SET_RATE_PARENT,
+ RK3399_CLKSEL_CON(29), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_i2s2_fracmux __initdata =
+ MUX(0, "clk_i2s2_mux", mux_i2s2_p, CLK_SET_RATE_PARENT,
+ RK3399_CLKSEL_CON(30), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_uart0_fracmux __initdata =
+ MUX(SCLK_UART0, "clk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+ RK3399_CLKSEL_CON(33), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_uart1_fracmux __initdata =
+ MUX(SCLK_UART1, "clk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+ RK3399_CLKSEL_CON(34), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_uart2_fracmux __initdata =
+ MUX(SCLK_UART2, "clk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+ RK3399_CLKSEL_CON(35), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_uart3_fracmux __initdata =
+ MUX(SCLK_UART3, "clk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT,
+ RK3399_CLKSEL_CON(36), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_uart4_pmu_fracmux __initdata =
+ MUX(SCLK_UART4_PMU, "clk_uart4_pmu", mux_uart4_pmu_p, CLK_SET_RATE_PARENT,
+ RK3399_PMU_CLKSEL_CON(5), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_dclk_vop0_fracmux __initdata =
+ MUX(DCLK_VOP0, "dclk_vop0", mux_dclk_vop0_p, CLK_SET_RATE_PARENT,
+ RK3399_CLKSEL_CON(49), 11, 1, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_dclk_vop1_fracmux __initdata =
+ MUX(DCLK_VOP1, "dclk_vop1", mux_dclk_vop1_p, CLK_SET_RATE_PARENT,
+ RK3399_CLKSEL_CON(50), 11, 1, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_pmuclk_wifi_fracmux __initdata =
+ MUX(SCLK_WIFI_PMU, "clk_wifi_pmu", mux_wifi_pmu_p, CLK_SET_RATE_PARENT,
+ RK3399_PMU_CLKSEL_CON(1), 14, 1, MFLAGS);
+
+static const struct rockchip_cpuclk_reg_data rk3399_cpuclkl_data = {
+ .core_reg[0] = RK3399_CLKSEL_CON(0),
+ .div_core_shift[0] = 0,
+ .div_core_mask[0] = 0x1f,
+ .num_cores = 1,
+ .mux_core_alt = 3,
+ .mux_core_main = 0,
+ .mux_core_shift = 6,
+ .mux_core_mask = 0x3,
+};
+
+static const struct rockchip_cpuclk_reg_data rk3399_cpuclkb_data = {
+ .core_reg[0] = RK3399_CLKSEL_CON(2),
+ .div_core_shift[0] = 0,
+ .div_core_mask[0] = 0x1f,
+ .num_cores = 1,
+ .mux_core_alt = 3,
+ .mux_core_main = 1,
+ .mux_core_shift = 6,
+ .mux_core_mask = 0x3,
+};
+
+#define RK3399_DIV_ACLKM_MASK 0x1f
+#define RK3399_DIV_ACLKM_SHIFT 8
+#define RK3399_DIV_ATCLK_MASK 0x1f
+#define RK3399_DIV_ATCLK_SHIFT 0
+#define RK3399_DIV_PCLK_DBG_MASK 0x1f
+#define RK3399_DIV_PCLK_DBG_SHIFT 8
+
+#define RK3399_CLKSEL0(_offs, _aclkm) \
+ { \
+ .reg = RK3399_CLKSEL_CON(0 + _offs), \
+ .val = HIWORD_UPDATE(_aclkm, RK3399_DIV_ACLKM_MASK, \
+ RK3399_DIV_ACLKM_SHIFT), \
+ }
+#define RK3399_CLKSEL1(_offs, _atclk, _pdbg) \
+ { \
+ .reg = RK3399_CLKSEL_CON(1 + _offs), \
+ .val = HIWORD_UPDATE(_atclk, RK3399_DIV_ATCLK_MASK, \
+ RK3399_DIV_ATCLK_SHIFT) | \
+ HIWORD_UPDATE(_pdbg, RK3399_DIV_PCLK_DBG_MASK, \
+ RK3399_DIV_PCLK_DBG_SHIFT), \
+ }
+
+/* cluster_l: aclkm in clksel0, rest in clksel1 */
+#define RK3399_CPUCLKL_RATE(_prate, _aclkm, _atclk, _pdbg) \
+ { \
+ .prate = _prate##U, \
+ .divs = { \
+ RK3399_CLKSEL0(0, _aclkm), \
+ RK3399_CLKSEL1(0, _atclk, _pdbg), \
+ }, \
+ }
+
+/* cluster_b: aclkm in clksel2, rest in clksel3 */
+#define RK3399_CPUCLKB_RATE(_prate, _aclkm, _atclk, _pdbg) \
+ { \
+ .prate = _prate##U, \
+ .divs = { \
+ RK3399_CLKSEL0(2, _aclkm), \
+ RK3399_CLKSEL1(2, _atclk, _pdbg), \
+ }, \
+ }
+
+static struct rockchip_cpuclk_rate_table rk3399_cpuclkl_rates[] __initdata = {
+ RK3399_CPUCLKL_RATE(1800000000, 1, 8, 8),
+ RK3399_CPUCLKL_RATE(1704000000, 1, 8, 8),
+ RK3399_CPUCLKL_RATE(1608000000, 1, 7, 7),
+ RK3399_CPUCLKL_RATE(1512000000, 1, 7, 7),
+ RK3399_CPUCLKL_RATE(1488000000, 1, 6, 6),
+ RK3399_CPUCLKL_RATE(1416000000, 1, 6, 6),
+ RK3399_CPUCLKL_RATE(1200000000, 1, 5, 5),
+ RK3399_CPUCLKL_RATE(1008000000, 1, 5, 5),
+ RK3399_CPUCLKL_RATE( 816000000, 1, 4, 4),
+ RK3399_CPUCLKL_RATE( 696000000, 1, 3, 3),
+ RK3399_CPUCLKL_RATE( 600000000, 1, 3, 3),
+ RK3399_CPUCLKL_RATE( 408000000, 1, 2, 2),
+ RK3399_CPUCLKL_RATE( 312000000, 1, 1, 1),
+ RK3399_CPUCLKL_RATE( 216000000, 1, 1, 1),
+ RK3399_CPUCLKL_RATE( 96000000, 1, 1, 1),
+};
+
+static struct rockchip_cpuclk_rate_table rk3399_cpuclkb_rates[] __initdata = {
+ RK3399_CPUCLKB_RATE(2208000000, 1, 11, 11),
+ RK3399_CPUCLKB_RATE(2184000000, 1, 11, 11),
+ RK3399_CPUCLKB_RATE(2088000000, 1, 10, 10),
+ RK3399_CPUCLKB_RATE(2040000000, 1, 10, 10),
+ RK3399_CPUCLKB_RATE(2016000000, 1, 9, 9),
+ RK3399_CPUCLKB_RATE(1992000000, 1, 9, 9),
+ RK3399_CPUCLKB_RATE(1896000000, 1, 9, 9),
+ RK3399_CPUCLKB_RATE(1800000000, 1, 8, 8),
+ RK3399_CPUCLKB_RATE(1704000000, 1, 8, 8),
+ RK3399_CPUCLKB_RATE(1608000000, 1, 7, 7),
+ RK3399_CPUCLKB_RATE(1512000000, 1, 7, 7),
+ RK3399_CPUCLKB_RATE(1488000000, 1, 6, 6),
+ RK3399_CPUCLKB_RATE(1416000000, 1, 6, 6),
+ RK3399_CPUCLKB_RATE(1200000000, 1, 5, 5),
+ RK3399_CPUCLKB_RATE(1008000000, 1, 5, 5),
+ RK3399_CPUCLKB_RATE( 816000000, 1, 4, 4),
+ RK3399_CPUCLKB_RATE( 696000000, 1, 3, 3),
+ RK3399_CPUCLKB_RATE( 600000000, 1, 3, 3),
+ RK3399_CPUCLKB_RATE( 408000000, 1, 2, 2),
+ RK3399_CPUCLKB_RATE( 312000000, 1, 1, 1),
+ RK3399_CPUCLKB_RATE( 216000000, 1, 1, 1),
+ RK3399_CPUCLKB_RATE( 96000000, 1, 1, 1),
+};
+
+static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
+ /*
+ * CRU Clock-Architecture
+ */
+
+ /* usbphy */
+ GATE(SCLK_USB2PHY0_REF, "clk_usb2phy0_ref", "xin24m", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(6), 5, GFLAGS),
+ GATE(SCLK_USB2PHY1_REF, "clk_usb2phy1_ref", "xin24m", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(6), 6, GFLAGS),
+
+ GATE(0, "clk_usbphy0_480m_src", "clk_usbphy0_480m", 0,
+ RK3399_CLKGATE_CON(13), 12, GFLAGS),
+ GATE(0, "clk_usbphy1_480m_src", "clk_usbphy1_480m", 0,
+ RK3399_CLKGATE_CON(13), 12, GFLAGS),
+ MUX(0, "clk_usbphy_480m", mux_usbphy_480m_p, 0,
+ RK3399_CLKSEL_CON(14), 6, 1, MFLAGS),
+
+ MUX(0, "upll", mux_pll_src_24m_usbphy480m_p, 0,
+ RK3399_CLKSEL_CON(14), 15, 1, MFLAGS),
+
+ COMPOSITE_NODIV(SCLK_HSICPHY, "clk_hsicphy", mux_pll_src_cpll_gpll_npll_usbphy480m_p, 0,
+ RK3399_CLKSEL_CON(19), 0, 2, MFLAGS,
+ RK3399_CLKGATE_CON(6), 4, GFLAGS),
+
+ COMPOSITE(ACLK_USB3, "aclk_usb3", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3399_CLKSEL_CON(39), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(12), 0, GFLAGS),
+ GATE(ACLK_USB3_NOC, "aclk_usb3_noc", "aclk_usb3", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(30), 0, GFLAGS),
+ GATE(ACLK_USB3OTG0, "aclk_usb3otg0", "aclk_usb3", 0,
+ RK3399_CLKGATE_CON(30), 1, GFLAGS),
+ GATE(ACLK_USB3OTG1, "aclk_usb3otg1", "aclk_usb3", 0,
+ RK3399_CLKGATE_CON(30), 2, GFLAGS),
+ GATE(ACLK_USB3_RKSOC_AXI_PERF, "aclk_usb3_rksoc_axi_perf", "aclk_usb3", 0,
+ RK3399_CLKGATE_CON(30), 3, GFLAGS),
+ GATE(ACLK_USB3_GRF, "aclk_usb3_grf", "aclk_usb3", 0,
+ RK3399_CLKGATE_CON(30), 4, GFLAGS),
+
+ GATE(SCLK_USB3OTG0_REF, "clk_usb3otg0_ref", "xin24m", 0,
+ RK3399_CLKGATE_CON(12), 1, GFLAGS),
+ GATE(SCLK_USB3OTG1_REF, "clk_usb3otg1_ref", "xin24m", 0,
+ RK3399_CLKGATE_CON(12), 2, GFLAGS),
+
+ COMPOSITE(SCLK_USB3OTG0_SUSPEND, "clk_usb3otg0_suspend", mux_pll_p, 0,
+ RK3399_CLKSEL_CON(40), 15, 1, MFLAGS, 0, 10, DFLAGS,
+ RK3399_CLKGATE_CON(12), 3, GFLAGS),
+
+ COMPOSITE(SCLK_USB3OTG1_SUSPEND, "clk_usb3otg1_suspend", mux_pll_p, 0,
+ RK3399_CLKSEL_CON(41), 15, 1, MFLAGS, 0, 10, DFLAGS,
+ RK3399_CLKGATE_CON(12), 4, GFLAGS),
+
+ COMPOSITE(SCLK_UPHY0_TCPDPHY_REF, "clk_uphy0_tcpdphy_ref", mux_pll_p, 0,
+ RK3399_CLKSEL_CON(64), 15, 1, MFLAGS, 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(13), 4, GFLAGS),
+
+ COMPOSITE(SCLK_UPHY0_TCPDCORE, "clk_uphy0_tcpdcore", mux_pll_src_24m_32k_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(64), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(13), 5, GFLAGS),
+
+ COMPOSITE(SCLK_UPHY1_TCPDPHY_REF, "clk_uphy1_tcpdphy_ref", mux_pll_p, 0,
+ RK3399_CLKSEL_CON(65), 15, 1, MFLAGS, 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(13), 6, GFLAGS),
+
+ COMPOSITE(SCLK_UPHY1_TCPDCORE, "clk_uphy1_tcpdcore", mux_pll_src_24m_32k_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(65), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(13), 7, GFLAGS),
+
+ /* little core */
+ GATE(0, "clk_core_l_lpll_src", "lpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(0), 0, GFLAGS),
+ GATE(0, "clk_core_l_bpll_src", "bpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(0), 1, GFLAGS),
+ GATE(0, "clk_core_l_dpll_src", "dpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(0), 2, GFLAGS),
+ GATE(0, "clk_core_l_gpll_src", "gpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(0), 3, GFLAGS),
+
+ COMPOSITE_NOMUX(0, "aclkm_core_l", "armclkl", CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(0), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3399_CLKGATE_CON(0), 4, GFLAGS),
+ COMPOSITE_NOMUX(0, "atclk_core_l", "armclkl", CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(1), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3399_CLKGATE_CON(0), 5, GFLAGS),
+ COMPOSITE_NOMUX(PCLK_COREDBG_L, "pclk_dbg_core_l", "armclkl", CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(1), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3399_CLKGATE_CON(0), 6, GFLAGS),
+
+ GATE(ACLK_CORE_ADB400_CORE_L_2_CCI500, "aclk_core_adb400_core_l_2_cci500", "aclkm_core_l", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(14), 12, GFLAGS),
+ GATE(ACLK_PERF_CORE_L, "aclk_perf_core_l", "aclkm_core_l", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(14), 13, GFLAGS),
+
+ GATE(0, "clk_dbg_pd_core_l", "armclkl", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(14), 9, GFLAGS),
+ GATE(ACLK_GIC_ADB400_GIC_2_CORE_L, "aclk_core_adb400_gic_2_core_l", "armclkl", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(14), 10, GFLAGS),
+ GATE(ACLK_GIC_ADB400_CORE_L_2_GIC, "aclk_core_adb400_core_l_2_gic", "armclkl", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(14), 11, GFLAGS),
+ GATE(SCLK_PVTM_CORE_L, "clk_pvtm_core_l", "xin24m", 0,
+ RK3399_CLKGATE_CON(0), 7, GFLAGS),
+
+ /* big core */
+ GATE(0, "clk_core_b_lpll_src", "lpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(1), 0, GFLAGS),
+ GATE(0, "clk_core_b_bpll_src", "bpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(1), 1, GFLAGS),
+ GATE(0, "clk_core_b_dpll_src", "dpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(1), 2, GFLAGS),
+ GATE(0, "clk_core_b_gpll_src", "gpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(1), 3, GFLAGS),
+
+ COMPOSITE_NOMUX(0, "aclkm_core_b", "armclkb", CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(2), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3399_CLKGATE_CON(1), 4, GFLAGS),
+ COMPOSITE_NOMUX(0, "atclk_core_b", "armclkb", CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(3), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3399_CLKGATE_CON(1), 5, GFLAGS),
+ COMPOSITE_NOMUX(0, "pclk_dbg_core_b", "armclkb", CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(3), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3399_CLKGATE_CON(1), 6, GFLAGS),
+
+ GATE(ACLK_CORE_ADB400_CORE_B_2_CCI500, "aclk_core_adb400_core_b_2_cci500", "aclkm_core_b", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(14), 5, GFLAGS),
+ GATE(ACLK_PERF_CORE_B, "aclk_perf_core_b", "aclkm_core_b", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(14), 6, GFLAGS),
+
+ GATE(0, "clk_dbg_pd_core_b", "armclkb", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(14), 1, GFLAGS),
+ GATE(ACLK_GIC_ADB400_GIC_2_CORE_B, "aclk_core_adb400_gic_2_core_b", "armclkb", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(14), 3, GFLAGS),
+ GATE(ACLK_GIC_ADB400_CORE_B_2_GIC, "aclk_core_adb400_core_b_2_gic", "armclkb", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(14), 4, GFLAGS),
+
+ DIV(PCLK_COREDBG_B, "pclken_dbg_core_b", "pclk_dbg_core_b", CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(3), 13, 2, DFLAGS | CLK_DIVIDER_READ_ONLY),
+
+ GATE(0, "pclk_dbg_cxcs_pd_core_b", "pclk_dbg_core_b", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(14), 2, GFLAGS),
+
+ GATE(SCLK_PVTM_CORE_B, "clk_pvtm_core_b", "xin24m", 0,
+ RK3399_CLKGATE_CON(1), 7, GFLAGS),
+
+ /* gmac */
+ GATE(0, "cpll_aclk_gmac_src", "cpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(6), 9, GFLAGS),
+ GATE(0, "gpll_aclk_gmac_src", "gpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(6), 8, GFLAGS),
+ COMPOSITE(0, "aclk_gmac_pre", mux_aclk_gmac_p, 0,
+ RK3399_CLKSEL_CON(20), 7, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(6), 10, GFLAGS),
+
+ GATE(ACLK_GMAC, "aclk_gmac", "aclk_gmac_pre", 0,
+ RK3399_CLKGATE_CON(32), 0, GFLAGS),
+ GATE(ACLK_GMAC_NOC, "aclk_gmac_noc", "aclk_gmac_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(32), 1, GFLAGS),
+ GATE(ACLK_PERF_GMAC, "aclk_perf_gmac", "aclk_gmac_pre", 0,
+ RK3399_CLKGATE_CON(32), 4, GFLAGS),
+
+ COMPOSITE_NOMUX(0, "pclk_gmac_pre", "aclk_gmac_pre", 0,
+ RK3399_CLKSEL_CON(19), 8, 3, DFLAGS,
+ RK3399_CLKGATE_CON(6), 11, GFLAGS),
+ GATE(PCLK_GMAC, "pclk_gmac", "pclk_gmac_pre", 0,
+ RK3399_CLKGATE_CON(32), 2, GFLAGS),
+ GATE(PCLK_GMAC_NOC, "pclk_gmac_noc", "pclk_gmac_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(32), 3, GFLAGS),
+
+ COMPOSITE(SCLK_MAC, "clk_gmac", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3399_CLKSEL_CON(20), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(5), 5, GFLAGS),
+
+ MUX(SCLK_RMII_SRC, "clk_rmii_src", mux_rmii_p, CLK_SET_RATE_PARENT,
+ RK3399_CLKSEL_CON(19), 4, 1, MFLAGS),
+ GATE(SCLK_MACREF_OUT, "clk_mac_refout", "clk_rmii_src", 0,
+ RK3399_CLKGATE_CON(5), 6, GFLAGS),
+ GATE(SCLK_MACREF, "clk_mac_ref", "clk_rmii_src", 0,
+ RK3399_CLKGATE_CON(5), 7, GFLAGS),
+ GATE(SCLK_MAC_RX, "clk_rmii_rx", "clk_rmii_src", 0,
+ RK3399_CLKGATE_CON(5), 8, GFLAGS),
+ GATE(SCLK_MAC_TX, "clk_rmii_tx", "clk_rmii_src", 0,
+ RK3399_CLKGATE_CON(5), 9, GFLAGS),
+
+ /* spdif */
+ COMPOSITE(0, "clk_spdif_div", mux_pll_src_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(32), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3399_CLKGATE_CON(8), 13, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_spdif_frac", "clk_spdif_div", 0,
+ RK3399_CLKSEL_CON(99), 0,
+ RK3399_CLKGATE_CON(8), 14, GFLAGS,
+ &rk3399_spdif_fracmux),
+ GATE(SCLK_SPDIF_8CH, "clk_spdif", "clk_spdif_mux", CLK_SET_RATE_PARENT,
+ RK3399_CLKGATE_CON(8), 15, GFLAGS),
+
+ COMPOSITE(SCLK_SPDIF_REC_DPTX, "clk_spdif_rec_dptx", mux_pll_src_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(32), 15, 1, MFLAGS, 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(10), 6, GFLAGS),
+ /* i2s */
+ COMPOSITE(0, "clk_i2s0_div", mux_pll_src_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(28), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3399_CLKGATE_CON(8), 3, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_i2s0_frac", "clk_i2s0_div", 0,
+ RK3399_CLKSEL_CON(96), 0,
+ RK3399_CLKGATE_CON(8), 4, GFLAGS,
+ &rk3399_i2s0_fracmux),
+ GATE(SCLK_I2S0_8CH, "clk_i2s0", "clk_i2s0_mux", CLK_SET_RATE_PARENT,
+ RK3399_CLKGATE_CON(8), 5, GFLAGS),
+
+ COMPOSITE(0, "clk_i2s1_div", mux_pll_src_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(29), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3399_CLKGATE_CON(8), 6, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_i2s1_frac", "clk_i2s1_div", 0,
+ RK3399_CLKSEL_CON(97), 0,
+ RK3399_CLKGATE_CON(8), 7, GFLAGS,
+ &rk3399_i2s1_fracmux),
+ GATE(SCLK_I2S1_8CH, "clk_i2s1", "clk_i2s1_mux", CLK_SET_RATE_PARENT,
+ RK3399_CLKGATE_CON(8), 8, GFLAGS),
+
+ COMPOSITE(0, "clk_i2s2_div", mux_pll_src_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(30), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3399_CLKGATE_CON(8), 9, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_i2s2_frac", "clk_i2s2_div", 0,
+ RK3399_CLKSEL_CON(98), 0,
+ RK3399_CLKGATE_CON(8), 10, GFLAGS,
+ &rk3399_i2s2_fracmux),
+ GATE(SCLK_I2S2_8CH, "clk_i2s2", "clk_i2s2_mux", CLK_SET_RATE_PARENT,
+ RK3399_CLKGATE_CON(8), 11, GFLAGS),
+
+ MUX(0, "clk_i2sout_src", mux_i2sch_p, CLK_SET_RATE_PARENT,
+ RK3399_CLKSEL_CON(31), 0, 2, MFLAGS),
+ COMPOSITE_NODIV(SCLK_I2S_8CH_OUT, "clk_i2sout", mux_i2sout_p, CLK_SET_RATE_PARENT,
+ RK3399_CLKSEL_CON(31), 2, 1, MFLAGS,
+ RK3399_CLKGATE_CON(8), 12, GFLAGS),
+
+ /* uart */
+ MUX(0, "clk_uart0_src", mux_pll_src_cpll_gpll_upll_p, 0,
+ RK3399_CLKSEL_CON(33), 12, 2, MFLAGS),
+ COMPOSITE_NOMUX(0, "clk_uart0_div", "clk_uart0_src", 0,
+ RK3399_CLKSEL_CON(33), 0, 7, DFLAGS,
+ RK3399_CLKGATE_CON(9), 0, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_uart0_frac", "clk_uart0_div", 0,
+ RK3399_CLKSEL_CON(100), 0,
+ RK3399_CLKGATE_CON(9), 1, GFLAGS,
+ &rk3399_uart0_fracmux),
+
+ MUX(0, "clk_uart_src", mux_pll_src_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(33), 15, 1, MFLAGS),
+ COMPOSITE_NOMUX(0, "clk_uart1_div", "clk_uart_src", 0,
+ RK3399_CLKSEL_CON(34), 0, 7, DFLAGS,
+ RK3399_CLKGATE_CON(9), 2, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_uart1_frac", "clk_uart1_div", 0,
+ RK3399_CLKSEL_CON(101), 0,
+ RK3399_CLKGATE_CON(9), 3, GFLAGS,
+ &rk3399_uart1_fracmux),
+
+ COMPOSITE_NOMUX(0, "clk_uart2_div", "clk_uart_src", 0,
+ RK3399_CLKSEL_CON(35), 0, 7, DFLAGS,
+ RK3399_CLKGATE_CON(9), 4, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_uart2_frac", "clk_uart2_div", 0,
+ RK3399_CLKSEL_CON(102), 0,
+ RK3399_CLKGATE_CON(9), 5, GFLAGS,
+ &rk3399_uart2_fracmux),
+
+ COMPOSITE_NOMUX(0, "clk_uart3_div", "clk_uart_src", 0,
+ RK3399_CLKSEL_CON(36), 0, 7, DFLAGS,
+ RK3399_CLKGATE_CON(9), 6, GFLAGS),
+ COMPOSITE_FRACMUX(0, "clk_uart3_frac", "clk_uart3_div", 0,
+ RK3399_CLKSEL_CON(103), 0,
+ RK3399_CLKGATE_CON(9), 7, GFLAGS,
+ &rk3399_uart3_fracmux),
+
+ COMPOSITE(PCLK_DDR, "pclk_ddr", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(6), 15, 1, MFLAGS, 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(3), 4, GFLAGS),
+
+ GATE(PCLK_CENTER_MAIN_NOC, "pclk_center_main_noc", "pclk_ddr", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(18), 10, GFLAGS),
+ GATE(PCLK_DDR_MON, "pclk_ddr_mon", "pclk_ddr", 0,
+ RK3399_CLKGATE_CON(18), 12, GFLAGS),
+ GATE(PCLK_CIC, "pclk_cic", "pclk_ddr", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(18), 15, GFLAGS),
+ GATE(PCLK_DDR_SGRF, "pclk_ddr_sgrf", "pclk_ddr", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(19), 2, GFLAGS),
+
+ GATE(SCLK_PVTM_DDR, "clk_pvtm_ddr", "xin24m", 0,
+ RK3399_CLKGATE_CON(4), 11, GFLAGS),
+ GATE(SCLK_DFIMON0_TIMER, "clk_dfimon0_timer", "xin24m", 0,
+ RK3399_CLKGATE_CON(3), 5, GFLAGS),
+ GATE(SCLK_DFIMON1_TIMER, "clk_dfimon1_timer", "xin24m", 0,
+ RK3399_CLKGATE_CON(3), 6, GFLAGS),
+
+ /* cci */
+ GATE(0, "cpll_aclk_cci_src", "cpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(2), 0, GFLAGS),
+ GATE(0, "gpll_aclk_cci_src", "gpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(2), 1, GFLAGS),
+ GATE(0, "npll_aclk_cci_src", "npll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(2), 2, GFLAGS),
+ GATE(0, "vpll_aclk_cci_src", "vpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(2), 3, GFLAGS),
+
+ COMPOSITE(0, "aclk_cci_pre", mux_aclk_cci_p, CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(5), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(2), 4, GFLAGS),
+
+ GATE(ACLK_ADB400M_PD_CORE_L, "aclk_adb400m_pd_core_l", "aclk_cci_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(15), 0, GFLAGS),
+ GATE(ACLK_ADB400M_PD_CORE_B, "aclk_adb400m_pd_core_b", "aclk_cci_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(15), 1, GFLAGS),
+ GATE(ACLK_CCI, "aclk_cci", "aclk_cci_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(15), 2, GFLAGS),
+ GATE(ACLK_CCI_NOC0, "aclk_cci_noc0", "aclk_cci_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(15), 3, GFLAGS),
+ GATE(ACLK_CCI_NOC1, "aclk_cci_noc1", "aclk_cci_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(15), 4, GFLAGS),
+ GATE(ACLK_CCI_GRF, "aclk_cci_grf", "aclk_cci_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(15), 7, GFLAGS),
+
+ GATE(0, "cpll_cci_trace", "cpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(2), 5, GFLAGS),
+ GATE(0, "gpll_cci_trace", "gpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(2), 6, GFLAGS),
+ COMPOSITE(SCLK_CCI_TRACE, "clk_cci_trace", mux_cci_trace_p, CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(5), 15, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(2), 7, GFLAGS),
+
+ GATE(0, "cpll_cs", "cpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(2), 8, GFLAGS),
+ GATE(0, "gpll_cs", "gpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(2), 9, GFLAGS),
+ GATE(0, "npll_cs", "npll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(2), 10, GFLAGS),
+ COMPOSITE_NOGATE(0, "clk_cs", mux_cs_p, CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(4), 6, 2, MFLAGS, 0, 5, DFLAGS),
+ GATE(0, "clk_dbg_cxcs", "clk_cs", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(15), 5, GFLAGS),
+ GATE(0, "clk_dbg_noc", "clk_cs", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(15), 6, GFLAGS),
+
+ /* vcodec */
+ COMPOSITE(0, "aclk_vcodec_pre", mux_pll_src_cpll_gpll_npll_ppll_p, 0,
+ RK3399_CLKSEL_CON(7), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(4), 0, GFLAGS),
+ COMPOSITE_NOMUX(0, "hclk_vcodec_pre", "aclk_vcodec_pre", 0,
+ RK3399_CLKSEL_CON(7), 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(4), 1, GFLAGS),
+ GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_vcodec_pre", 0,
+ RK3399_CLKGATE_CON(17), 2, GFLAGS),
+ GATE(0, "hclk_vcodec_noc", "hclk_vcodec_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(17), 3, GFLAGS),
+
+ GATE(ACLK_VCODEC, "aclk_vcodec", "aclk_vcodec_pre", 0,
+ RK3399_CLKGATE_CON(17), 0, GFLAGS),
+ GATE(0, "aclk_vcodec_noc", "aclk_vcodec_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(17), 1, GFLAGS),
+
+ /* vdu */
+ COMPOSITE(SCLK_VDU_CORE, "clk_vdu_core", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3399_CLKSEL_CON(9), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(4), 4, GFLAGS),
+ COMPOSITE(SCLK_VDU_CA, "clk_vdu_ca", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3399_CLKSEL_CON(9), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(4), 5, GFLAGS),
+
+ COMPOSITE(0, "aclk_vdu_pre", mux_pll_src_cpll_gpll_npll_ppll_p, 0,
+ RK3399_CLKSEL_CON(8), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(4), 2, GFLAGS),
+ COMPOSITE_NOMUX(0, "hclk_vdu_pre", "aclk_vdu_pre", 0,
+ RK3399_CLKSEL_CON(8), 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(4), 3, GFLAGS),
+ GATE(HCLK_VDU, "hclk_vdu", "hclk_vdu_pre", 0,
+ RK3399_CLKGATE_CON(17), 10, GFLAGS),
+ GATE(HCLK_VDU_NOC, "hclk_vdu_noc", "hclk_vdu_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(17), 11, GFLAGS),
+
+ GATE(ACLK_VDU, "aclk_vdu", "aclk_vdu_pre", 0,
+ RK3399_CLKGATE_CON(17), 8, GFLAGS),
+ GATE(ACLK_VDU_NOC, "aclk_vdu_noc", "aclk_vdu_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(17), 9, GFLAGS),
+
+ /* iep */
+ COMPOSITE(0, "aclk_iep_pre", mux_pll_src_cpll_gpll_npll_ppll_p, 0,
+ RK3399_CLKSEL_CON(10), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(4), 6, GFLAGS),
+ COMPOSITE_NOMUX(0, "hclk_iep_pre", "aclk_iep_pre", 0,
+ RK3399_CLKSEL_CON(10), 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(4), 7, GFLAGS),
+ GATE(HCLK_IEP, "hclk_iep", "hclk_iep_pre", 0,
+ RK3399_CLKGATE_CON(16), 2, GFLAGS),
+ GATE(HCLK_IEP_NOC, "hclk_iep_noc", "hclk_iep_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(16), 3, GFLAGS),
+
+ GATE(ACLK_IEP, "aclk_iep", "aclk_iep_pre", 0,
+ RK3399_CLKGATE_CON(16), 0, GFLAGS),
+ GATE(ACLK_IEP_NOC, "aclk_iep_noc", "aclk_iep_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(16), 1, GFLAGS),
+
+ /* rga */
+ COMPOSITE(SCLK_RGA_CORE, "clk_rga_core", mux_pll_src_cpll_gpll_npll_ppll_p, 0,
+ RK3399_CLKSEL_CON(12), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(4), 10, GFLAGS),
+
+ COMPOSITE(0, "aclk_rga_pre", mux_pll_src_cpll_gpll_npll_ppll_p, 0,
+ RK3399_CLKSEL_CON(11), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(4), 8, GFLAGS),
+ COMPOSITE_NOMUX(0, "hclk_rga_pre", "aclk_rga_pre", 0,
+ RK3399_CLKSEL_CON(11), 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(4), 9, GFLAGS),
+ GATE(HCLK_RGA, "hclk_rga", "hclk_rga_pre", 0,
+ RK3399_CLKGATE_CON(16), 10, GFLAGS),
+ GATE(HCLK_RGA_NOC, "hclk_rga_noc", "hclk_rga_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(16), 11, GFLAGS),
+
+ GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0,
+ RK3399_CLKGATE_CON(16), 8, GFLAGS),
+ GATE(ACLK_RGA_NOC, "aclk_rga_noc", "aclk_rga_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(16), 9, GFLAGS),
+
+ /* center */
+ COMPOSITE(0, "aclk_center", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(12), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(3), 7, GFLAGS),
+ GATE(ACLK_CENTER_MAIN_NOC, "aclk_center_main_noc", "aclk_center", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(19), 0, GFLAGS),
+ GATE(ACLK_CENTER_PERI_NOC, "aclk_center_peri_noc", "aclk_center", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(19), 1, GFLAGS),
+
+ /* gpu */
+ COMPOSITE(0, "aclk_gpu_pre", mux_pll_src_ppll_cpll_gpll_npll_p, CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(13), 5, 3, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(13), 0, GFLAGS),
+ GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_pre", 0,
+ RK3399_CLKGATE_CON(30), 8, GFLAGS),
+ GATE(ACLK_PERF_GPU, "aclk_perf_gpu", "aclk_gpu_pre", 0,
+ RK3399_CLKGATE_CON(30), 10, GFLAGS),
+ GATE(ACLK_GPU_GRF, "aclk_gpu_grf", "aclk_gpu_pre", 0,
+ RK3399_CLKGATE_CON(30), 11, GFLAGS),
+ GATE(SCLK_PVTM_GPU, "aclk_pvtm_gpu", "xin24m", 0,
+ RK3399_CLKGATE_CON(13), 1, GFLAGS),
+
+ /* perihp */
+ GATE(0, "cpll_aclk_perihp_src", "cpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(5), 1, GFLAGS),
+ GATE(0, "gpll_aclk_perihp_src", "gpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(5), 0, GFLAGS),
+ COMPOSITE(ACLK_PERIHP, "aclk_perihp", mux_aclk_perihp_p, CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(14), 7, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(5), 2, GFLAGS),
+ COMPOSITE_NOMUX(HCLK_PERIHP, "hclk_perihp", "aclk_perihp", CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(14), 8, 2, DFLAGS,
+ RK3399_CLKGATE_CON(5), 3, GFLAGS),
+ COMPOSITE_NOMUX(PCLK_PERIHP, "pclk_perihp", "aclk_perihp", CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(14), 12, 2, DFLAGS,
+ RK3399_CLKGATE_CON(5), 4, GFLAGS),
+
+ GATE(ACLK_PERF_PCIE, "aclk_perf_pcie", "aclk_perihp", 0,
+ RK3399_CLKGATE_CON(20), 2, GFLAGS),
+ GATE(ACLK_PCIE, "aclk_pcie", "aclk_perihp", 0,
+ RK3399_CLKGATE_CON(20), 10, GFLAGS),
+ GATE(0, "aclk_perihp_noc", "aclk_perihp", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(20), 12, GFLAGS),
+
+ GATE(HCLK_HOST0, "hclk_host0", "hclk_perihp", 0,
+ RK3399_CLKGATE_CON(20), 5, GFLAGS),
+ GATE(HCLK_HOST0_ARB, "hclk_host0_arb", "hclk_perihp", 0,
+ RK3399_CLKGATE_CON(20), 6, GFLAGS),
+ GATE(HCLK_HOST1, "hclk_host1", "hclk_perihp", 0,
+ RK3399_CLKGATE_CON(20), 7, GFLAGS),
+ GATE(HCLK_HOST1_ARB, "hclk_host1_arb", "hclk_perihp", 0,
+ RK3399_CLKGATE_CON(20), 8, GFLAGS),
+ GATE(HCLK_HSIC, "hclk_hsic", "hclk_perihp", 0,
+ RK3399_CLKGATE_CON(20), 9, GFLAGS),
+ GATE(0, "hclk_perihp_noc", "hclk_perihp", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(20), 13, GFLAGS),
+ GATE(0, "hclk_ahb1tom", "hclk_perihp", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(20), 15, GFLAGS),
+
+ GATE(PCLK_PERIHP_GRF, "pclk_perihp_grf", "pclk_perihp", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(20), 4, GFLAGS),
+ GATE(PCLK_PCIE, "pclk_pcie", "pclk_perihp", 0,
+ RK3399_CLKGATE_CON(20), 11, GFLAGS),
+ GATE(0, "pclk_perihp_noc", "pclk_perihp", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(20), 14, GFLAGS),
+ GATE(PCLK_HSICPHY, "pclk_hsicphy", "pclk_perihp", 0,
+ RK3399_CLKGATE_CON(31), 8, GFLAGS),
+
+ /* sdio & sdmmc */
+ COMPOSITE(HCLK_SD, "hclk_sd", mux_pll_src_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(13), 15, 1, MFLAGS, 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(12), 13, GFLAGS),
+ GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_sd", 0,
+ RK3399_CLKGATE_CON(33), 8, GFLAGS),
+ GATE(0, "hclk_sdmmc_noc", "hclk_sd", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(33), 9, GFLAGS),
+
+ COMPOSITE(SCLK_SDIO, "clk_sdio", mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p, 0,
+ RK3399_CLKSEL_CON(15), 8, 3, MFLAGS, 0, 7, DFLAGS,
+ RK3399_CLKGATE_CON(6), 0, GFLAGS),
+
+ COMPOSITE(SCLK_SDMMC, "clk_sdmmc", mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p, 0,
+ RK3399_CLKSEL_CON(16), 8, 3, MFLAGS, 0, 7, DFLAGS,
+ RK3399_CLKGATE_CON(6), 1, GFLAGS),
+
+ MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "clk_sdmmc", RK3399_SDMMC_CON0, 1),
+ MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "clk_sdmmc", RK3399_SDMMC_CON1, 1),
+
+ MMC(SCLK_SDIO_DRV, "sdio_drv", "clk_sdio", RK3399_SDIO_CON0, 1),
+ MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "clk_sdio", RK3399_SDIO_CON1, 1),
+
+ /* pcie */
+ COMPOSITE(SCLK_PCIE_PM, "clk_pcie_pm", mux_pll_src_cpll_gpll_npll_24m_p, 0,
+ RK3399_CLKSEL_CON(17), 8, 3, MFLAGS, 0, 7, DFLAGS,
+ RK3399_CLKGATE_CON(6), 2, GFLAGS),
+
+ COMPOSITE_NOMUX(SCLK_PCIEPHY_REF100M, "clk_pciephy_ref100m", "npll", 0,
+ RK3399_CLKSEL_CON(18), 11, 5, DFLAGS,
+ RK3399_CLKGATE_CON(12), 6, GFLAGS),
+ MUX(SCLK_PCIEPHY_REF, "clk_pciephy_ref", mux_pll_src_24m_pciephy_p, CLK_SET_RATE_PARENT,
+ RK3399_CLKSEL_CON(18), 10, 1, MFLAGS),
+
+ COMPOSITE(0, "clk_pcie_core_cru", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3399_CLKSEL_CON(18), 8, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3399_CLKGATE_CON(6), 3, GFLAGS),
+ MUX(SCLK_PCIE_CORE, "clk_pcie_core", mux_pciecore_cru_phy_p, CLK_SET_RATE_PARENT,
+ RK3399_CLKSEL_CON(18), 7, 1, MFLAGS),
+
+ /* emmc */
+ COMPOSITE(SCLK_EMMC, "clk_emmc", mux_pll_src_cpll_gpll_npll_upll_24m_p, 0,
+ RK3399_CLKSEL_CON(22), 8, 3, MFLAGS, 0, 7, DFLAGS,
+ RK3399_CLKGATE_CON(6), 14, GFLAGS),
+
+ GATE(0, "cpll_aclk_emmc_src", "cpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(6), 13, GFLAGS),
+ GATE(0, "gpll_aclk_emmc_src", "gpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(6), 12, GFLAGS),
+ COMPOSITE_NOGATE(ACLK_EMMC, "aclk_emmc", mux_aclk_emmc_p, CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(21), 7, 1, MFLAGS, 0, 5, DFLAGS),
+ GATE(ACLK_EMMC_CORE, "aclk_emmccore", "aclk_emmc", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(32), 8, GFLAGS),
+ GATE(ACLK_EMMC_NOC, "aclk_emmc_noc", "aclk_emmc", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(32), 9, GFLAGS),
+ GATE(ACLK_EMMC_GRF, "aclk_emmcgrf", "aclk_emmc", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(32), 10, GFLAGS),
+
+ /* perilp0 */
+ GATE(0, "cpll_aclk_perilp0_src", "cpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(7), 1, GFLAGS),
+ GATE(0, "gpll_aclk_perilp0_src", "gpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(7), 0, GFLAGS),
+ COMPOSITE(ACLK_PERILP0, "aclk_perilp0", mux_aclk_perilp0_p, CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(23), 7, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(7), 2, GFLAGS),
+ COMPOSITE_NOMUX(HCLK_PERILP0, "hclk_perilp0", "aclk_perilp0", CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(23), 8, 2, DFLAGS,
+ RK3399_CLKGATE_CON(7), 3, GFLAGS),
+ COMPOSITE_NOMUX(PCLK_PERILP0, "pclk_perilp0", "aclk_perilp0", 0,
+ RK3399_CLKSEL_CON(23), 12, 3, DFLAGS,
+ RK3399_CLKGATE_CON(7), 4, GFLAGS),
+
+ /* aclk_perilp0 gates */
+ GATE(ACLK_INTMEM, "aclk_intmem", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 0, GFLAGS),
+ GATE(ACLK_TZMA, "aclk_tzma", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 1, GFLAGS),
+ GATE(SCLK_INTMEM0, "clk_intmem0", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 2, GFLAGS),
+ GATE(SCLK_INTMEM1, "clk_intmem1", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 3, GFLAGS),
+ GATE(SCLK_INTMEM2, "clk_intmem2", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 4, GFLAGS),
+ GATE(SCLK_INTMEM3, "clk_intmem3", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 5, GFLAGS),
+ GATE(SCLK_INTMEM4, "clk_intmem4", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 6, GFLAGS),
+ GATE(SCLK_INTMEM5, "clk_intmem5", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 7, GFLAGS),
+ GATE(ACLK_DCF, "aclk_dcf", "aclk_perilp0", 0, RK3399_CLKGATE_CON(23), 8, GFLAGS),
+ GATE(ACLK_DMAC0_PERILP, "aclk_dmac0_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 5, GFLAGS),
+ GATE(ACLK_DMAC1_PERILP, "aclk_dmac1_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 6, GFLAGS),
+ GATE(ACLK_PERILP0_NOC, "aclk_perilp0_noc", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 7, GFLAGS),
+
+ /* hclk_perilp0 gates */
+ GATE(HCLK_ROM, "hclk_rom", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 4, GFLAGS),
+ GATE(HCLK_M_CRYPTO0, "hclk_m_crypto0", "hclk_perilp0", 0, RK3399_CLKGATE_CON(24), 5, GFLAGS),
+ GATE(HCLK_S_CRYPTO0, "hclk_s_crypto0", "hclk_perilp0", 0, RK3399_CLKGATE_CON(24), 6, GFLAGS),
+ GATE(HCLK_M_CRYPTO1, "hclk_m_crypto1", "hclk_perilp0", 0, RK3399_CLKGATE_CON(24), 14, GFLAGS),
+ GATE(HCLK_S_CRYPTO1, "hclk_s_crypto1", "hclk_perilp0", 0, RK3399_CLKGATE_CON(24), 15, GFLAGS),
+ GATE(HCLK_PERILP0_NOC, "hclk_perilp0_noc", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 8, GFLAGS),
+
+ /* pclk_perilp0 gates */
+ GATE(PCLK_DCF, "pclk_dcf", "pclk_perilp0", 0, RK3399_CLKGATE_CON(23), 9, GFLAGS),
+
+ /* crypto */
+ COMPOSITE(SCLK_CRYPTO0, "clk_crypto0", mux_pll_src_cpll_gpll_ppll_p, 0,
+ RK3399_CLKSEL_CON(24), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(7), 7, GFLAGS),
+
+ COMPOSITE(SCLK_CRYPTO1, "clk_crypto1", mux_pll_src_cpll_gpll_ppll_p, 0,
+ RK3399_CLKSEL_CON(26), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(7), 8, GFLAGS),
+
+ /* cm0s_perilp */
+ GATE(0, "cpll_fclk_cm0s_src", "cpll", 0,
+ RK3399_CLKGATE_CON(7), 6, GFLAGS),
+ GATE(0, "gpll_fclk_cm0s_src", "gpll", 0,
+ RK3399_CLKGATE_CON(7), 5, GFLAGS),
+ COMPOSITE(FCLK_CM0S, "fclk_cm0s", mux_fclk_cm0s_p, 0,
+ RK3399_CLKSEL_CON(24), 15, 1, MFLAGS, 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(7), 9, GFLAGS),
+
+ /* fclk_cm0s gates */
+ GATE(SCLK_M0_PERILP, "sclk_m0_perilp", "fclk_cm0s", 0, RK3399_CLKGATE_CON(24), 8, GFLAGS),
+ GATE(HCLK_M0_PERILP, "hclk_m0_perilp", "fclk_cm0s", 0, RK3399_CLKGATE_CON(24), 9, GFLAGS),
+ GATE(DCLK_M0_PERILP, "dclk_m0_perilp", "fclk_cm0s", 0, RK3399_CLKGATE_CON(24), 10, GFLAGS),
+ GATE(SCLK_M0_PERILP_DEC, "clk_m0_perilp_dec", "fclk_cm0s", 0, RK3399_CLKGATE_CON(24), 11, GFLAGS),
+ GATE(HCLK_M0_PERILP_NOC, "hclk_m0_perilp_noc", "fclk_cm0s", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 11, GFLAGS),
+
+ /* perilp1 */
+ GATE(0, "cpll_hclk_perilp1_src", "cpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(8), 1, GFLAGS),
+ GATE(0, "gpll_hclk_perilp1_src", "gpll", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(8), 0, GFLAGS),
+ COMPOSITE_NOGATE(HCLK_PERILP1, "hclk_perilp1", mux_hclk_perilp1_p, CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(25), 7, 1, MFLAGS, 0, 5, DFLAGS),
+ COMPOSITE_NOMUX(PCLK_PERILP1, "pclk_perilp1", "hclk_perilp1", CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(25), 8, 3, DFLAGS,
+ RK3399_CLKGATE_CON(8), 2, GFLAGS),
+
+ /* hclk_perilp1 gates */
+ GATE(0, "hclk_perilp1_noc", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 9, GFLAGS),
+ GATE(0, "hclk_sdio_noc", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 12, GFLAGS),
+ GATE(HCLK_I2S0_8CH, "hclk_i2s0", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 0, GFLAGS),
+ GATE(HCLK_I2S1_8CH, "hclk_i2s1", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 1, GFLAGS),
+ GATE(HCLK_I2S2_8CH, "hclk_i2s2", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 2, GFLAGS),
+ GATE(HCLK_SPDIF, "hclk_spdif", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 3, GFLAGS),
+ GATE(HCLK_SDIO, "hclk_sdio", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 4, GFLAGS),
+ GATE(PCLK_SPI5, "pclk_spi5", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 5, GFLAGS),
+ GATE(0, "hclk_sdioaudio_noc", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(34), 6, GFLAGS),
+
+ /* pclk_perilp1 gates */
+ GATE(PCLK_UART0, "pclk_uart0", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 0, GFLAGS),
+ GATE(PCLK_UART1, "pclk_uart1", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 1, GFLAGS),
+ GATE(PCLK_UART2, "pclk_uart2", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 2, GFLAGS),
+ GATE(PCLK_UART3, "pclk_uart3", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 3, GFLAGS),
+ GATE(PCLK_I2C7, "pclk_rki2c7", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 5, GFLAGS),
+ GATE(PCLK_I2C1, "pclk_rki2c1", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 6, GFLAGS),
+ GATE(PCLK_I2C5, "pclk_rki2c5", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 7, GFLAGS),
+ GATE(PCLK_I2C6, "pclk_rki2c6", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 8, GFLAGS),
+ GATE(PCLK_I2C2, "pclk_rki2c2", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 9, GFLAGS),
+ GATE(PCLK_I2C3, "pclk_rki2c3", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 10, GFLAGS),
+ GATE(PCLK_MAILBOX0, "pclk_mailbox0", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 11, GFLAGS),
+ GATE(PCLK_SARADC, "pclk_saradc", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 12, GFLAGS),
+ GATE(PCLK_TSADC, "pclk_tsadc", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 13, GFLAGS),
+ GATE(PCLK_EFUSE1024NS, "pclk_efuse1024ns", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 14, GFLAGS),
+ GATE(PCLK_EFUSE1024S, "pclk_efuse1024s", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 15, GFLAGS),
+ GATE(PCLK_SPI0, "pclk_spi0", "pclk_perilp1", 0, RK3399_CLKGATE_CON(23), 10, GFLAGS),
+ GATE(PCLK_SPI1, "pclk_spi1", "pclk_perilp1", 0, RK3399_CLKGATE_CON(23), 11, GFLAGS),
+ GATE(PCLK_SPI2, "pclk_spi2", "pclk_perilp1", 0, RK3399_CLKGATE_CON(23), 12, GFLAGS),
+ GATE(PCLK_SPI4, "pclk_spi4", "pclk_perilp1", 0, RK3399_CLKGATE_CON(23), 13, GFLAGS),
+ GATE(PCLK_PERIHP_GRF, "pclk_perilp_sgrf", "pclk_perilp1", 0, RK3399_CLKGATE_CON(24), 13, GFLAGS),
+ GATE(0, "pclk_perilp1_noc", "pclk_perilp1", 0, RK3399_CLKGATE_CON(25), 10, GFLAGS),
+
+ /* saradc */
+ COMPOSITE_NOMUX(SCLK_SARADC, "clk_saradc", "xin24m", 0,
+ RK3399_CLKSEL_CON(26), 8, 8, DFLAGS,
+ RK3399_CLKGATE_CON(9), 11, GFLAGS),
+
+ /* tsadc */
+ COMPOSITE(SCLK_TSADC, "clk_tsadc", mux_pll_p, 0,
+ RK3399_CLKSEL_CON(27), 15, 1, MFLAGS, 0, 10, DFLAGS,
+ RK3399_CLKGATE_CON(9), 10, GFLAGS),
+
+ /* cif_testout */
+ MUX(0, "clk_testout1_pll_src", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3399_CLKSEL_CON(38), 6, 2, MFLAGS),
+ COMPOSITE(SCLK_TESTCLKOUT1, "clk_testout1", mux_clk_testout1_p, 0,
+ RK3399_CLKSEL_CON(38), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(13), 14, GFLAGS),
+
+ MUX(0, "clk_testout2_pll_src", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3399_CLKSEL_CON(38), 14, 2, MFLAGS),
+ COMPOSITE(SCLK_TESTCLKOUT2, "clk_testout2", mux_clk_testout2_p, 0,
+ RK3399_CLKSEL_CON(38), 13, 1, MFLAGS, 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(13), 15, GFLAGS),
+
+ /* vio */
+ COMPOSITE(ACLK_VIO, "aclk_vio", mux_pll_src_cpll_gpll_ppll_p, CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(42), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(11), 0, GFLAGS),
+ COMPOSITE_NOMUX(PCLK_VIO, "pclk_vio", "aclk_vio", 0,
+ RK3399_CLKSEL_CON(43), 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(11), 1, GFLAGS),
+
+ GATE(ACLK_VIO_NOC, "aclk_vio_noc", "aclk_vio", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(29), 0, GFLAGS),
+
+ GATE(PCLK_MIPI_DSI0, "pclk_mipi_dsi0", "pclk_vio", 0,
+ RK3399_CLKGATE_CON(29), 1, GFLAGS),
+ GATE(PCLK_MIPI_DSI1, "pclk_mipi_dsi1", "pclk_vio", 0,
+ RK3399_CLKGATE_CON(29), 2, GFLAGS),
+ GATE(PCLK_VIO_GRF, "pclk_vio_grf", "pclk_vio", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(29), 12, GFLAGS),
+
+ /* hdcp */
+ COMPOSITE(ACLK_HDCP, "aclk_hdcp", mux_pll_src_cpll_gpll_ppll_p, 0,
+ RK3399_CLKSEL_CON(42), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(11), 12, GFLAGS),
+ COMPOSITE_NOMUX(HCLK_HDCP, "hclk_hdcp", "aclk_hdcp", 0,
+ RK3399_CLKSEL_CON(43), 5, 5, DFLAGS,
+ RK3399_CLKGATE_CON(11), 3, GFLAGS),
+ COMPOSITE_NOMUX(PCLK_HDCP, "pclk_hdcp", "aclk_hdcp", 0,
+ RK3399_CLKSEL_CON(43), 10, 5, DFLAGS,
+ RK3399_CLKGATE_CON(11), 10, GFLAGS),
+
+ GATE(ACLK_HDCP_NOC, "aclk_hdcp_noc", "aclk_hdcp", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(29), 4, GFLAGS),
+ GATE(ACLK_HDCP22, "aclk_hdcp22", "aclk_hdcp", 0,
+ RK3399_CLKGATE_CON(29), 10, GFLAGS),
+
+ GATE(HCLK_HDCP_NOC, "hclk_hdcp_noc", "hclk_hdcp", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(29), 5, GFLAGS),
+ GATE(HCLK_HDCP22, "hclk_hdcp22", "hclk_hdcp", 0,
+ RK3399_CLKGATE_CON(29), 9, GFLAGS),
+
+ GATE(PCLK_HDCP_NOC, "pclk_hdcp_noc", "pclk_hdcp", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(29), 3, GFLAGS),
+ GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "pclk_hdcp", 0,
+ RK3399_CLKGATE_CON(29), 6, GFLAGS),
+ GATE(PCLK_DP_CTRL, "pclk_dp_ctrl", "pclk_hdcp", 0,
+ RK3399_CLKGATE_CON(29), 7, GFLAGS),
+ GATE(PCLK_HDCP22, "pclk_hdcp22", "pclk_hdcp", 0,
+ RK3399_CLKGATE_CON(29), 8, GFLAGS),
+ GATE(PCLK_GASKET, "pclk_gasket", "pclk_hdcp", 0,
+ RK3399_CLKGATE_CON(29), 11, GFLAGS),
+
+ /* edp */
+ COMPOSITE(SCLK_DP_CORE, "clk_dp_core", mux_pll_src_npll_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(46), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(11), 8, GFLAGS),
+
+ COMPOSITE(PCLK_EDP, "pclk_edp", mux_pll_src_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(44), 15, 1, MFLAGS, 8, 6, DFLAGS,
+ RK3399_CLKGATE_CON(11), 11, GFLAGS),
+ GATE(PCLK_EDP_NOC, "pclk_edp_noc", "pclk_edp", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(32), 12, GFLAGS),
+ GATE(PCLK_EDP_CTRL, "pclk_edp_ctrl", "pclk_edp", 0,
+ RK3399_CLKGATE_CON(32), 13, GFLAGS),
+
+ /* hdmi */
+ GATE(SCLK_HDMI_SFR, "clk_hdmi_sfr", "xin24m", 0,
+ RK3399_CLKGATE_CON(11), 6, GFLAGS),
+
+ COMPOSITE(SCLK_HDMI_CEC, "clk_hdmi_cec", mux_pll_p, 0,
+ RK3399_CLKSEL_CON(45), 15, 1, MFLAGS, 0, 10, DFLAGS,
+ RK3399_CLKGATE_CON(11), 7, GFLAGS),
+
+ /* vop0 */
+ COMPOSITE(ACLK_VOP0_PRE, "aclk_vop0_pre", mux_pll_src_vpll_cpll_gpll_npll_p, 0,
+ RK3399_CLKSEL_CON(47), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(10), 8, GFLAGS),
+ COMPOSITE_NOMUX(0, "hclk_vop0_pre", "aclk_vop0_pre", 0,
+ RK3399_CLKSEL_CON(47), 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(10), 9, GFLAGS),
+
+ GATE(ACLK_VOP0, "aclk_vop0", "aclk_vop0_pre", 0,
+ RK3399_CLKGATE_CON(28), 3, GFLAGS),
+ GATE(ACLK_VOP0_NOC, "aclk_vop0_noc", "aclk_vop0_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(28), 1, GFLAGS),
+
+ GATE(HCLK_VOP0, "hclk_vop0", "hclk_vop0_pre", 0,
+ RK3399_CLKGATE_CON(28), 2, GFLAGS),
+ GATE(HCLK_VOP0_NOC, "hclk_vop0_noc", "hclk_vop0_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(28), 0, GFLAGS),
+
+ COMPOSITE(DCLK_VOP0_DIV, "dclk_vop0_div", mux_pll_src_vpll_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(49), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3399_CLKGATE_CON(10), 12, GFLAGS),
+
+ COMPOSITE_FRACMUX_NOGATE(DCLK_VOP0_FRAC, "dclk_vop0_frac", "dclk_vop0_div", 0,
+ RK3399_CLKSEL_CON(106), 0,
+ &rk3399_dclk_vop0_fracmux),
+
+ COMPOSITE(SCLK_VOP0_PWM, "clk_vop0_pwm", mux_pll_src_vpll_cpll_gpll_24m_p, 0,
+ RK3399_CLKSEL_CON(51), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(10), 14, GFLAGS),
+
+ /* vop1 */
+ COMPOSITE(ACLK_VOP1_PRE, "aclk_vop1_pre", mux_pll_src_vpll_cpll_gpll_npll_p, 0,
+ RK3399_CLKSEL_CON(48), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(10), 10, GFLAGS),
+ COMPOSITE_NOMUX(0, "hclk_vop1_pre", "aclk_vop1_pre", 0,
+ RK3399_CLKSEL_CON(48), 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(10), 11, GFLAGS),
+
+ GATE(ACLK_VOP1, "aclk_vop1", "aclk_vop1_pre", 0,
+ RK3399_CLKGATE_CON(28), 7, GFLAGS),
+ GATE(ACLK_VOP1_NOC, "aclk_vop1_noc", "aclk_vop1_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(28), 5, GFLAGS),
+
+ GATE(HCLK_VOP1, "hclk_vop1", "hclk_vop1_pre", 0,
+ RK3399_CLKGATE_CON(28), 6, GFLAGS),
+ GATE(HCLK_VOP1_NOC, "hclk_vop1_noc", "hclk_vop1_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(28), 4, GFLAGS),
+
+ COMPOSITE(DCLK_VOP1_DIV, "dclk_vop1_div", mux_pll_src_vpll_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(50), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3399_CLKGATE_CON(10), 13, GFLAGS),
+
+ COMPOSITE_FRACMUX_NOGATE(DCLK_VOP1_FRAC, "dclk_vop1_frac", "dclk_vop1_div", 0,
+ RK3399_CLKSEL_CON(107), 0,
+ &rk3399_dclk_vop1_fracmux),
+
+ COMPOSITE(SCLK_VOP1_PWM, "clk_vop1_pwm", mux_pll_src_vpll_cpll_gpll_24m_p, CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(52), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(10), 15, GFLAGS),
+
+ /* isp */
+ COMPOSITE(ACLK_ISP0, "aclk_isp0", mux_pll_src_cpll_gpll_ppll_p, 0,
+ RK3399_CLKSEL_CON(53), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(12), 8, GFLAGS),
+ COMPOSITE_NOMUX(HCLK_ISP0, "hclk_isp0", "aclk_isp0", 0,
+ RK3399_CLKSEL_CON(53), 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(12), 9, GFLAGS),
+
+ GATE(ACLK_ISP0_NOC, "aclk_isp0_noc", "aclk_isp0", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(27), 1, GFLAGS),
+ GATE(ACLK_ISP0_WRAPPER, "aclk_isp0_wrapper", "aclk_isp0", 0,
+ RK3399_CLKGATE_CON(27), 5, GFLAGS),
+ GATE(HCLK_ISP1_WRAPPER, "hclk_isp1_wrapper", "aclk_isp0", 0,
+ RK3399_CLKGATE_CON(27), 7, GFLAGS),
+
+ GATE(HCLK_ISP0_NOC, "hclk_isp0_noc", "hclk_isp0", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(27), 0, GFLAGS),
+ GATE(HCLK_ISP0_WRAPPER, "hclk_isp0_wrapper", "hclk_isp0", 0,
+ RK3399_CLKGATE_CON(27), 4, GFLAGS),
+
+ COMPOSITE(SCLK_ISP0, "clk_isp0", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3399_CLKSEL_CON(55), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(11), 4, GFLAGS),
+
+ COMPOSITE(ACLK_ISP1, "aclk_isp1", mux_pll_src_cpll_gpll_ppll_p, 0,
+ RK3399_CLKSEL_CON(54), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(12), 10, GFLAGS),
+ COMPOSITE_NOMUX(HCLK_ISP1, "hclk_isp1", "aclk_isp1", 0,
+ RK3399_CLKSEL_CON(54), 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(12), 11, GFLAGS),
+
+ GATE(ACLK_ISP1_NOC, "aclk_isp1_noc", "aclk_isp1", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(27), 3, GFLAGS),
+
+ GATE(HCLK_ISP1_NOC, "hclk_isp1_noc", "hclk_isp1", CLK_IGNORE_UNUSED,
+ RK3399_CLKGATE_CON(27), 2, GFLAGS),
+ GATE(ACLK_ISP1_WRAPPER, "aclk_isp1_wrapper", "hclk_isp1", 0,
+ RK3399_CLKGATE_CON(27), 8, GFLAGS),
+
+ COMPOSITE(SCLK_ISP1, "clk_isp1", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3399_CLKSEL_CON(55), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(11), 5, GFLAGS),
+
+ /*
+ * We use pclkin_cifinv by default GRF_SOC_CON20[9] (GSC20_9) setting in system,
+ * so we ignore the mux and make clocks nodes as following,
+ *
+ * pclkin_cifinv --|-------\
+ * |GSC20_9|-- pclkin_cifmux -- |G27_6| -- pclkin_isp1_wrapper
+ * pclkin_cif --|-------/
+ */
+ GATE(PCLK_ISP1_WRAPPER, "pclkin_isp1_wrapper", "pclkin_cif", 0,
+ RK3399_CLKGATE_CON(27), 6, GFLAGS),
+
+ /* cif */
+ COMPOSITE_NODIV(0, "clk_cifout_src", mux_pll_src_cpll_gpll_npll_p, 0,
+ RK3399_CLKSEL_CON(56), 6, 2, MFLAGS,
+ RK3399_CLKGATE_CON(10), 7, GFLAGS),
+
+ COMPOSITE_NOGATE(SCLK_CIF_OUT, "clk_cifout", mux_clk_cif_p, 0,
+ RK3399_CLKSEL_CON(56), 5, 1, MFLAGS, 0, 5, DFLAGS),
+
+ /* gic */
+ COMPOSITE(ACLK_GIC_PRE, "aclk_gic_pre", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(56), 15, 1, MFLAGS, 8, 5, DFLAGS,
+ RK3399_CLKGATE_CON(12), 12, GFLAGS),
+
+ GATE(ACLK_GIC, "aclk_gic", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 0, GFLAGS),
+ GATE(ACLK_GIC_NOC, "aclk_gic_noc", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 1, GFLAGS),
+ GATE(ACLK_GIC_ADB400_CORE_L_2_GIC, "aclk_gic_adb400_core_l_2_gic", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 2, GFLAGS),
+ GATE(ACLK_GIC_ADB400_CORE_B_2_GIC, "aclk_gic_adb400_core_b_2_gic", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 3, GFLAGS),
+ GATE(ACLK_GIC_ADB400_GIC_2_CORE_L, "aclk_gic_adb400_gic_2_core_l", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 4, GFLAGS),
+ GATE(ACLK_GIC_ADB400_GIC_2_CORE_B, "aclk_gic_adb400_gic_2_core_b", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 5, GFLAGS),
+
+ /* alive */
+ /* pclk_alive_gpll_src is controlled by PMUGRF_SOC_CON0[6] */
+ DIV(PCLK_ALIVE, "pclk_alive", "gpll", 0,
+ RK3399_CLKSEL_CON(57), 0, 5, DFLAGS),
+
+ GATE(PCLK_USBPHY_MUX_G, "pclk_usbphy_mux_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 4, GFLAGS),
+ GATE(PCLK_UPHY0_TCPHY_G, "pclk_uphy0_tcphy_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 5, GFLAGS),
+ GATE(PCLK_UPHY0_TCPD_G, "pclk_uphy0_tcpd_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 6, GFLAGS),
+ GATE(PCLK_UPHY1_TCPHY_G, "pclk_uphy1_tcphy_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 8, GFLAGS),
+ GATE(PCLK_UPHY1_TCPD_G, "pclk_uphy1_tcpd_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 9, GFLAGS),
+
+ GATE(PCLK_GRF, "pclk_grf", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 1, GFLAGS),
+ GATE(PCLK_INTR_ARB, "pclk_intr_arb", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 2, GFLAGS),
+ GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 3, GFLAGS),
+ GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 4, GFLAGS),
+ GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 5, GFLAGS),
+ GATE(PCLK_TIMER0, "pclk_timer0", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 6, GFLAGS),
+ GATE(PCLK_TIMER1, "pclk_timer1", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 7, GFLAGS),
+ GATE(PCLK_PMU_INTR_ARB, "pclk_pmu_intr_arb", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 9, GFLAGS),
+ GATE(PCLK_SGRF, "pclk_sgrf", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 10, GFLAGS),
+
+ /* Watchdog pclk is controlled by RK3399 SECURE_GRF_SOC_CON3[8]. */
+ SGRF_GATE(PCLK_WDT, "pclk_wdt", "pclk_alive"),
+
+ GATE(SCLK_MIPIDPHY_REF, "clk_mipidphy_ref", "xin24m", 0, RK3399_CLKGATE_CON(11), 14, GFLAGS),
+ GATE(SCLK_DPHY_PLL, "clk_dphy_pll", "clk_mipidphy_ref", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 0, GFLAGS),
+
+ GATE(SCLK_MIPIDPHY_CFG, "clk_mipidphy_cfg", "xin24m", 0, RK3399_CLKGATE_CON(11), 15, GFLAGS),
+ GATE(SCLK_DPHY_TX0_CFG, "clk_dphy_tx0_cfg", "clk_mipidphy_cfg", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 1, GFLAGS),
+ GATE(SCLK_DPHY_TX1RX1_CFG, "clk_dphy_tx1rx1_cfg", "clk_mipidphy_cfg", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 2, GFLAGS),
+ GATE(SCLK_DPHY_RX0_CFG, "clk_dphy_rx0_cfg", "clk_mipidphy_cfg", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 3, GFLAGS),
+
+ /* testout */
+ MUX(0, "clk_test_pre", mux_pll_src_cpll_gpll_p, CLK_SET_RATE_PARENT,
+ RK3399_CLKSEL_CON(58), 7, 1, MFLAGS),
+ COMPOSITE_FRAC(0, "clk_test_frac", "clk_test_pre", 0,
+ RK3399_CLKSEL_CON(105), 0,
+ RK3399_CLKGATE_CON(13), 9, GFLAGS),
+
+ DIV(0, "clk_test_24m", "xin24m", 0,
+ RK3399_CLKSEL_CON(57), 6, 10, DFLAGS),
+
+ /* spi */
+ COMPOSITE(SCLK_SPI0, "clk_spi0", mux_pll_src_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(59), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3399_CLKGATE_CON(9), 12, GFLAGS),
+
+ COMPOSITE(SCLK_SPI1, "clk_spi1", mux_pll_src_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(59), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ RK3399_CLKGATE_CON(9), 13, GFLAGS),
+
+ COMPOSITE(SCLK_SPI2, "clk_spi2", mux_pll_src_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(60), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3399_CLKGATE_CON(9), 14, GFLAGS),
+
+ COMPOSITE(SCLK_SPI4, "clk_spi4", mux_pll_src_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(60), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ RK3399_CLKGATE_CON(9), 15, GFLAGS),
+
+ COMPOSITE(SCLK_SPI5, "clk_spi5", mux_pll_src_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(58), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ RK3399_CLKGATE_CON(13), 13, GFLAGS),
+
+ /* i2c */
+ COMPOSITE(SCLK_I2C1, "clk_i2c1", mux_pll_src_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(61), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3399_CLKGATE_CON(10), 0, GFLAGS),
+
+ COMPOSITE(SCLK_I2C2, "clk_i2c2", mux_pll_src_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(62), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3399_CLKGATE_CON(10), 2, GFLAGS),
+
+ COMPOSITE(SCLK_I2C3, "clk_i2c3", mux_pll_src_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(63), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3399_CLKGATE_CON(10), 4, GFLAGS),
+
+ COMPOSITE(SCLK_I2C5, "clk_i2c5", mux_pll_src_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(61), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ RK3399_CLKGATE_CON(10), 1, GFLAGS),
+
+ COMPOSITE(SCLK_I2C6, "clk_i2c6", mux_pll_src_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(62), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ RK3399_CLKGATE_CON(10), 3, GFLAGS),
+
+ COMPOSITE(SCLK_I2C7, "clk_i2c7", mux_pll_src_cpll_gpll_p, 0,
+ RK3399_CLKSEL_CON(63), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ RK3399_CLKGATE_CON(10), 5, GFLAGS),
+
+ /* timer */
+ GATE(SCLK_TIMER00, "clk_timer00", "xin24m", 0, RK3399_CLKGATE_CON(26), 0, GFLAGS),
+ GATE(SCLK_TIMER01, "clk_timer01", "xin24m", 0, RK3399_CLKGATE_CON(26), 1, GFLAGS),
+ GATE(SCLK_TIMER02, "clk_timer02", "xin24m", 0, RK3399_CLKGATE_CON(26), 2, GFLAGS),
+ GATE(SCLK_TIMER03, "clk_timer03", "xin24m", 0, RK3399_CLKGATE_CON(26), 3, GFLAGS),
+ GATE(SCLK_TIMER04, "clk_timer04", "xin24m", 0, RK3399_CLKGATE_CON(26), 4, GFLAGS),
+ GATE(SCLK_TIMER05, "clk_timer05", "xin24m", 0, RK3399_CLKGATE_CON(26), 5, GFLAGS),
+ GATE(SCLK_TIMER06, "clk_timer06", "xin24m", 0, RK3399_CLKGATE_CON(26), 6, GFLAGS),
+ GATE(SCLK_TIMER07, "clk_timer07", "xin24m", 0, RK3399_CLKGATE_CON(26), 7, GFLAGS),
+ GATE(SCLK_TIMER08, "clk_timer08", "xin24m", 0, RK3399_CLKGATE_CON(26), 8, GFLAGS),
+ GATE(SCLK_TIMER09, "clk_timer09", "xin24m", 0, RK3399_CLKGATE_CON(26), 9, GFLAGS),
+ GATE(SCLK_TIMER10, "clk_timer10", "xin24m", 0, RK3399_CLKGATE_CON(26), 10, GFLAGS),
+ GATE(SCLK_TIMER11, "clk_timer11", "xin24m", 0, RK3399_CLKGATE_CON(26), 11, GFLAGS),
+
+ /* clk_test */
+ /* clk_test_pre is controlled by CRU_MISC_CON[3] */
+ COMPOSITE_NOMUX(0, "clk_test", "clk_test_pre", CLK_IGNORE_UNUSED,
+ RK3399_CLKSEL_CON(58), 0, 5, DFLAGS,
+ RK3399_CLKGATE_CON(13), 11, GFLAGS),
+
+ /* ddrc */
+ GATE(0, "clk_ddrc_lpll_src", "lpll", 0, RK3399_CLKGATE_CON(3),
+ 0, GFLAGS),
+ GATE(0, "clk_ddrc_bpll_src", "bpll", 0, RK3399_CLKGATE_CON(3),
+ 1, GFLAGS),
+ GATE(0, "clk_ddrc_dpll_src", "dpll", 0, RK3399_CLKGATE_CON(3),
+ 2, GFLAGS),
+ GATE(0, "clk_ddrc_gpll_src", "gpll", 0, RK3399_CLKGATE_CON(3),
+ 3, GFLAGS),
+ COMPOSITE_DDRCLK(SCLK_DDRC, "sclk_ddrc", mux_ddrclk_p, 0,
+ RK3399_CLKSEL_CON(6), 4, 2, 0, 0, ROCKCHIP_DDRCLK_SIP),
+};
+
+static struct rockchip_clk_branch rk3399_clk_pmu_branches[] __initdata = {
+ /*
+ * PMU CRU Clock-Architecture
+ */
+
+ GATE(0, "fclk_cm0s_pmu_ppll_src", "ppll", 0,
+ RK3399_PMU_CLKGATE_CON(0), 1, GFLAGS),
+
+ COMPOSITE_NOGATE(FCLK_CM0S_SRC_PMU, "fclk_cm0s_src_pmu", mux_fclk_cm0s_pmu_ppll_p, 0,
+ RK3399_PMU_CLKSEL_CON(0), 15, 1, MFLAGS, 8, 5, DFLAGS),
+
+ COMPOSITE(SCLK_SPI3_PMU, "clk_spi3_pmu", mux_24m_ppll_p, 0,
+ RK3399_PMU_CLKSEL_CON(1), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3399_PMU_CLKGATE_CON(0), 2, GFLAGS),
+
+ COMPOSITE(0, "clk_wifi_div", mux_ppll_24m_p, CLK_IGNORE_UNUSED,
+ RK3399_PMU_CLKSEL_CON(1), 13, 1, MFLAGS, 8, 5, DFLAGS,
+ RK3399_PMU_CLKGATE_CON(0), 8, GFLAGS),
+
+ COMPOSITE_FRACMUX_NOGATE(0, "clk_wifi_frac", "clk_wifi_div", 0,
+ RK3399_PMU_CLKSEL_CON(7), 0,
+ &rk3399_pmuclk_wifi_fracmux),
+
+ MUX(0, "clk_timer_src_pmu", mux_pll_p, CLK_IGNORE_UNUSED,
+ RK3399_PMU_CLKSEL_CON(1), 15, 1, MFLAGS),
+
+ COMPOSITE_NOMUX(SCLK_I2C0_PMU, "clk_i2c0_pmu", "ppll", 0,
+ RK3399_PMU_CLKSEL_CON(2), 0, 7, DFLAGS,
+ RK3399_PMU_CLKGATE_CON(0), 9, GFLAGS),
+
+ COMPOSITE_NOMUX(SCLK_I2C4_PMU, "clk_i2c4_pmu", "ppll", 0,
+ RK3399_PMU_CLKSEL_CON(3), 0, 7, DFLAGS,
+ RK3399_PMU_CLKGATE_CON(0), 10, GFLAGS),
+
+ COMPOSITE_NOMUX(SCLK_I2C8_PMU, "clk_i2c8_pmu", "ppll", 0,
+ RK3399_PMU_CLKSEL_CON(2), 8, 7, DFLAGS,
+ RK3399_PMU_CLKGATE_CON(0), 11, GFLAGS),
+
+ DIV(0, "clk_32k_suspend_pmu", "xin24m", CLK_IGNORE_UNUSED,
+ RK3399_PMU_CLKSEL_CON(4), 0, 10, DFLAGS),
+ MUX(0, "clk_testout_2io", mux_clk_testout2_2io_p, CLK_IGNORE_UNUSED,
+ RK3399_PMU_CLKSEL_CON(4), 15, 1, MFLAGS),
+
+ COMPOSITE(0, "clk_uart4_div", mux_24m_ppll_p, 0,
+ RK3399_PMU_CLKSEL_CON(5), 10, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3399_PMU_CLKGATE_CON(0), 5, GFLAGS),
+
+ COMPOSITE_FRACMUX(0, "clk_uart4_frac", "clk_uart4_div", 0,
+ RK3399_PMU_CLKSEL_CON(6), 0,
+ RK3399_PMU_CLKGATE_CON(0), 6, GFLAGS,
+ &rk3399_uart4_pmu_fracmux),
+
+ DIV(PCLK_SRC_PMU, "pclk_pmu_src", "ppll", CLK_IGNORE_UNUSED,
+ RK3399_PMU_CLKSEL_CON(0), 0, 5, DFLAGS),
+
+ /* pmu clock gates */
+ GATE(SCLK_TIMER12_PMU, "clk_timer0_pmu", "clk_timer_src_pmu", 0, RK3399_PMU_CLKGATE_CON(0), 3, GFLAGS),
+ GATE(SCLK_TIMER13_PMU, "clk_timer1_pmu", "clk_timer_src_pmu", 0, RK3399_PMU_CLKGATE_CON(0), 4, GFLAGS),
+
+ GATE(SCLK_PVTM_PMU, "clk_pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(0), 7, GFLAGS),
+
+ GATE(PCLK_PMU, "pclk_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 0, GFLAGS),
+ GATE(PCLK_PMUGRF_PMU, "pclk_pmugrf_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 1, GFLAGS),
+ GATE(PCLK_INTMEM1_PMU, "pclk_intmem1_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 2, GFLAGS),
+ GATE(PCLK_GPIO0_PMU, "pclk_gpio0_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 3, GFLAGS),
+ GATE(PCLK_GPIO1_PMU, "pclk_gpio1_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 4, GFLAGS),
+ GATE(PCLK_SGRF_PMU, "pclk_sgrf_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 5, GFLAGS),
+ GATE(PCLK_NOC_PMU, "pclk_noc_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 6, GFLAGS),
+ GATE(PCLK_I2C0_PMU, "pclk_i2c0_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 7, GFLAGS),
+ GATE(PCLK_I2C4_PMU, "pclk_i2c4_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 8, GFLAGS),
+ GATE(PCLK_I2C8_PMU, "pclk_i2c8_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 9, GFLAGS),
+ GATE(PCLK_RKPWM_PMU, "pclk_rkpwm_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 10, GFLAGS),
+ GATE(PCLK_SPI3_PMU, "pclk_spi3_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 11, GFLAGS),
+ GATE(PCLK_TIMER_PMU, "pclk_timer_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 12, GFLAGS),
+ GATE(PCLK_MAILBOX_PMU, "pclk_mailbox_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 13, GFLAGS),
+ GATE(PCLK_UART4_PMU, "pclk_uart4_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 14, GFLAGS),
+ GATE(PCLK_WDT_M0_PMU, "pclk_wdt_m0_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 15, GFLAGS),
+
+ GATE(FCLK_CM0S_PMU, "fclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 0, GFLAGS),
+ GATE(SCLK_CM0S_PMU, "sclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 1, GFLAGS),
+ GATE(HCLK_CM0S_PMU, "hclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 2, GFLAGS),
+ GATE(DCLK_CM0S_PMU, "dclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 3, GFLAGS),
+ GATE(HCLK_NOC_PMU, "hclk_noc_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 5, GFLAGS),
+};
+
+static const char *const rk3399_cru_critical_clocks[] __initconst = {
+ "aclk_cci_pre",
+ "aclk_gic",
+ "aclk_gic_noc",
+ "aclk_hdcp_noc",
+ "hclk_hdcp_noc",
+ "pclk_hdcp_noc",
+ "pclk_perilp0",
+ "pclk_perilp0",
+ "hclk_perilp0",
+ "hclk_perilp0_noc",
+ "pclk_perilp1",
+ "pclk_perilp1_noc",
+ "pclk_perihp",
+ "pclk_perihp_noc",
+ "hclk_perihp",
+ "aclk_perihp",
+ "aclk_perihp_noc",
+ "aclk_perilp0",
+ "aclk_perilp0_noc",
+ "hclk_perilp1",
+ "hclk_perilp1_noc",
+ "aclk_dmac0_perilp",
+ "aclk_emmc_noc",
+ "gpll_hclk_perilp1_src",
+ "gpll_aclk_perilp0_src",
+ "gpll_aclk_perihp_src",
+ "aclk_vio_noc",
+
+ /* ddrc */
+ "sclk_ddrc",
+
+ "armclkl",
+ "armclkb",
+};
+
+static const char *const rk3399_pmucru_critical_clocks[] __initconst = {
+ "ppll",
+ "pclk_pmu_src",
+ "fclk_cm0s_src_pmu",
+ "clk_timer_src_pmu",
+ "pclk_rkpwm_pmu",
+};
+
+static void __init rk3399_clk_init(struct device_node *np)
+{
+ struct rockchip_clk_provider *ctx;
+ void __iomem *reg_base;
+
+ reg_base = of_iomap(np, 0);
+ if (!reg_base) {
+ pr_err("%s: could not map cru region\n", __func__);
+ return;
+ }
+
+ ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+ if (IS_ERR(ctx)) {
+ pr_err("%s: rockchip clk init failed\n", __func__);
+ return;
+ }
+
+ rockchip_clk_register_plls(ctx, rk3399_pll_clks,
+ ARRAY_SIZE(rk3399_pll_clks), -1);
+
+ rockchip_clk_register_branches(ctx, rk3399_clk_branches,
+ ARRAY_SIZE(rk3399_clk_branches));
+
+ rockchip_clk_register_armclk(ctx, ARMCLKL, "armclkl",
+ mux_armclkl_p, ARRAY_SIZE(mux_armclkl_p),
+ &rk3399_cpuclkl_data, rk3399_cpuclkl_rates,
+ ARRAY_SIZE(rk3399_cpuclkl_rates));
+
+ rockchip_clk_register_armclk(ctx, ARMCLKB, "armclkb",
+ mux_armclkb_p, ARRAY_SIZE(mux_armclkb_p),
+ &rk3399_cpuclkb_data, rk3399_cpuclkb_rates,
+ ARRAY_SIZE(rk3399_cpuclkb_rates));
+
+ rockchip_clk_protect_critical(rk3399_cru_critical_clocks,
+ ARRAY_SIZE(rk3399_cru_critical_clocks));
+
+ rockchip_register_softrst(np, 21, reg_base + RK3399_SOFTRST_CON(0),
+ ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+ rockchip_register_restart_notifier(ctx, RK3399_GLB_SRST_FST);
+
+ rockchip_clk_of_add_provider(np, ctx);
+}
+
+static void __init rk3399_pmu_clk_init(struct device_node *np)
+{
+ struct rockchip_clk_provider *ctx;
+ void __iomem *reg_base;
+
+ reg_base = of_iomap(np, 0);
+ if (!reg_base) {
+ pr_err("%s: could not map cru pmu region\n", __func__);
+ return;
+ }
+
+ ctx = rockchip_clk_init(np, reg_base, CLKPMU_NR_CLKS);
+ if (IS_ERR(ctx)) {
+ pr_err("%s: rockchip pmu clk init failed\n", __func__);
+ return;
+ }
+
+ rockchip_clk_register_plls(ctx, rk3399_pmu_pll_clks,
+ ARRAY_SIZE(rk3399_pmu_pll_clks), -1);
+
+ rockchip_clk_register_branches(ctx, rk3399_clk_pmu_branches,
+ ARRAY_SIZE(rk3399_clk_pmu_branches));
+
+ rockchip_clk_protect_critical(rk3399_pmucru_critical_clocks,
+ ARRAY_SIZE(rk3399_pmucru_critical_clocks));
+
+ rockchip_register_softrst(np, 2, reg_base + RK3399_PMU_SOFTRST_CON(0),
+ ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+ rockchip_clk_of_add_provider(np, ctx);
+}
+
+struct clk_rk3399_inits {
+ void (*inits)(struct device_node *np);
+};
+
+static const struct clk_rk3399_inits clk_rk3399_pmucru_init = {
+ .inits = rk3399_pmu_clk_init,
+};
+
+static const struct clk_rk3399_inits clk_rk3399_cru_init = {
+ .inits = rk3399_clk_init,
+};
+
+static const struct of_device_id clk_rk3399_match_table[] = {
+ {
+ .compatible = "rockchip,rk3399-cru",
+ .data = &clk_rk3399_cru_init,
+ }, {
+ .compatible = "rockchip,rk3399-pmucru",
+ .data = &clk_rk3399_pmucru_init,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, clk_rk3399_match_table);
+
+static int __init clk_rk3399_probe(struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ const struct of_device_id *match;
+ const struct clk_rk3399_inits *init_data;
+
+ match = of_match_device(clk_rk3399_match_table, dev);
+ if (!match || !match->data)
+ return -EINVAL;
+
+ init_data = match->data;
+ if (init_data->inits)
+ init_data->inits(np);
+
+ return 0;
+}
+
+static struct driver clk_rk3399_driver = {
+ .probe = clk_rk3399_probe,
+ .name = "clk-rk3399",
+ .of_compatible = DRV_OF_COMPAT(clk_rk3399_match_table),
+};
+
+core_platform_driver(clk_rk3399_driver);
diff --git a/drivers/clk/rockchip/clk-rk3568.c b/drivers/clk/rockchip/clk-rk3568.c
new file mode 100644
index 0000000000..d07d7aef5d
--- /dev/null
+++ b/drivers/clk/rockchip/clk-rk3568.c
@@ -0,0 +1,1741 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021 Rockchip Electronics Co. Ltd.
+ * Author: Elaine Zhang <zhangqing@rock-chips.com>
+ */
+
+#include <common.h>
+#include <linux/clk.h>
+#include <of.h>
+#include <of_address.h>
+#include <linux/barebox-wrapper.h>
+#include <init.h>
+#include <linux/spinlock.h>
+#include <of_device.h>
+#include <dt-bindings/clock/rk3568-cru.h>
+#include "clk.h"
+
+#define RK3568_GRF_SOC_STATUS0 0x580
+
+enum rk3568_pmu_plls {
+ ppll, hpll,
+};
+
+enum rk3568_plls {
+ apll, dpll, gpll, cpll, npll, vpll,
+};
+
+static struct rockchip_pll_rate_table rk3568_pll_rates[] = {
+ /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+ RK3036_PLL_RATE(2208000000, 1, 92, 1, 1, 1, 0),
+ RK3036_PLL_RATE(2184000000, 1, 91, 1, 1, 1, 0),
+ RK3036_PLL_RATE(2160000000, 1, 90, 1, 1, 1, 0),
+ RK3036_PLL_RATE(2088000000, 1, 87, 1, 1, 1, 0),
+ RK3036_PLL_RATE(2064000000, 1, 86, 1, 1, 1, 0),
+ RK3036_PLL_RATE(2040000000, 1, 85, 1, 1, 1, 0),
+ RK3036_PLL_RATE(2016000000, 1, 84, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1992000000, 1, 83, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1920000000, 1, 80, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1896000000, 1, 79, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1800000000, 1, 75, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1704000000, 1, 71, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1600000000, 3, 200, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1584000000, 1, 132, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1560000000, 1, 130, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1536000000, 1, 128, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1512000000, 1, 126, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1488000000, 1, 124, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1464000000, 1, 122, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1440000000, 1, 120, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1416000000, 1, 118, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1400000000, 3, 350, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1392000000, 1, 116, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1368000000, 1, 114, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1344000000, 1, 112, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1320000000, 1, 110, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1296000000, 1, 108, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1272000000, 1, 106, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1248000000, 1, 104, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1200000000, 1, 100, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1104000000, 1, 92, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1100000000, 3, 275, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1000000000, 3, 250, 2, 1, 1, 0),
+ RK3036_PLL_RATE(912000000, 1, 76, 2, 1, 1, 0),
+ RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
+ RK3036_PLL_RATE(800000000, 3, 200, 2, 1, 1, 0),
+ RK3036_PLL_RATE(700000000, 3, 350, 4, 1, 1, 0),
+ RK3036_PLL_RATE(696000000, 1, 116, 4, 1, 1, 0),
+ RK3036_PLL_RATE(600000000, 1, 100, 4, 1, 1, 0),
+ RK3036_PLL_RATE(594000000, 1, 99, 4, 1, 1, 0),
+ RK3036_PLL_RATE(500000000, 1, 125, 6, 1, 1, 0),
+ RK3036_PLL_RATE(408000000, 1, 68, 2, 2, 1, 0),
+ RK3036_PLL_RATE(312000000, 1, 78, 6, 1, 1, 0),
+ RK3036_PLL_RATE(216000000, 1, 72, 4, 2, 1, 0),
+ RK3036_PLL_RATE(200000000, 1, 100, 3, 4, 1, 0),
+ RK3036_PLL_RATE(148500000, 1, 99, 4, 4, 1, 0),
+ RK3036_PLL_RATE(100000000, 1, 150, 6, 6, 1, 0),
+ RK3036_PLL_RATE(96000000, 1, 96, 6, 4, 1, 0),
+ RK3036_PLL_RATE(74250000, 2, 99, 4, 4, 1, 0),
+ { /* sentinel */ },
+};
+
+#define RK3568_DIV_ATCLK_CORE_MASK 0x1f
+#define RK3568_DIV_ATCLK_CORE_SHIFT 0
+#define RK3568_DIV_GICCLK_CORE_MASK 0x1f
+#define RK3568_DIV_GICCLK_CORE_SHIFT 8
+#define RK3568_DIV_PCLK_CORE_MASK 0x1f
+#define RK3568_DIV_PCLK_CORE_SHIFT 0
+#define RK3568_DIV_PERIPHCLK_CORE_MASK 0x1f
+#define RK3568_DIV_PERIPHCLK_CORE_SHIFT 8
+#define RK3568_DIV_ACLK_CORE_MASK 0x1f
+#define RK3568_DIV_ACLK_CORE_SHIFT 8
+
+#define RK3568_DIV_SCLK_CORE_MASK 0xf
+#define RK3568_DIV_SCLK_CORE_SHIFT 0
+#define RK3568_MUX_SCLK_CORE_MASK 0x3
+#define RK3568_MUX_SCLK_CORE_SHIFT 8
+#define RK3568_MUX_SCLK_CORE_NPLL_MASK 0x1
+#define RK3568_MUX_SCLK_CORE_NPLL_SHIFT 15
+#define RK3568_MUX_CLK_CORE_APLL_MASK 0x1
+#define RK3568_MUX_CLK_CORE_APLL_SHIFT 7
+#define RK3568_MUX_CLK_PVTPLL_MASK 0x1
+#define RK3568_MUX_CLK_PVTPLL_SHIFT 15
+
+#define RK3568_CLKSEL1(_sclk_core) \
+{ \
+ .reg = RK3568_CLKSEL_CON(2), \
+ .val = HIWORD_UPDATE(_sclk_core, RK3568_MUX_SCLK_CORE_NPLL_MASK, \
+ RK3568_MUX_SCLK_CORE_NPLL_SHIFT) | \
+ HIWORD_UPDATE(_sclk_core, RK3568_MUX_SCLK_CORE_MASK, \
+ RK3568_MUX_SCLK_CORE_SHIFT) | \
+ HIWORD_UPDATE(1, RK3568_DIV_SCLK_CORE_MASK, \
+ RK3568_DIV_SCLK_CORE_SHIFT), \
+}
+
+#define RK3568_CLKSEL2(_aclk_core) \
+{ \
+ .reg = RK3568_CLKSEL_CON(5), \
+ .val = HIWORD_UPDATE(_aclk_core, RK3568_DIV_ACLK_CORE_MASK, \
+ RK3568_DIV_ACLK_CORE_SHIFT), \
+}
+
+#define RK3568_CLKSEL3(_atclk_core, _gic_core) \
+{ \
+ .reg = RK3568_CLKSEL_CON(3), \
+ .val = HIWORD_UPDATE(_atclk_core, RK3568_DIV_ATCLK_CORE_MASK, \
+ RK3568_DIV_ATCLK_CORE_SHIFT) | \
+ HIWORD_UPDATE(_gic_core, RK3568_DIV_GICCLK_CORE_MASK, \
+ RK3568_DIV_GICCLK_CORE_SHIFT), \
+}
+
+#define RK3568_CLKSEL4(_pclk_core, _periph_core) \
+{ \
+ .reg = RK3568_CLKSEL_CON(4), \
+ .val = HIWORD_UPDATE(_pclk_core, RK3568_DIV_PCLK_CORE_MASK, \
+ RK3568_DIV_PCLK_CORE_SHIFT) | \
+ HIWORD_UPDATE(_periph_core, RK3568_DIV_PERIPHCLK_CORE_MASK, \
+ RK3568_DIV_PERIPHCLK_CORE_SHIFT), \
+}
+
+#define RK3568_CPUCLK_RATE(_prate, _sclk, _acore, _atcore, _gicclk, _pclk, _periph) \
+{ \
+ .prate = _prate##U, \
+ .divs = { \
+ RK3568_CLKSEL1(_sclk), \
+ RK3568_CLKSEL2(_acore), \
+ RK3568_CLKSEL3(_atcore, _gicclk), \
+ RK3568_CLKSEL4(_pclk, _periph), \
+ }, \
+}
+
+static struct rockchip_cpuclk_rate_table rk3568_cpuclk_rates[] __initdata = {
+ RK3568_CPUCLK_RATE(1800000000, 0, 1, 7, 7, 7, 7),
+ RK3568_CPUCLK_RATE(1704000000, 0, 1, 7, 7, 7, 7),
+ RK3568_CPUCLK_RATE(1608000000, 0, 1, 5, 5, 5, 5),
+ RK3568_CPUCLK_RATE(1584000000, 0, 1, 5, 5, 5, 5),
+ RK3568_CPUCLK_RATE(1560000000, 0, 1, 5, 5, 5, 5),
+ RK3568_CPUCLK_RATE(1536000000, 0, 1, 5, 5, 5, 5),
+ RK3568_CPUCLK_RATE(1512000000, 0, 1, 5, 5, 5, 5),
+ RK3568_CPUCLK_RATE(1488000000, 0, 1, 5, 5, 5, 5),
+ RK3568_CPUCLK_RATE(1464000000, 0, 1, 5, 5, 5, 5),
+ RK3568_CPUCLK_RATE(1440000000, 0, 1, 5, 5, 5, 5),
+ RK3568_CPUCLK_RATE(1416000000, 0, 1, 5, 5, 5, 5),
+ RK3568_CPUCLK_RATE(1392000000, 0, 1, 5, 5, 5, 5),
+ RK3568_CPUCLK_RATE(1368000000, 0, 1, 5, 5, 5, 5),
+ RK3568_CPUCLK_RATE(1344000000, 0, 1, 5, 5, 5, 5),
+ RK3568_CPUCLK_RATE(1320000000, 0, 1, 5, 5, 5, 5),
+ RK3568_CPUCLK_RATE(1296000000, 0, 1, 5, 5, 5, 5),
+ RK3568_CPUCLK_RATE(1272000000, 0, 1, 5, 5, 5, 5),
+ RK3568_CPUCLK_RATE(1248000000, 0, 1, 5, 5, 5, 5),
+ RK3568_CPUCLK_RATE(1224000000, 0, 1, 5, 5, 5, 5),
+ RK3568_CPUCLK_RATE(1200000000, 0, 1, 3, 3, 3, 3),
+ RK3568_CPUCLK_RATE(1104000000, 0, 1, 3, 3, 3, 3),
+ RK3568_CPUCLK_RATE(1008000000, 0, 1, 3, 3, 3, 3),
+ RK3568_CPUCLK_RATE(912000000, 0, 1, 3, 3, 3, 3),
+ RK3568_CPUCLK_RATE(816000000, 0, 1, 3, 3, 3, 3),
+ RK3568_CPUCLK_RATE(696000000, 0, 1, 3, 3, 3, 3),
+ RK3568_CPUCLK_RATE(600000000, 0, 1, 3, 3, 3, 3),
+ RK3568_CPUCLK_RATE(408000000, 0, 1, 3, 3, 3, 3),
+ RK3568_CPUCLK_RATE(312000000, 0, 1, 3, 3, 3, 3),
+ RK3568_CPUCLK_RATE(216000000, 0, 1, 3, 3, 3, 3),
+ RK3568_CPUCLK_RATE(96000000, 0, 1, 3, 3, 3, 3),
+};
+
+static const struct rockchip_cpuclk_reg_data rk3568_cpuclk_data = {
+ .core_reg[0] = RK3568_CLKSEL_CON(0),
+ .div_core_shift[0] = 0,
+ .div_core_mask[0] = 0x1f,
+ .core_reg[1] = RK3568_CLKSEL_CON(0),
+ .div_core_shift[1] = 8,
+ .div_core_mask[1] = 0x1f,
+ .core_reg[2] = RK3568_CLKSEL_CON(1),
+ .div_core_shift[2] = 0,
+ .div_core_mask[2] = 0x1f,
+ .core_reg[3] = RK3568_CLKSEL_CON(1),
+ .div_core_shift[3] = 8,
+ .div_core_mask[3] = 0x1f,
+ .num_cores = 4,
+ .mux_core_alt = 1,
+ .mux_core_main = 0,
+ .mux_core_shift = 6,
+ .mux_core_mask = 0x1,
+};
+
+PNAME(mux_pll_p) = { "xin24m" };
+PNAME(mux_usb480m_p) = { "xin24m", "usb480m_phy", "clk_rtc_32k" };
+PNAME(mux_armclk_p) = { "apll", "gpll" };
+PNAME(clk_i2s0_8ch_tx_p) = { "clk_i2s0_8ch_tx_src", "clk_i2s0_8ch_tx_frac", "i2s0_mclkin", "xin_osc0_half" };
+PNAME(clk_i2s0_8ch_rx_p) = { "clk_i2s0_8ch_rx_src", "clk_i2s0_8ch_rx_frac", "i2s0_mclkin", "xin_osc0_half" };
+PNAME(clk_i2s1_8ch_tx_p) = { "clk_i2s1_8ch_tx_src", "clk_i2s1_8ch_tx_frac", "i2s1_mclkin", "xin_osc0_half" };
+PNAME(clk_i2s1_8ch_rx_p) = { "clk_i2s1_8ch_rx_src", "clk_i2s1_8ch_rx_frac", "i2s1_mclkin", "xin_osc0_half" };
+PNAME(clk_i2s2_2ch_p) = { "clk_i2s2_2ch_src", "clk_i2s2_2ch_frac", "i2s2_mclkin", "xin_osc0_half "};
+PNAME(clk_i2s3_2ch_tx_p) = { "clk_i2s3_2ch_tx_src", "clk_i2s3_2ch_tx_frac", "i2s3_mclkin", "xin_osc0_half" };
+PNAME(clk_i2s3_2ch_rx_p) = { "clk_i2s3_2ch_rx_src", "clk_i2s3_2ch_rx_frac", "i2s3_mclkin", "xin_osc0_half" };
+PNAME(mclk_spdif_8ch_p) = { "mclk_spdif_8ch_src", "mclk_spdif_8ch_frac" };
+PNAME(sclk_audpwm_p) = { "sclk_audpwm_src", "sclk_audpwm_frac" };
+PNAME(sclk_uart1_p) = { "clk_uart1_src", "clk_uart1_frac", "xin24m" };
+PNAME(sclk_uart2_p) = { "clk_uart2_src", "clk_uart2_frac", "xin24m" };
+PNAME(sclk_uart3_p) = { "clk_uart3_src", "clk_uart3_frac", "xin24m" };
+PNAME(sclk_uart4_p) = { "clk_uart4_src", "clk_uart4_frac", "xin24m" };
+PNAME(sclk_uart5_p) = { "clk_uart5_src", "clk_uart5_frac", "xin24m" };
+PNAME(sclk_uart6_p) = { "clk_uart6_src", "clk_uart6_frac", "xin24m" };
+PNAME(sclk_uart7_p) = { "clk_uart7_src", "clk_uart7_frac", "xin24m" };
+PNAME(sclk_uart8_p) = { "clk_uart8_src", "clk_uart8_frac", "xin24m" };
+PNAME(sclk_uart9_p) = { "clk_uart9_src", "clk_uart9_frac", "xin24m" };
+PNAME(sclk_uart0_p) = { "sclk_uart0_div", "sclk_uart0_frac", "xin24m" };
+PNAME(clk_rtc32k_pmu_p) = { "clk_32k_pvtm", "xin32k", "clk_rtc32k_frac" };
+PNAME(mpll_gpll_cpll_npll_p) = { "mpll", "gpll", "cpll", "npll" };
+PNAME(gpll_cpll_npll_p) = { "gpll", "cpll", "npll" };
+PNAME(npll_gpll_p) = { "npll", "gpll" };
+PNAME(cpll_gpll_p) = { "cpll", "gpll" };
+PNAME(gpll_cpll_p) = { "gpll", "cpll" };
+PNAME(gpll_cpll_npll_vpll_p) = { "gpll", "cpll", "npll", "vpll" };
+PNAME(apll_gpll_npll_p) = { "apll", "gpll", "npll" };
+PNAME(sclk_core_pre_p) = { "sclk_core_src", "npll" };
+PNAME(gpll150_gpll100_gpll75_xin24m_p) = { "gpll_150m", "gpll_100m", "gpll_75m", "xin24m" };
+PNAME(clk_gpu_pre_mux_p) = { "clk_gpu_src", "gpu_pvtpll_out" };
+PNAME(clk_npu_pre_ndft_p) = { "clk_npu_src", "dummy"};
+PNAME(clk_npu_p) = { "clk_npu_pre_ndft", "npu_pvtpll_out" };
+PNAME(dpll_gpll_cpll_p) = { "dpll", "gpll", "cpll" };
+PNAME(clk_ddr1x_p) = { "clk_ddrphy1x_src", "dpll" };
+PNAME(gpll200_gpll150_gpll100_xin24m_p) = { "gpll_200m", "gpll_150m", "gpll_100m", "xin24m" };
+PNAME(gpll100_gpll75_gpll50_p) = { "gpll_100m", "gpll_75m", "cpll_50m" };
+PNAME(i2s0_mclkout_tx_p) = { "clk_i2s0_8ch_tx", "xin_osc0_half" };
+PNAME(i2s0_mclkout_rx_p) = { "clk_i2s0_8ch_rx", "xin_osc0_half" };
+PNAME(i2s1_mclkout_tx_p) = { "clk_i2s1_8ch_tx", "xin_osc0_half" };
+PNAME(i2s1_mclkout_rx_p) = { "clk_i2s1_8ch_rx", "xin_osc0_half" };
+PNAME(i2s2_mclkout_p) = { "clk_i2s2_2ch", "xin_osc0_half" };
+PNAME(i2s3_mclkout_tx_p) = { "clk_i2s3_2ch_tx", "xin_osc0_half" };
+PNAME(i2s3_mclkout_rx_p) = { "clk_i2s3_2ch_rx", "xin_osc0_half" };
+PNAME(mclk_pdm_p) = { "gpll_300m", "cpll_250m", "gpll_200m", "gpll_100m" };
+PNAME(clk_i2c_p) = { "gpll_200m", "gpll_100m", "xin24m", "cpll_100m" };
+PNAME(gpll200_gpll150_gpll100_p) = { "gpll_200m", "gpll_150m", "gpll_100m" };
+PNAME(gpll300_gpll200_gpll100_p) = { "gpll_300m", "gpll_200m", "gpll_100m" };
+PNAME(clk_nandc_p) = { "gpll_200m", "gpll_150m", "cpll_100m", "xin24m" };
+PNAME(sclk_sfc_p) = { "xin24m", "cpll_50m", "gpll_75m", "gpll_100m", "cpll_125m", "gpll_150m" };
+PNAME(gpll200_gpll150_cpll125_p) = { "gpll_200m", "gpll_150m", "cpll_125m" };
+PNAME(cclk_emmc_p) = { "xin24m", "gpll_200m", "gpll_150m", "cpll_100m", "cpll_50m", "clk_osc0_div_375k" };
+PNAME(aclk_pipe_p) = { "gpll_400m", "gpll_300m", "gpll_200m", "xin24m" };
+PNAME(gpll200_cpll125_p) = { "gpll_200m", "cpll_125m" };
+PNAME(gpll300_gpll200_gpll100_xin24m_p) = { "gpll_300m", "gpll_200m", "gpll_100m", "xin24m" };
+PNAME(clk_sdmmc_p) = { "xin24m", "gpll_400m", "gpll_300m", "cpll_100m", "cpll_50m", "clk_osc0_div_750k" };
+PNAME(cpll125_cpll50_cpll25_xin24m_p) = { "cpll_125m", "cpll_50m", "cpll_25m", "xin24m" };
+PNAME(clk_gmac_ptp_p) = { "cpll_62p5", "gpll_100m", "cpll_50m", "xin24m" };
+PNAME(cpll333_gpll300_gpll200_p) = { "cpll_333m", "gpll_300m", "gpll_200m" };
+PNAME(cpll_gpll_hpll_p) = { "cpll", "gpll", "hpll" };
+PNAME(gpll_usb480m_xin24m_p) = { "gpll", "usb480m", "xin24m", "xin24m" };
+PNAME(gpll300_cpll250_gpll100_xin24m_p) = { "gpll_300m", "cpll_250m", "gpll_100m", "xin24m" };
+PNAME(cpll_gpll_hpll_vpll_p) = { "cpll", "gpll", "hpll", "vpll" };
+PNAME(hpll_vpll_gpll_cpll_p) = { "hpll", "vpll", "gpll", "cpll" };
+PNAME(gpll400_cpll333_gpll200_p) = { "gpll_400m", "cpll_333m", "gpll_200m" };
+PNAME(gpll100_gpll75_cpll50_xin24m_p) = { "gpll_100m", "gpll_75m", "cpll_50m", "xin24m" };
+PNAME(xin24m_gpll100_cpll100_p) = { "xin24m", "gpll_100m", "cpll_100m" };
+PNAME(gpll_cpll_usb480m_p) = { "gpll", "cpll", "usb480m" };
+PNAME(gpll100_xin24m_cpll100_p) = { "gpll_100m", "xin24m", "cpll_100m" };
+PNAME(gpll200_xin24m_cpll100_p) = { "gpll_200m", "xin24m", "cpll_100m" };
+PNAME(xin24m_32k_p) = { "xin24m", "clk_rtc_32k" };
+PNAME(cpll500_gpll400_gpll300_xin24m_p) = { "cpll_500m", "gpll_400m", "gpll_300m", "xin24m" };
+PNAME(gpll400_gpll300_gpll200_xin24m_p) = { "gpll_400m", "gpll_300m", "gpll_200m", "xin24m" };
+PNAME(xin24m_cpll100_p) = { "xin24m", "cpll_100m" };
+PNAME(ppll_usb480m_cpll_gpll_p) = { "ppll", "usb480m", "cpll", "gpll"};
+PNAME(clk_usbphy0_ref_p) = { "clk_ref24m", "xin_osc0_usbphy0_g" };
+PNAME(clk_usbphy1_ref_p) = { "clk_ref24m", "xin_osc0_usbphy1_g" };
+PNAME(clk_mipidsiphy0_ref_p) = { "clk_ref24m", "xin_osc0_mipidsiphy0_g" };
+PNAME(clk_mipidsiphy1_ref_p) = { "clk_ref24m", "xin_osc0_mipidsiphy1_g" };
+PNAME(clk_wifi_p) = { "clk_wifi_osc0", "clk_wifi_div" };
+PNAME(clk_pciephy0_ref_p) = { "clk_pciephy0_osc0", "clk_pciephy0_div" };
+PNAME(clk_pciephy1_ref_p) = { "clk_pciephy1_osc0", "clk_pciephy1_div" };
+PNAME(clk_pciephy2_ref_p) = { "clk_pciephy2_osc0", "clk_pciephy2_div" };
+PNAME(mux_gmac0_p) = { "clk_mac0_2top", "gmac0_clkin" };
+PNAME(mux_gmac0_rgmii_speed_p) = { "clk_gmac0", "clk_gmac0", "clk_gmac0_tx_div50", "clk_gmac0_tx_div5" };
+PNAME(mux_gmac0_rmii_speed_p) = { "clk_gmac0_rx_div20", "clk_gmac0_rx_div2" };
+PNAME(mux_gmac0_rx_tx_p) = { "clk_gmac0_rgmii_speed", "clk_gmac0_rmii_speed", "clk_gmac0_xpcs_mii" };
+PNAME(mux_gmac1_p) = { "clk_mac1_2top", "gmac1_clkin" };
+PNAME(mux_gmac1_rgmii_speed_p) = { "clk_gmac1", "clk_gmac1", "clk_gmac1_tx_div50", "clk_gmac1_tx_div5" };
+PNAME(mux_gmac1_rmii_speed_p) = { "clk_gmac1_rx_div20", "clk_gmac1_rx_div2" };
+PNAME(mux_gmac1_rx_tx_p) = { "clk_gmac1_rgmii_speed", "clk_gmac1_rmii_speed", "clk_gmac1_xpcs_mii" };
+PNAME(clk_hdmi_ref_p) = { "hpll", "hpll_ph0" };
+PNAME(clk_pdpmu_p) = { "ppll", "gpll" };
+PNAME(clk_mac_2top_p) = { "cpll_125m", "cpll_50m", "cpll_25m", "ppll" };
+PNAME(clk_pwm0_p) = { "xin24m", "clk_pdpmu" };
+PNAME(aclk_rkvdec_pre_p) = { "gpll", "cpll" };
+PNAME(clk_rkvdec_core_p) = { "gpll", "cpll", "dummy_npll", "dummy_vpll" };
+
+static struct rockchip_pll_clock rk3568_pmu_pll_clks[] __initdata = {
+ [ppll] = PLL(pll_rk3328, PLL_PPLL, "ppll", mux_pll_p,
+ 0, RK3568_PMU_PLL_CON(0),
+ RK3568_PMU_MODE_CON0, 0, 4, 0, rk3568_pll_rates),
+ [hpll] = PLL(pll_rk3328, PLL_HPLL, "hpll", mux_pll_p,
+ 0, RK3568_PMU_PLL_CON(16),
+ RK3568_PMU_MODE_CON0, 2, 7, 0, rk3568_pll_rates),
+};
+
+static struct rockchip_pll_clock rk3568_pll_clks[] __initdata = {
+ [apll] = PLL(pll_rk3328, PLL_APLL, "apll", mux_pll_p,
+ 0, RK3568_PLL_CON(0),
+ RK3568_MODE_CON0, 0, 0, 0, rk3568_pll_rates),
+ [dpll] = PLL(pll_rk3328, PLL_DPLL, "dpll", mux_pll_p,
+ 0, RK3568_PLL_CON(8),
+ RK3568_MODE_CON0, 2, 1, 0, NULL),
+ [cpll] = PLL(pll_rk3328, PLL_CPLL, "cpll", mux_pll_p,
+ 0, RK3568_PLL_CON(24),
+ RK3568_MODE_CON0, 4, 2, 0, rk3568_pll_rates),
+ [gpll] = PLL(pll_rk3328, PLL_GPLL, "gpll", mux_pll_p,
+ 0, RK3568_PLL_CON(16),
+ RK3568_MODE_CON0, 6, 3, 0, rk3568_pll_rates),
+ [npll] = PLL(pll_rk3328, PLL_NPLL, "npll", mux_pll_p,
+ 0, RK3568_PLL_CON(32),
+ RK3568_MODE_CON0, 10, 5, 0, rk3568_pll_rates),
+ [vpll] = PLL(pll_rk3328, PLL_VPLL, "vpll", mux_pll_p,
+ 0, RK3568_PLL_CON(40),
+ RK3568_MODE_CON0, 12, 6, 0, rk3568_pll_rates),
+};
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+
+static struct rockchip_clk_branch rk3568_i2s0_8ch_tx_fracmux __initdata =
+ MUX(CLK_I2S0_8CH_TX, "clk_i2s0_8ch_tx", clk_i2s0_8ch_tx_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(11), 10, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_i2s0_8ch_rx_fracmux __initdata =
+ MUX(CLK_I2S0_8CH_RX, "clk_i2s0_8ch_rx", clk_i2s0_8ch_rx_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(13), 10, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_i2s1_8ch_tx_fracmux __initdata =
+ MUX(CLK_I2S1_8CH_TX, "clk_i2s1_8ch_tx", clk_i2s1_8ch_tx_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(15), 10, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_i2s1_8ch_rx_fracmux __initdata =
+ MUX(CLK_I2S1_8CH_RX, "clk_i2s1_8ch_rx", clk_i2s1_8ch_rx_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(17), 10, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_i2s2_2ch_fracmux __initdata =
+ MUX(CLK_I2S2_2CH, "clk_i2s2_2ch", clk_i2s2_2ch_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(19), 10, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_i2s3_2ch_tx_fracmux __initdata =
+ MUX(CLK_I2S3_2CH_TX, "clk_i2s3_2ch_tx", clk_i2s3_2ch_tx_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(21), 10, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_i2s3_2ch_rx_fracmux __initdata =
+ MUX(CLK_I2S3_2CH_RX, "clk_i2s3_2ch_rx", clk_i2s3_2ch_rx_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(83), 10, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_spdif_8ch_fracmux __initdata =
+ MUX(MCLK_SPDIF_8CH, "mclk_spdif_8ch", mclk_spdif_8ch_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(23), 15, 1, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_audpwm_fracmux __initdata =
+ MUX(SCLK_AUDPWM, "sclk_audpwm", sclk_audpwm_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(25), 15, 1, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_uart1_fracmux __initdata =
+ MUX(0, "sclk_uart1_mux", sclk_uart1_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(52), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_uart2_fracmux __initdata =
+ MUX(0, "sclk_uart2_mux", sclk_uart2_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(54), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_uart3_fracmux __initdata =
+ MUX(0, "sclk_uart3_mux", sclk_uart3_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(56), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_uart4_fracmux __initdata =
+ MUX(0, "sclk_uart4_mux", sclk_uart4_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(58), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_uart5_fracmux __initdata =
+ MUX(0, "sclk_uart5_mux", sclk_uart5_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(60), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_uart6_fracmux __initdata =
+ MUX(0, "sclk_uart6_mux", sclk_uart6_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(62), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_uart7_fracmux __initdata =
+ MUX(0, "sclk_uart7_mux", sclk_uart7_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(64), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_uart8_fracmux __initdata =
+ MUX(0, "sclk_uart8_mux", sclk_uart8_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(66), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_uart9_fracmux __initdata =
+ MUX(0, "sclk_uart9_mux", sclk_uart9_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(68), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_uart0_fracmux __initdata =
+ MUX(0, "sclk_uart0_mux", sclk_uart0_p, CLK_SET_RATE_PARENT,
+ RK3568_PMU_CLKSEL_CON(4), 10, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_rtc32k_pmu_fracmux __initdata =
+ MUX(CLK_RTC_32K, "clk_rtc_32k", clk_rtc32k_pmu_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+ RK3568_PMU_CLKSEL_CON(0), 6, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3568_clk_branches[] __initdata = {
+ /*
+ * Clock-Architecture Diagram 1
+ */
+ /* SRC_CLK */
+ COMPOSITE_NOMUX(0, "gpll_400m", "gpll", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(75), 0, 5, DFLAGS,
+ RK3568_CLKGATE_CON(35), 0, GFLAGS),
+ COMPOSITE_NOMUX(0, "gpll_300m", "gpll", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(75), 8, 5, DFLAGS,
+ RK3568_CLKGATE_CON(35), 1, GFLAGS),
+ COMPOSITE_NOMUX(0, "gpll_200m", "gpll", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(76), 0, 5, DFLAGS,
+ RK3568_CLKGATE_CON(35), 2, GFLAGS),
+ COMPOSITE_NOMUX(0, "gpll_150m", "gpll", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(76), 8, 5, DFLAGS,
+ RK3568_CLKGATE_CON(35), 3, GFLAGS),
+ COMPOSITE_NOMUX(0, "gpll_100m", "gpll", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(77), 0, 5, DFLAGS,
+ RK3568_CLKGATE_CON(35), 4, GFLAGS),
+ COMPOSITE_NOMUX(0, "gpll_75m", "gpll", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(77), 8, 5, DFLAGS,
+ RK3568_CLKGATE_CON(35), 5, GFLAGS),
+ COMPOSITE_NOMUX(0, "gpll_20m", "gpll", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(78), 0, 6, DFLAGS,
+ RK3568_CLKGATE_CON(35), 6, GFLAGS),
+ COMPOSITE_NOMUX(CPLL_500M, "cpll_500m", "cpll", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(78), 8, 5, DFLAGS,
+ RK3568_CLKGATE_CON(35), 7, GFLAGS),
+ COMPOSITE_NOMUX(CPLL_333M, "cpll_333m", "cpll", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(79), 0, 5, DFLAGS,
+ RK3568_CLKGATE_CON(35), 8, GFLAGS),
+ COMPOSITE_NOMUX(CPLL_250M, "cpll_250m", "cpll", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(79), 8, 5, DFLAGS,
+ RK3568_CLKGATE_CON(35), 9, GFLAGS),
+ COMPOSITE_NOMUX(CPLL_125M, "cpll_125m", "cpll", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(80), 0, 5, DFLAGS,
+ RK3568_CLKGATE_CON(35), 10, GFLAGS),
+ COMPOSITE_NOMUX(CPLL_100M, "cpll_100m", "cpll", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(82), 0, 5, DFLAGS,
+ RK3568_CLKGATE_CON(35), 11, GFLAGS),
+ COMPOSITE_NOMUX(CPLL_62P5M, "cpll_62p5", "cpll", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(80), 8, 5, DFLAGS,
+ RK3568_CLKGATE_CON(35), 12, GFLAGS),
+ COMPOSITE_NOMUX(CPLL_50M, "cpll_50m", "cpll", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(81), 0, 5, DFLAGS,
+ RK3568_CLKGATE_CON(35), 13, GFLAGS),
+ COMPOSITE_NOMUX(CPLL_25M, "cpll_25m", "cpll", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(81), 8, 6, DFLAGS,
+ RK3568_CLKGATE_CON(35), 14, GFLAGS),
+ COMPOSITE_NOMUX(0, "clk_osc0_div_750k", "xin24m", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(82), 8, 6, DFLAGS,
+ RK3568_CLKGATE_CON(35), 15, GFLAGS),
+ FACTOR(0, "clk_osc0_div_375k", "clk_osc0_div_750k", 0, 1, 2),
+ FACTOR(0, "xin_osc0_half", "xin24m", 0, 1, 2),
+ MUX(USB480M, "usb480m", mux_usb480m_p, CLK_SET_RATE_PARENT,
+ RK3568_MODE_CON0, 14, 2, MFLAGS),
+
+ /* PD_CORE */
+ COMPOSITE(0, "sclk_core_src", apll_gpll_npll_p, CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3568_CLKGATE_CON(0), 5, GFLAGS),
+ COMPOSITE_NODIV(0, "sclk_core", sclk_core_pre_p, CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(2), 15, 1, MFLAGS,
+ RK3568_CLKGATE_CON(0), 7, GFLAGS),
+
+ COMPOSITE_NOMUX(0, "atclk_core", "armclk", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(3), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3568_CLKGATE_CON(0), 8, GFLAGS),
+ COMPOSITE_NOMUX(0, "gicclk_core", "armclk", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(3), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3568_CLKGATE_CON(0), 9, GFLAGS),
+ COMPOSITE_NOMUX(0, "pclk_core_pre", "armclk", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(4), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3568_CLKGATE_CON(0), 10, GFLAGS),
+ COMPOSITE_NOMUX(0, "periphclk_core_pre", "armclk", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(4), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3568_CLKGATE_CON(0), 11, GFLAGS),
+ COMPOSITE_NOMUX(0, "tsclk_core", "periphclk_core_pre", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(5), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3568_CLKGATE_CON(0), 14, GFLAGS),
+ COMPOSITE_NOMUX(0, "cntclk_core", "periphclk_core_pre", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(5), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3568_CLKGATE_CON(0), 15, GFLAGS),
+ COMPOSITE_NOMUX(0, "aclk_core", "sclk_core", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(5), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3568_CLKGATE_CON(1), 0, GFLAGS),
+
+ COMPOSITE_NODIV(ACLK_CORE_NIU2BUS, "aclk_core_niu2bus", gpll150_gpll100_gpll75_xin24m_p, CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(5), 14, 2, MFLAGS,
+ RK3568_CLKGATE_CON(1), 2, GFLAGS),
+
+ GATE(CLK_CORE_PVTM, "clk_core_pvtm", "xin24m", 0,
+ RK3568_CLKGATE_CON(1), 10, GFLAGS),
+ GATE(CLK_CORE_PVTM_CORE, "clk_core_pvtm_core", "armclk", 0,
+ RK3568_CLKGATE_CON(1), 11, GFLAGS),
+ GATE(CLK_CORE_PVTPLL, "clk_core_pvtpll", "armclk", CLK_IGNORE_UNUSED,
+ RK3568_CLKGATE_CON(1), 12, GFLAGS),
+ GATE(PCLK_CORE_PVTM, "pclk_core_pvtm", "pclk_core_pre", 0,
+ RK3568_CLKGATE_CON(1), 9, GFLAGS),
+
+ /* PD_GPU */
+ COMPOSITE(CLK_GPU_SRC, "clk_gpu_src", mpll_gpll_cpll_npll_p, 0,
+ RK3568_CLKSEL_CON(6), 6, 2, MFLAGS | CLK_MUX_READ_ONLY, 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3568_CLKGATE_CON(2), 0, GFLAGS),
+ MUX(CLK_GPU_PRE_MUX, "clk_gpu_pre_mux", clk_gpu_pre_mux_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(6), 11, 1, MFLAGS | CLK_MUX_READ_ONLY),
+ DIV(ACLK_GPU_PRE, "aclk_gpu_pre", "clk_gpu_pre_mux", 0,
+ RK3568_CLKSEL_CON(6), 8, 2, DFLAGS),
+ DIV(PCLK_GPU_PRE, "pclk_gpu_pre", "clk_gpu_pre_mux", 0,
+ RK3568_CLKSEL_CON(6), 12, 4, DFLAGS),
+ GATE(CLK_GPU, "clk_gpu", "clk_gpu_pre_mux", 0,
+ RK3568_CLKGATE_CON(2), 3, GFLAGS),
+
+ GATE(PCLK_GPU_PVTM, "pclk_gpu_pvtm", "pclk_gpu_pre", 0,
+ RK3568_CLKGATE_CON(2), 6, GFLAGS),
+ GATE(CLK_GPU_PVTM, "clk_gpu_pvtm", "xin24m", 0,
+ RK3568_CLKGATE_CON(2), 7, GFLAGS),
+ GATE(CLK_GPU_PVTM_CORE, "clk_gpu_pvtm_core", "clk_gpu_src", 0,
+ RK3568_CLKGATE_CON(2), 8, GFLAGS),
+ GATE(CLK_GPU_PVTPLL, "clk_gpu_pvtpll", "clk_gpu_src", CLK_IGNORE_UNUSED,
+ RK3568_CLKGATE_CON(2), 9, GFLAGS),
+
+ /* PD_NPU */
+ COMPOSITE(CLK_NPU_SRC, "clk_npu_src", npll_gpll_p, 0,
+ RK3568_CLKSEL_CON(7), 6, 1, MFLAGS, 0, 4, DFLAGS,
+ RK3568_CLKGATE_CON(3), 0, GFLAGS),
+ MUX(CLK_NPU_PRE_NDFT, "clk_npu_pre_ndft", clk_npu_pre_ndft_p, CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+ RK3568_CLKSEL_CON(7), 8, 1, MFLAGS),
+ MUX(CLK_NPU, "clk_npu", clk_npu_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(7), 15, 1, MFLAGS),
+ COMPOSITE_NOMUX(HCLK_NPU_PRE, "hclk_npu_pre", "clk_npu", 0,
+ RK3568_CLKSEL_CON(8), 0, 4, DFLAGS,
+ RK3568_CLKGATE_CON(3), 2, GFLAGS),
+ COMPOSITE_NOMUX(PCLK_NPU_PRE, "pclk_npu_pre", "clk_npu", 0,
+ RK3568_CLKSEL_CON(8), 4, 4, DFLAGS,
+ RK3568_CLKGATE_CON(3), 3, GFLAGS),
+ GATE(ACLK_NPU_PRE, "aclk_npu_pre", "clk_npu", 0,
+ RK3568_CLKGATE_CON(3), 4, GFLAGS),
+ GATE(ACLK_NPU, "aclk_npu", "aclk_npu_pre", 0,
+ RK3568_CLKGATE_CON(3), 7, GFLAGS),
+ GATE(HCLK_NPU, "hclk_npu", "hclk_npu_pre", 0,
+ RK3568_CLKGATE_CON(3), 8, GFLAGS),
+
+ GATE(PCLK_NPU_PVTM, "pclk_npu_pvtm", "pclk_npu_pre", 0,
+ RK3568_CLKGATE_CON(3), 9, GFLAGS),
+ GATE(CLK_NPU_PVTM, "clk_npu_pvtm", "xin24m", 0,
+ RK3568_CLKGATE_CON(3), 10, GFLAGS),
+ GATE(CLK_NPU_PVTM_CORE, "clk_npu_pvtm_core", "clk_npu_pre_ndft", 0,
+ RK3568_CLKGATE_CON(3), 11, GFLAGS),
+ GATE(CLK_NPU_PVTPLL, "clk_npu_pvtpll", "clk_npu_pre_ndft", CLK_IGNORE_UNUSED,
+ RK3568_CLKGATE_CON(3), 12, GFLAGS),
+
+ /* PD_DDR */
+ COMPOSITE(CLK_DDRPHY1X_SRC, "clk_ddrphy1x_src", dpll_gpll_cpll_p, CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(9), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3568_CLKGATE_CON(4), 0, GFLAGS),
+ MUXGRF(CLK_DDR1X, "clk_ddr1x", clk_ddr1x_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(9), 15, 1, MFLAGS),
+
+ COMPOSITE_NOMUX(CLK_MSCH, "clk_msch", "clk_ddr1x", CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(10), 0, 2, DFLAGS,
+ RK3568_CLKGATE_CON(4), 2, GFLAGS),
+ GATE(CLK24_DDRMON, "clk24_ddrmon", "xin24m", CLK_IGNORE_UNUSED,
+ RK3568_CLKGATE_CON(4), 15, GFLAGS),
+
+ /* PD_GIC_AUDIO */
+ COMPOSITE_NODIV(ACLK_GIC_AUDIO, "aclk_gic_audio", gpll200_gpll150_gpll100_xin24m_p, CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(10), 8, 2, MFLAGS,
+ RK3568_CLKGATE_CON(5), 0, GFLAGS),
+ COMPOSITE_NODIV(HCLK_GIC_AUDIO, "hclk_gic_audio", gpll150_gpll100_gpll75_xin24m_p, CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(10), 10, 2, MFLAGS,
+ RK3568_CLKGATE_CON(5), 1, GFLAGS),
+ GATE(HCLK_SDMMC_BUFFER, "hclk_sdmmc_buffer", "hclk_gic_audio", 0,
+ RK3568_CLKGATE_CON(5), 8, GFLAGS),
+ COMPOSITE_NODIV(DCLK_SDMMC_BUFFER, "dclk_sdmmc_buffer", gpll100_gpll75_gpll50_p, 0,
+ RK3568_CLKSEL_CON(10), 12, 2, MFLAGS,
+ RK3568_CLKGATE_CON(5), 9, GFLAGS),
+ GATE(ACLK_GIC600, "aclk_gic600", "aclk_gic_audio", CLK_IGNORE_UNUSED,
+ RK3568_CLKGATE_CON(5), 4, GFLAGS),
+ GATE(ACLK_SPINLOCK, "aclk_spinlock", "aclk_gic_audio", CLK_IGNORE_UNUSED,
+ RK3568_CLKGATE_CON(5), 7, GFLAGS),
+ GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_gic_audio", 0,
+ RK3568_CLKGATE_CON(5), 10, GFLAGS),
+ GATE(HCLK_I2S1_8CH, "hclk_i2s1_8ch", "hclk_gic_audio", 0,
+ RK3568_CLKGATE_CON(5), 11, GFLAGS),
+ GATE(HCLK_I2S2_2CH, "hclk_i2s2_2ch", "hclk_gic_audio", 0,
+ RK3568_CLKGATE_CON(5), 12, GFLAGS),
+ GATE(HCLK_I2S3_2CH, "hclk_i2s3_2ch", "hclk_gic_audio", 0,
+ RK3568_CLKGATE_CON(5), 13, GFLAGS),
+
+ COMPOSITE(CLK_I2S0_8CH_TX_SRC, "clk_i2s0_8ch_tx_src", gpll_cpll_npll_p, 0,
+ RK3568_CLKSEL_CON(11), 8, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3568_CLKGATE_CON(6), 0, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S0_8CH_TX_FRAC, "clk_i2s0_8ch_tx_frac", "clk_i2s0_8ch_tx_src", CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(12), 0,
+ RK3568_CLKGATE_CON(6), 1, GFLAGS,
+ &rk3568_i2s0_8ch_tx_fracmux),
+ GATE(MCLK_I2S0_8CH_TX, "mclk_i2s0_8ch_tx", "clk_i2s0_8ch_tx", 0,
+ RK3568_CLKGATE_CON(6), 2, GFLAGS),
+ COMPOSITE_NODIV(I2S0_MCLKOUT_TX, "i2s0_mclkout_tx", i2s0_mclkout_tx_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(11), 15, 1, MFLAGS,
+ RK3568_CLKGATE_CON(6), 3, GFLAGS),
+
+ COMPOSITE(CLK_I2S0_8CH_RX_SRC, "clk_i2s0_8ch_rx_src", gpll_cpll_npll_p, 0,
+ RK3568_CLKSEL_CON(13), 8, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3568_CLKGATE_CON(6), 4, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S0_8CH_RX_FRAC, "clk_i2s0_8ch_rx_frac", "clk_i2s0_8ch_rx_src", CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(14), 0,
+ RK3568_CLKGATE_CON(6), 5, GFLAGS,
+ &rk3568_i2s0_8ch_rx_fracmux),
+ GATE(MCLK_I2S0_8CH_RX, "mclk_i2s0_8ch_rx", "clk_i2s0_8ch_rx", 0,
+ RK3568_CLKGATE_CON(6), 6, GFLAGS),
+ COMPOSITE_NODIV(I2S0_MCLKOUT_RX, "i2s0_mclkout_rx", i2s0_mclkout_rx_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(13), 15, 1, MFLAGS,
+ RK3568_CLKGATE_CON(6), 7, GFLAGS),
+
+ COMPOSITE(CLK_I2S1_8CH_TX_SRC, "clk_i2s1_8ch_tx_src", gpll_cpll_npll_p, 0,
+ RK3568_CLKSEL_CON(15), 8, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3568_CLKGATE_CON(6), 8, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S1_8CH_TX_FRAC, "clk_i2s1_8ch_tx_frac", "clk_i2s1_8ch_tx_src", CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(16), 0,
+ RK3568_CLKGATE_CON(6), 9, GFLAGS,
+ &rk3568_i2s1_8ch_tx_fracmux),
+ GATE(MCLK_I2S1_8CH_TX, "mclk_i2s1_8ch_tx", "clk_i2s1_8ch_tx", 0,
+ RK3568_CLKGATE_CON(6), 10, GFLAGS),
+ COMPOSITE_NODIV(I2S1_MCLKOUT_TX, "i2s1_mclkout_tx", i2s1_mclkout_tx_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(15), 15, 1, MFLAGS,
+ RK3568_CLKGATE_CON(6), 11, GFLAGS),
+
+ COMPOSITE(CLK_I2S1_8CH_RX_SRC, "clk_i2s1_8ch_rx_src", gpll_cpll_npll_p, 0,
+ RK3568_CLKSEL_CON(17), 8, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3568_CLKGATE_CON(6), 12, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S1_8CH_RX_FRAC, "clk_i2s1_8ch_rx_frac", "clk_i2s1_8ch_rx_src", CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(18), 0,
+ RK3568_CLKGATE_CON(6), 13, GFLAGS,
+ &rk3568_i2s1_8ch_rx_fracmux),
+ GATE(MCLK_I2S1_8CH_RX, "mclk_i2s1_8ch_rx", "clk_i2s1_8ch_rx", 0,
+ RK3568_CLKGATE_CON(6), 14, GFLAGS),
+ COMPOSITE_NODIV(I2S1_MCLKOUT_RX, "i2s1_mclkout_rx", i2s1_mclkout_rx_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(17), 15, 1, MFLAGS,
+ RK3568_CLKGATE_CON(6), 15, GFLAGS),
+
+ COMPOSITE(CLK_I2S2_2CH_SRC, "clk_i2s2_2ch_src", gpll_cpll_npll_p, 0,
+ RK3568_CLKSEL_CON(19), 8, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3568_CLKGATE_CON(7), 0, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S2_2CH_FRAC, "clk_i2s2_2ch_frac", "clk_i2s2_2ch_src", CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(20), 0,
+ RK3568_CLKGATE_CON(7), 1, GFLAGS,
+ &rk3568_i2s2_2ch_fracmux),
+ GATE(MCLK_I2S2_2CH, "mclk_i2s2_2ch", "clk_i2s2_2ch", 0,
+ RK3568_CLKGATE_CON(7), 2, GFLAGS),
+ COMPOSITE_NODIV(I2S2_MCLKOUT, "i2s2_mclkout", i2s2_mclkout_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(19), 15, 1, MFLAGS,
+ RK3568_CLKGATE_CON(7), 3, GFLAGS),
+
+ COMPOSITE(CLK_I2S3_2CH_TX_SRC, "clk_i2s3_2ch_tx_src", gpll_cpll_npll_p, 0,
+ RK3568_CLKSEL_CON(21), 8, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3568_CLKGATE_CON(7), 4, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S3_2CH_TX_FRAC, "clk_i2s3_2ch_tx_frac", "clk_i2s3_2ch_tx_src", CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(22), 0,
+ RK3568_CLKGATE_CON(7), 5, GFLAGS,
+ &rk3568_i2s3_2ch_tx_fracmux),
+ GATE(MCLK_I2S3_2CH_TX, "mclk_i2s3_2ch_tx", "clk_i2s3_2ch_tx", 0,
+ RK3568_CLKGATE_CON(7), 6, GFLAGS),
+ COMPOSITE_NODIV(I2S3_MCLKOUT_TX, "i2s3_mclkout_tx", i2s3_mclkout_tx_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(21), 15, 1, MFLAGS,
+ RK3568_CLKGATE_CON(7), 7, GFLAGS),
+
+ COMPOSITE(CLK_I2S3_2CH_RX_SRC, "clk_i2s3_2ch_rx_src", gpll_cpll_npll_p, 0,
+ RK3568_CLKSEL_CON(83), 8, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3568_CLKGATE_CON(7), 8, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S3_2CH_RX_FRAC, "clk_i2s3_2ch_rx_frac", "clk_i2s3_2ch_rx_src", CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(84), 0,
+ RK3568_CLKGATE_CON(7), 9, GFLAGS,
+ &rk3568_i2s3_2ch_rx_fracmux),
+ GATE(MCLK_I2S3_2CH_RX, "mclk_i2s3_2ch_rx", "clk_i2s3_2ch_rx", 0,
+ RK3568_CLKGATE_CON(7), 10, GFLAGS),
+ COMPOSITE_NODIV(I2S3_MCLKOUT_RX, "i2s3_mclkout_rx", i2s3_mclkout_rx_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(83), 15, 1, MFLAGS,
+ RK3568_CLKGATE_CON(7), 11, GFLAGS),
+
+ GATE(HCLK_PDM, "hclk_pdm", "hclk_gic_audio", 0,
+ RK3568_CLKGATE_CON(5), 14, GFLAGS),
+ COMPOSITE_NODIV(MCLK_PDM, "mclk_pdm", mclk_pdm_p, 0,
+ RK3568_CLKSEL_CON(23), 8, 2, MFLAGS,
+ RK3568_CLKGATE_CON(5), 15, GFLAGS),
+ GATE(HCLK_VAD, "hclk_vad", "hclk_gic_audio", 0,
+ RK3568_CLKGATE_CON(7), 12, GFLAGS),
+ GATE(HCLK_SPDIF_8CH, "hclk_spdif_8ch", "hclk_gic_audio", 0,
+ RK3568_CLKGATE_CON(7), 13, GFLAGS),
+
+ COMPOSITE(MCLK_SPDIF_8CH_SRC, "mclk_spdif_8ch_src", cpll_gpll_p, 0,
+ RK3568_CLKSEL_CON(23), 14, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3568_CLKGATE_CON(7), 14, GFLAGS),
+ COMPOSITE_FRACMUX(MCLK_SPDIF_8CH_FRAC, "mclk_spdif_8ch_frac", "mclk_spdif_8ch_src", CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(24), 0,
+ RK3568_CLKGATE_CON(7), 15, GFLAGS,
+ &rk3568_spdif_8ch_fracmux),
+
+ GATE(HCLK_AUDPWM, "hclk_audpwm", "hclk_gic_audio", 0,
+ RK3568_CLKGATE_CON(8), 0, GFLAGS),
+ COMPOSITE(SCLK_AUDPWM_SRC, "sclk_audpwm_src", gpll_cpll_p, 0,
+ RK3568_CLKSEL_CON(25), 14, 1, MFLAGS, 0, 6, DFLAGS,
+ RK3568_CLKGATE_CON(8), 1, GFLAGS),
+ COMPOSITE_FRACMUX(SCLK_AUDPWM_FRAC, "sclk_audpwm_frac", "sclk_audpwm_src", CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(26), 0,
+ RK3568_CLKGATE_CON(8), 2, GFLAGS,
+ &rk3568_audpwm_fracmux),
+
+ GATE(HCLK_ACDCDIG, "hclk_acdcdig", "hclk_gic_audio", 0,
+ RK3568_CLKGATE_CON(8), 3, GFLAGS),
+ COMPOSITE_NODIV(CLK_ACDCDIG_I2C, "clk_acdcdig_i2c", clk_i2c_p, 0,
+ RK3568_CLKSEL_CON(23), 10, 2, MFLAGS,
+ RK3568_CLKGATE_CON(8), 4, GFLAGS),
+ GATE(CLK_ACDCDIG_DAC, "clk_acdcdig_dac", "mclk_i2s3_2ch_tx", 0,
+ RK3568_CLKGATE_CON(8), 5, GFLAGS),
+ GATE(CLK_ACDCDIG_ADC, "clk_acdcdig_adc", "mclk_i2s3_2ch_rx", 0,
+ RK3568_CLKGATE_CON(8), 6, GFLAGS),
+
+ /* PD_SECURE_FLASH */
+ COMPOSITE_NODIV(ACLK_SECURE_FLASH, "aclk_secure_flash", gpll200_gpll150_gpll100_xin24m_p, 0,
+ RK3568_CLKSEL_CON(27), 0, 2, MFLAGS,
+ RK3568_CLKGATE_CON(8), 7, GFLAGS),
+ COMPOSITE_NODIV(HCLK_SECURE_FLASH, "hclk_secure_flash", gpll150_gpll100_gpll75_xin24m_p, 0,
+ RK3568_CLKSEL_CON(27), 2, 2, MFLAGS,
+ RK3568_CLKGATE_CON(8), 8, GFLAGS),
+ GATE(ACLK_CRYPTO_NS, "aclk_crypto_ns", "aclk_secure_flash", 0,
+ RK3568_CLKGATE_CON(8), 11, GFLAGS),
+ GATE(HCLK_CRYPTO_NS, "hclk_crypto_ns", "hclk_secure_flash", 0,
+ RK3568_CLKGATE_CON(8), 12, GFLAGS),
+ COMPOSITE_NODIV(CLK_CRYPTO_NS_CORE, "clk_crypto_ns_core", gpll200_gpll150_gpll100_p, 0,
+ RK3568_CLKSEL_CON(27), 4, 2, MFLAGS,
+ RK3568_CLKGATE_CON(8), 13, GFLAGS),
+ COMPOSITE_NODIV(CLK_CRYPTO_NS_PKA, "clk_crypto_ns_pka", gpll300_gpll200_gpll100_p, 0,
+ RK3568_CLKSEL_CON(27), 6, 2, MFLAGS,
+ RK3568_CLKGATE_CON(8), 14, GFLAGS),
+ GATE(CLK_CRYPTO_NS_RNG, "clk_crypto_ns_rng", "hclk_secure_flash", 0,
+ RK3568_CLKGATE_CON(8), 15, GFLAGS),
+ GATE(HCLK_TRNG_NS, "hclk_trng_ns", "hclk_secure_flash", CLK_IGNORE_UNUSED,
+ RK3568_CLKGATE_CON(9), 10, GFLAGS),
+ GATE(CLK_TRNG_NS, "clk_trng_ns", "hclk_secure_flash", CLK_IGNORE_UNUSED,
+ RK3568_CLKGATE_CON(9), 11, GFLAGS),
+ GATE(PCLK_OTPC_NS, "pclk_otpc_ns", "hclk_secure_flash", 0,
+ RK3568_CLKGATE_CON(26), 9, GFLAGS),
+ GATE(CLK_OTPC_NS_SBPI, "clk_otpc_ns_sbpi", "xin24m", 0,
+ RK3568_CLKGATE_CON(26), 10, GFLAGS),
+ GATE(CLK_OTPC_NS_USR, "clk_otpc_ns_usr", "xin_osc0_half", 0,
+ RK3568_CLKGATE_CON(26), 11, GFLAGS),
+ GATE(HCLK_NANDC, "hclk_nandc", "hclk_secure_flash", 0,
+ RK3568_CLKGATE_CON(9), 0, GFLAGS),
+ COMPOSITE_NODIV(NCLK_NANDC, "nclk_nandc", clk_nandc_p, 0,
+ RK3568_CLKSEL_CON(28), 0, 2, MFLAGS,
+ RK3568_CLKGATE_CON(9), 1, GFLAGS),
+ GATE(HCLK_SFC, "hclk_sfc", "hclk_secure_flash", 0,
+ RK3568_CLKGATE_CON(9), 2, GFLAGS),
+ GATE(HCLK_SFC_XIP, "hclk_sfc_xip", "hclk_secure_flash", 0,
+ RK3568_CLKGATE_CON(9), 3, GFLAGS),
+ COMPOSITE_NODIV(SCLK_SFC, "sclk_sfc", sclk_sfc_p, 0,
+ RK3568_CLKSEL_CON(28), 4, 3, MFLAGS,
+ RK3568_CLKGATE_CON(9), 4, GFLAGS),
+ GATE(ACLK_EMMC, "aclk_emmc", "aclk_secure_flash", 0,
+ RK3568_CLKGATE_CON(9), 5, GFLAGS),
+ GATE(HCLK_EMMC, "hclk_emmc", "hclk_secure_flash", 0,
+ RK3568_CLKGATE_CON(9), 6, GFLAGS),
+ COMPOSITE_NODIV(BCLK_EMMC, "bclk_emmc", gpll200_gpll150_cpll125_p, 0,
+ RK3568_CLKSEL_CON(28), 8, 2, MFLAGS,
+ RK3568_CLKGATE_CON(9), 7, GFLAGS),
+ COMPOSITE_NODIV(CCLK_EMMC, "cclk_emmc", cclk_emmc_p, 0,
+ RK3568_CLKSEL_CON(28), 12, 3, MFLAGS,
+ RK3568_CLKGATE_CON(9), 8, GFLAGS),
+ GATE(TCLK_EMMC, "tclk_emmc", "xin24m", 0,
+ RK3568_CLKGATE_CON(9), 9, GFLAGS),
+ MMC(SCLK_EMMC_DRV, "emmc_drv", "cclk_emmc", RK3568_EMMC_CON0, 1),
+ MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "cclk_emmc", RK3568_EMMC_CON1, 1),
+
+ /* PD_PIPE */
+ COMPOSITE_NODIV(ACLK_PIPE, "aclk_pipe", aclk_pipe_p, 0,
+ RK3568_CLKSEL_CON(29), 0, 2, MFLAGS,
+ RK3568_CLKGATE_CON(10), 0, GFLAGS),
+ COMPOSITE_NOMUX(PCLK_PIPE, "pclk_pipe", "aclk_pipe", 0,
+ RK3568_CLKSEL_CON(29), 4, 4, DFLAGS,
+ RK3568_CLKGATE_CON(10), 1, GFLAGS),
+ GATE(ACLK_PCIE20_MST, "aclk_pcie20_mst", "aclk_pipe", 0,
+ RK3568_CLKGATE_CON(12), 0, GFLAGS),
+ GATE(ACLK_PCIE20_SLV, "aclk_pcie20_slv", "aclk_pipe", 0,
+ RK3568_CLKGATE_CON(12), 1, GFLAGS),
+ GATE(ACLK_PCIE20_DBI, "aclk_pcie20_dbi", "aclk_pipe", 0,
+ RK3568_CLKGATE_CON(12), 2, GFLAGS),
+ GATE(PCLK_PCIE20, "pclk_pcie20", "pclk_pipe", 0,
+ RK3568_CLKGATE_CON(12), 3, GFLAGS),
+ GATE(CLK_PCIE20_AUX_NDFT, "clk_pcie20_aux_ndft", "xin24m", 0,
+ RK3568_CLKGATE_CON(12), 4, GFLAGS),
+ GATE(ACLK_PCIE30X1_MST, "aclk_pcie30x1_mst", "aclk_pipe", 0,
+ RK3568_CLKGATE_CON(12), 8, GFLAGS),
+ GATE(ACLK_PCIE30X1_SLV, "aclk_pcie30x1_slv", "aclk_pipe", 0,
+ RK3568_CLKGATE_CON(12), 9, GFLAGS),
+ GATE(ACLK_PCIE30X1_DBI, "aclk_pcie30x1_dbi", "aclk_pipe", 0,
+ RK3568_CLKGATE_CON(12), 10, GFLAGS),
+ GATE(PCLK_PCIE30X1, "pclk_pcie30x1", "pclk_pipe", 0,
+ RK3568_CLKGATE_CON(12), 11, GFLAGS),
+ GATE(CLK_PCIE30X1_AUX_NDFT, "clk_pcie30x1_aux_ndft", "xin24m", 0,
+ RK3568_CLKGATE_CON(12), 12, GFLAGS),
+ GATE(ACLK_PCIE30X2_MST, "aclk_pcie30x2_mst", "aclk_pipe", 0,
+ RK3568_CLKGATE_CON(13), 0, GFLAGS),
+ GATE(ACLK_PCIE30X2_SLV, "aclk_pcie30x2_slv", "aclk_pipe", 0,
+ RK3568_CLKGATE_CON(13), 1, GFLAGS),
+ GATE(ACLK_PCIE30X2_DBI, "aclk_pcie30x2_dbi", "aclk_pipe", 0,
+ RK3568_CLKGATE_CON(13), 2, GFLAGS),
+ GATE(PCLK_PCIE30X2, "pclk_pcie30x2", "pclk_pipe", 0,
+ RK3568_CLKGATE_CON(13), 3, GFLAGS),
+ GATE(CLK_PCIE30X2_AUX_NDFT, "clk_pcie30x2_aux_ndft", "xin24m", 0,
+ RK3568_CLKGATE_CON(13), 4, GFLAGS),
+ GATE(ACLK_SATA0, "aclk_sata0", "aclk_pipe", 0,
+ RK3568_CLKGATE_CON(11), 0, GFLAGS),
+ GATE(CLK_SATA0_PMALIVE, "clk_sata0_pmalive", "gpll_20m", 0,
+ RK3568_CLKGATE_CON(11), 1, GFLAGS),
+ GATE(CLK_SATA0_RXOOB, "clk_sata0_rxoob", "cpll_50m", 0,
+ RK3568_CLKGATE_CON(11), 2, GFLAGS),
+ GATE(ACLK_SATA1, "aclk_sata1", "aclk_pipe", 0,
+ RK3568_CLKGATE_CON(11), 4, GFLAGS),
+ GATE(CLK_SATA1_PMALIVE, "clk_sata1_pmalive", "gpll_20m", 0,
+ RK3568_CLKGATE_CON(11), 5, GFLAGS),
+ GATE(CLK_SATA1_RXOOB, "clk_sata1_rxoob", "cpll_50m", 0,
+ RK3568_CLKGATE_CON(11), 6, GFLAGS),
+ GATE(ACLK_SATA2, "aclk_sata2", "aclk_pipe", 0,
+ RK3568_CLKGATE_CON(11), 8, GFLAGS),
+ GATE(CLK_SATA2_PMALIVE, "clk_sata2_pmalive", "gpll_20m", 0,
+ RK3568_CLKGATE_CON(11), 9, GFLAGS),
+ GATE(CLK_SATA2_RXOOB, "clk_sata2_rxoob", "cpll_50m", 0,
+ RK3568_CLKGATE_CON(11), 10, GFLAGS),
+ GATE(ACLK_USB3OTG0, "aclk_usb3otg0", "aclk_pipe", 0,
+ RK3568_CLKGATE_CON(10), 8, GFLAGS),
+ GATE(CLK_USB3OTG0_REF, "clk_usb3otg0_ref", "xin24m", 0,
+ RK3568_CLKGATE_CON(10), 9, GFLAGS),
+ COMPOSITE_NODIV(CLK_USB3OTG0_SUSPEND, "clk_usb3otg0_suspend", xin24m_32k_p, 0,
+ RK3568_CLKSEL_CON(29), 8, 1, MFLAGS,
+ RK3568_CLKGATE_CON(10), 10, GFLAGS),
+ GATE(ACLK_USB3OTG1, "aclk_usb3otg1", "aclk_pipe", 0,
+ RK3568_CLKGATE_CON(10), 12, GFLAGS),
+ GATE(CLK_USB3OTG1_REF, "clk_usb3otg1_ref", "xin24m", 0,
+ RK3568_CLKGATE_CON(10), 13, GFLAGS),
+ COMPOSITE_NODIV(CLK_USB3OTG1_SUSPEND, "clk_usb3otg1_suspend", xin24m_32k_p, 0,
+ RK3568_CLKSEL_CON(29), 9, 1, MFLAGS,
+ RK3568_CLKGATE_CON(10), 14, GFLAGS),
+ COMPOSITE_NODIV(CLK_XPCS_EEE, "clk_xpcs_eee", gpll200_cpll125_p, 0,
+ RK3568_CLKSEL_CON(29), 13, 1, MFLAGS,
+ RK3568_CLKGATE_CON(10), 4, GFLAGS),
+ GATE(PCLK_XPCS, "pclk_xpcs", "pclk_pipe", 0,
+ RK3568_CLKGATE_CON(13), 6, GFLAGS),
+
+ /* PD_PHP */
+ COMPOSITE_NODIV(ACLK_PHP, "aclk_php", gpll300_gpll200_gpll100_xin24m_p, 0,
+ RK3568_CLKSEL_CON(30), 0, 2, MFLAGS,
+ RK3568_CLKGATE_CON(14), 8, GFLAGS),
+ COMPOSITE_NODIV(HCLK_PHP, "hclk_php", gpll150_gpll100_gpll75_xin24m_p, 0,
+ RK3568_CLKSEL_CON(30), 2, 2, MFLAGS,
+ RK3568_CLKGATE_CON(14), 9, GFLAGS),
+ COMPOSITE_NOMUX(PCLK_PHP, "pclk_php", "aclk_php", 0,
+ RK3568_CLKSEL_CON(30), 4, 4, DFLAGS,
+ RK3568_CLKGATE_CON(14), 10, GFLAGS),
+ GATE(HCLK_SDMMC0, "hclk_sdmmc0", "hclk_php", 0,
+ RK3568_CLKGATE_CON(15), 0, GFLAGS),
+ COMPOSITE_NODIV(CLK_SDMMC0, "clk_sdmmc0", clk_sdmmc_p, 0,
+ RK3568_CLKSEL_CON(30), 8, 3, MFLAGS,
+ RK3568_CLKGATE_CON(15), 1, GFLAGS),
+ MMC(SCLK_SDMMC0_DRV, "sdmmc0_drv", "clk_sdmmc0", RK3568_SDMMC0_CON0, 1),
+ MMC(SCLK_SDMMC0_SAMPLE, "sdmmc0_sample", "clk_sdmmc0", RK3568_SDMMC0_CON1, 1),
+
+ GATE(HCLK_SDMMC1, "hclk_sdmmc1", "hclk_php", 0,
+ RK3568_CLKGATE_CON(15), 2, GFLAGS),
+ COMPOSITE_NODIV(CLK_SDMMC1, "clk_sdmmc1", clk_sdmmc_p, 0,
+ RK3568_CLKSEL_CON(30), 12, 3, MFLAGS,
+ RK3568_CLKGATE_CON(15), 3, GFLAGS),
+ MMC(SCLK_SDMMC1_DRV, "sdmmc1_drv", "clk_sdmmc1", RK3568_SDMMC1_CON0, 1),
+ MMC(SCLK_SDMMC1_SAMPLE, "sdmmc1_sample", "clk_sdmmc1", RK3568_SDMMC1_CON1, 1),
+
+ GATE(ACLK_GMAC0, "aclk_gmac0", "aclk_php", 0,
+ RK3568_CLKGATE_CON(15), 5, GFLAGS),
+ GATE(PCLK_GMAC0, "pclk_gmac0", "pclk_php", 0,
+ RK3568_CLKGATE_CON(15), 6, GFLAGS),
+ COMPOSITE_NODIV(CLK_MAC0_2TOP, "clk_mac0_2top", clk_mac_2top_p, 0,
+ RK3568_CLKSEL_CON(31), 8, 2, MFLAGS,
+ RK3568_CLKGATE_CON(15), 7, GFLAGS),
+ COMPOSITE_NODIV(CLK_MAC0_OUT, "clk_mac0_out", cpll125_cpll50_cpll25_xin24m_p, 0,
+ RK3568_CLKSEL_CON(31), 14, 2, MFLAGS,
+ RK3568_CLKGATE_CON(15), 8, GFLAGS),
+ GATE(CLK_MAC0_REFOUT, "clk_mac0_refout", "clk_mac0_2top", 0,
+ RK3568_CLKGATE_CON(15), 12, GFLAGS),
+ COMPOSITE_NODIV(CLK_GMAC0_PTP_REF, "clk_gmac0_ptp_ref", clk_gmac_ptp_p, 0,
+ RK3568_CLKSEL_CON(31), 12, 2, MFLAGS,
+ RK3568_CLKGATE_CON(15), 4, GFLAGS),
+ MUX(SCLK_GMAC0, "clk_gmac0", mux_gmac0_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+ RK3568_CLKSEL_CON(31), 2, 1, MFLAGS),
+ FACTOR(0, "clk_gmac0_tx_div5", "clk_gmac0", 0, 1, 5),
+ FACTOR(0, "clk_gmac0_tx_div50", "clk_gmac0", 0, 1, 50),
+ FACTOR(0, "clk_gmac0_rx_div2", "clk_gmac0", 0, 1, 2),
+ FACTOR(0, "clk_gmac0_rx_div20", "clk_gmac0", 0, 1, 20),
+ MUX(SCLK_GMAC0_RGMII_SPEED, "clk_gmac0_rgmii_speed", mux_gmac0_rgmii_speed_p, 0,
+ RK3568_CLKSEL_CON(31), 4, 2, MFLAGS),
+ MUX(SCLK_GMAC0_RMII_SPEED, "clk_gmac0_rmii_speed", mux_gmac0_rmii_speed_p, 0,
+ RK3568_CLKSEL_CON(31), 3, 1, MFLAGS),
+ MUX(SCLK_GMAC0_RX_TX, "clk_gmac0_rx_tx", mux_gmac0_rx_tx_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(31), 0, 2, MFLAGS),
+
+ /* PD_USB */
+ COMPOSITE_NODIV(ACLK_USB, "aclk_usb", gpll300_gpll200_gpll100_xin24m_p, 0,
+ RK3568_CLKSEL_CON(32), 0, 2, MFLAGS,
+ RK3568_CLKGATE_CON(16), 0, GFLAGS),
+ COMPOSITE_NODIV(HCLK_USB, "hclk_usb", gpll150_gpll100_gpll75_xin24m_p, 0,
+ RK3568_CLKSEL_CON(32), 2, 2, MFLAGS,
+ RK3568_CLKGATE_CON(16), 1, GFLAGS),
+ COMPOSITE_NOMUX(PCLK_USB, "pclk_usb", "aclk_usb", 0,
+ RK3568_CLKSEL_CON(32), 4, 4, DFLAGS,
+ RK3568_CLKGATE_CON(16), 2, GFLAGS),
+ GATE(HCLK_USB2HOST0, "hclk_usb2host0", "hclk_usb", 0,
+ RK3568_CLKGATE_CON(16), 12, GFLAGS),
+ GATE(HCLK_USB2HOST0_ARB, "hclk_usb2host0_arb", "hclk_usb", 0,
+ RK3568_CLKGATE_CON(16), 13, GFLAGS),
+ GATE(HCLK_USB2HOST1, "hclk_usb2host1", "hclk_usb", 0,
+ RK3568_CLKGATE_CON(16), 14, GFLAGS),
+ GATE(HCLK_USB2HOST1_ARB, "hclk_usb2host1_arb", "hclk_usb", 0,
+ RK3568_CLKGATE_CON(16), 15, GFLAGS),
+ GATE(HCLK_SDMMC2, "hclk_sdmmc2", "hclk_usb", 0,
+ RK3568_CLKGATE_CON(17), 0, GFLAGS),
+ COMPOSITE_NODIV(CLK_SDMMC2, "clk_sdmmc2", clk_sdmmc_p, 0,
+ RK3568_CLKSEL_CON(32), 8, 3, MFLAGS,
+ RK3568_CLKGATE_CON(17), 1, GFLAGS),
+ MMC(SCLK_SDMMC2_DRV, "sdmmc2_drv", "clk_sdmmc2", RK3568_SDMMC2_CON0, 1),
+ MMC(SCLK_SDMMC2_SAMPLE, "sdmmc2_sample", "clk_sdmmc2", RK3568_SDMMC2_CON1, 1),
+
+ GATE(ACLK_GMAC1, "aclk_gmac1", "aclk_usb", 0,
+ RK3568_CLKGATE_CON(17), 3, GFLAGS),
+ GATE(PCLK_GMAC1, "pclk_gmac1", "pclk_usb", 0,
+ RK3568_CLKGATE_CON(17), 4, GFLAGS),
+ COMPOSITE_NODIV(CLK_MAC1_2TOP, "clk_mac1_2top", clk_mac_2top_p, 0,
+ RK3568_CLKSEL_CON(33), 8, 2, MFLAGS,
+ RK3568_CLKGATE_CON(17), 5, GFLAGS),
+ COMPOSITE_NODIV(CLK_MAC1_OUT, "clk_mac1_out", cpll125_cpll50_cpll25_xin24m_p, 0,
+ RK3568_CLKSEL_CON(33), 14, 2, MFLAGS,
+ RK3568_CLKGATE_CON(17), 6, GFLAGS),
+ GATE(CLK_MAC1_REFOUT, "clk_mac1_refout", "clk_mac1_2top", 0,
+ RK3568_CLKGATE_CON(17), 10, GFLAGS),
+ COMPOSITE_NODIV(CLK_GMAC1_PTP_REF, "clk_gmac1_ptp_ref", clk_gmac_ptp_p, 0,
+ RK3568_CLKSEL_CON(33), 12, 2, MFLAGS,
+ RK3568_CLKGATE_CON(17), 2, GFLAGS),
+ MUX(SCLK_GMAC1, "clk_gmac1", mux_gmac1_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+ RK3568_CLKSEL_CON(33), 2, 1, MFLAGS),
+ FACTOR(0, "clk_gmac1_tx_div5", "clk_gmac1", 0, 1, 5),
+ FACTOR(0, "clk_gmac1_tx_div50", "clk_gmac1", 0, 1, 50),
+ FACTOR(0, "clk_gmac1_rx_div2", "clk_gmac1", 0, 1, 2),
+ FACTOR(0, "clk_gmac1_rx_div20", "clk_gmac1", 0, 1, 20),
+ MUX(SCLK_GMAC1_RGMII_SPEED, "clk_gmac1_rgmii_speed", mux_gmac1_rgmii_speed_p, 0,
+ RK3568_CLKSEL_CON(33), 4, 2, MFLAGS),
+ MUX(SCLK_GMAC1_RMII_SPEED, "clk_gmac1_rmii_speed", mux_gmac1_rmii_speed_p, 0,
+ RK3568_CLKSEL_CON(33), 3, 1, MFLAGS),
+ MUX(SCLK_GMAC1_RX_TX, "clk_gmac1_rx_tx", mux_gmac1_rx_tx_p, CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(33), 0, 2, MFLAGS),
+
+ /* PD_PERI */
+ COMPOSITE_NODIV(ACLK_PERIMID, "aclk_perimid", gpll300_gpll200_gpll100_xin24m_p, CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(10), 4, 2, MFLAGS,
+ RK3568_CLKGATE_CON(14), 0, GFLAGS),
+ COMPOSITE_NODIV(HCLK_PERIMID, "hclk_perimid", gpll150_gpll100_gpll75_xin24m_p, CLK_IGNORE_UNUSED,
+ RK3568_CLKSEL_CON(10), 6, 2, MFLAGS,
+ RK3568_CLKGATE_CON(14), 1, GFLAGS),
+
+ /* PD_VI */
+ COMPOSITE_NODIV(ACLK_VI, "aclk_vi", gpll400_gpll300_gpll200_xin24m_p, 0,
+ RK3568_CLKSEL_CON(34), 0, 2, MFLAGS,
+ RK3568_CLKGATE_CON(18), 0, GFLAGS),
+ COMPOSITE_NOMUX(HCLK_VI, "hclk_vi", "aclk_vi", 0,
+ RK3568_CLKSEL_CON(34), 4, 4, DFLAGS,
+ RK3568_CLKGATE_CON(18), 1, GFLAGS),
+ COMPOSITE_NOMUX(PCLK_VI, "pclk_vi", "aclk_vi", 0,
+ RK3568_CLKSEL_CON(34), 8, 4, DFLAGS,
+ RK3568_CLKGATE_CON(18), 2, GFLAGS),
+ GATE(ACLK_VICAP, "aclk_vicap", "aclk_vi", 0,
+ RK3568_CLKGATE_CON(18), 9, GFLAGS),
+ GATE(HCLK_VICAP, "hclk_vicap", "hclk_vi", 0,
+ RK3568_CLKGATE_CON(18), 10, GFLAGS),
+ COMPOSITE_NODIV(DCLK_VICAP, "dclk_vicap", cpll333_gpll300_gpll200_p, 0,
+ RK3568_CLKSEL_CON(34), 14, 2, MFLAGS,
+ RK3568_CLKGATE_CON(18), 11, GFLAGS),
+ GATE(ICLK_VICAP_G, "iclk_vicap_g", "iclk_vicap", 0,
+ RK3568_CLKGATE_CON(18), 13, GFLAGS),
+ GATE(ACLK_ISP, "aclk_isp", "aclk_vi", 0,
+ RK3568_CLKGATE_CON(19), 0, GFLAGS),
+ GATE(HCLK_ISP, "hclk_isp", "hclk_vi", 0,
+ RK3568_CLKGATE_CON(19), 1, GFLAGS),
+ COMPOSITE(CLK_ISP, "clk_isp", cpll_gpll_hpll_p, 0,
+ RK3568_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3568_CLKGATE_CON(19), 2, GFLAGS),
+ GATE(PCLK_CSI2HOST1, "pclk_csi2host1", "pclk_vi", 0,
+ RK3568_CLKGATE_CON(19), 4, GFLAGS),
+ COMPOSITE(CLK_CIF_OUT, "clk_cif_out", gpll_usb480m_xin24m_p, 0,
+ RK3568_CLKSEL_CON(35), 14, 2, MFLAGS, 8, 6, DFLAGS,
+ RK3568_CLKGATE_CON(19), 8, GFLAGS),
+ COMPOSITE(CLK_CAM0_OUT, "clk_cam0_out", gpll_usb480m_xin24m_p, 0,
+ RK3568_CLKSEL_CON(36), 6, 2, MFLAGS, 0, 6, DFLAGS,
+ RK3568_CLKGATE_CON(19), 9, GFLAGS),
+ COMPOSITE(CLK_CAM1_OUT, "clk_cam1_out", gpll_usb480m_xin24m_p, 0,
+ RK3568_CLKSEL_CON(36), 14, 2, MFLAGS, 8, 6, DFLAGS,
+ RK3568_CLKGATE_CON(19), 10, GFLAGS),
+
+ /* PD_VO */
+ COMPOSITE_NODIV(ACLK_VO, "aclk_vo", gpll300_cpll250_gpll100_xin24m_p, 0,
+ RK3568_CLKSEL_CON(37), 0, 2, MFLAGS,
+ RK3568_CLKGATE_CON(20), 0, GFLAGS),
+ COMPOSITE_NOMUX(HCLK_VO, "hclk_vo", "aclk_vo", 0,
+ RK3568_CLKSEL_CON(37), 8, 4, DFLAGS,
+ RK3568_CLKGATE_CON(20), 1, GFLAGS),
+ COMPOSITE_NOMUX(PCLK_VO, "pclk_vo", "aclk_vo", 0,
+ RK3568_CLKSEL_CON(37), 12, 4, DFLAGS,
+ RK3568_CLKGATE_CON(20), 2, GFLAGS),
+ COMPOSITE(ACLK_VOP_PRE, "aclk_vop_pre", cpll_gpll_hpll_vpll_p, 0,
+ RK3568_CLKSEL_CON(38), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3568_CLKGATE_CON(20), 6, GFLAGS),
+ GATE(ACLK_VOP, "aclk_vop", "aclk_vop_pre", 0,
+ RK3568_CLKGATE_CON(20), 8, GFLAGS),
+ GATE(HCLK_VOP, "hclk_vop", "hclk_vo", 0,
+ RK3568_CLKGATE_CON(20), 9, GFLAGS),
+ COMPOSITE(DCLK_VOP0, "dclk_vop0", hpll_vpll_gpll_cpll_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+ RK3568_CLKSEL_CON(39), 10, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3568_CLKGATE_CON(20), 10, GFLAGS),
+ COMPOSITE(DCLK_VOP1, "dclk_vop1", hpll_vpll_gpll_cpll_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+ RK3568_CLKSEL_CON(40), 10, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3568_CLKGATE_CON(20), 11, GFLAGS),
+ COMPOSITE(DCLK_VOP2, "dclk_vop2", hpll_vpll_gpll_cpll_p, 0,
+ RK3568_CLKSEL_CON(41), 10, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3568_CLKGATE_CON(20), 12, GFLAGS),
+ GATE(CLK_VOP_PWM, "clk_vop_pwm", "xin24m", 0,
+ RK3568_CLKGATE_CON(20), 13, GFLAGS),
+ GATE(ACLK_HDCP, "aclk_hdcp", "aclk_vo", 0,
+ RK3568_CLKGATE_CON(21), 0, GFLAGS),
+ GATE(HCLK_HDCP, "hclk_hdcp", "hclk_vo", 0,
+ RK3568_CLKGATE_CON(21), 1, GFLAGS),
+ GATE(PCLK_HDCP, "pclk_hdcp", "pclk_vo", 0,
+ RK3568_CLKGATE_CON(21), 2, GFLAGS),
+ GATE(PCLK_HDMI_HOST, "pclk_hdmi_host", "pclk_vo", 0,
+ RK3568_CLKGATE_CON(21), 3, GFLAGS),
+ GATE(CLK_HDMI_SFR, "clk_hdmi_sfr", "xin24m", 0,
+ RK3568_CLKGATE_CON(21), 4, GFLAGS),
+ GATE(CLK_HDMI_CEC, "clk_hdmi_cec", "clk_rtc_32k", 0,
+ RK3568_CLKGATE_CON(21), 5, GFLAGS),
+ GATE(PCLK_DSITX_0, "pclk_dsitx_0", "pclk_vo", 0,
+ RK3568_CLKGATE_CON(21), 6, GFLAGS),
+ GATE(PCLK_DSITX_1, "pclk_dsitx_1", "pclk_vo", 0,
+ RK3568_CLKGATE_CON(21), 7, GFLAGS),
+ GATE(PCLK_EDP_CTRL, "pclk_edp_ctrl", "pclk_vo", 0,
+ RK3568_CLKGATE_CON(21), 8, GFLAGS),
+ COMPOSITE_NODIV(CLK_EDP_200M, "clk_edp_200m", gpll200_gpll150_cpll125_p, 0,
+ RK3568_CLKSEL_CON(38), 8, 2, MFLAGS,
+ RK3568_CLKGATE_CON(21), 9, GFLAGS),
+
+ /* PD_VPU */
+ COMPOSITE(ACLK_VPU_PRE, "aclk_vpu_pre", gpll_cpll_p, 0,
+ RK3568_CLKSEL_CON(42), 7, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3568_CLKGATE_CON(22), 0, GFLAGS),
+ COMPOSITE_NOMUX(HCLK_VPU_PRE, "hclk_vpu_pre", "aclk_vpu_pre", 0,
+ RK3568_CLKSEL_CON(42), 8, 4, DFLAGS,
+ RK3568_CLKGATE_CON(22), 1, GFLAGS),
+ GATE(ACLK_VPU, "aclk_vpu", "aclk_vpu_pre", 0,
+ RK3568_CLKGATE_CON(22), 4, GFLAGS),
+ GATE(HCLK_VPU, "hclk_vpu", "hclk_vpu_pre", 0,
+ RK3568_CLKGATE_CON(22), 5, GFLAGS),
+
+ /* PD_RGA */
+ COMPOSITE_NODIV(ACLK_RGA_PRE, "aclk_rga_pre", gpll300_cpll250_gpll100_xin24m_p, 0,
+ RK3568_CLKSEL_CON(43), 0, 2, MFLAGS,
+ RK3568_CLKGATE_CON(23), 0, GFLAGS),
+ COMPOSITE_NOMUX(HCLK_RGA_PRE, "hclk_rga_pre", "aclk_rga_pre", 0,
+ RK3568_CLKSEL_CON(43), 8, 4, DFLAGS,
+ RK3568_CLKGATE_CON(23), 1, GFLAGS),
+ COMPOSITE_NOMUX(PCLK_RGA_PRE, "pclk_rga_pre", "aclk_rga_pre", 0,
+ RK3568_CLKSEL_CON(43), 12, 4, DFLAGS,
+ RK3568_CLKGATE_CON(22), 12, GFLAGS),
+ GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0,
+ RK3568_CLKGATE_CON(23), 4, GFLAGS),
+ GATE(HCLK_RGA, "hclk_rga", "hclk_rga_pre", 0,
+ RK3568_CLKGATE_CON(23), 5, GFLAGS),
+ COMPOSITE_NODIV(CLK_RGA_CORE, "clk_rga_core", gpll300_gpll200_gpll100_p, 0,
+ RK3568_CLKSEL_CON(43), 2, 2, MFLAGS,
+ RK3568_CLKGATE_CON(23), 6, GFLAGS),
+ GATE(ACLK_IEP, "aclk_iep", "aclk_rga_pre", 0,
+ RK3568_CLKGATE_CON(23), 7, GFLAGS),
+ GATE(HCLK_IEP, "hclk_iep", "hclk_rga_pre", 0,
+ RK3568_CLKGATE_CON(23), 8, GFLAGS),
+ COMPOSITE_NODIV(CLK_IEP_CORE, "clk_iep_core", gpll300_gpll200_gpll100_p, 0,
+ RK3568_CLKSEL_CON(43), 4, 2, MFLAGS,
+ RK3568_CLKGATE_CON(23), 9, GFLAGS),
+ GATE(HCLK_EBC, "hclk_ebc", "hclk_rga_pre", 0, RK3568_CLKGATE_CON(23), 10, GFLAGS),
+ COMPOSITE_NODIV(DCLK_EBC, "dclk_ebc", gpll400_cpll333_gpll200_p, 0,
+ RK3568_CLKSEL_CON(43), 6, 2, MFLAGS,
+ RK3568_CLKGATE_CON(23), 11, GFLAGS),
+ GATE(ACLK_JDEC, "aclk_jdec", "aclk_rga_pre", 0,
+ RK3568_CLKGATE_CON(23), 12, GFLAGS),
+ GATE(HCLK_JDEC, "hclk_jdec", "hclk_rga_pre", 0,
+ RK3568_CLKGATE_CON(23), 13, GFLAGS),
+ GATE(ACLK_JENC, "aclk_jenc", "aclk_rga_pre", 0,
+ RK3568_CLKGATE_CON(23), 14, GFLAGS),
+ GATE(HCLK_JENC, "hclk_jenc", "hclk_rga_pre", 0,
+ RK3568_CLKGATE_CON(23), 15, GFLAGS),
+ GATE(PCLK_EINK, "pclk_eink", "pclk_rga_pre", 0,
+ RK3568_CLKGATE_CON(22), 14, GFLAGS),
+ GATE(HCLK_EINK, "hclk_eink", "hclk_rga_pre", 0,
+ RK3568_CLKGATE_CON(22), 15, GFLAGS),
+
+ /* PD_RKVENC */
+ COMPOSITE(ACLK_RKVENC_PRE, "aclk_rkvenc_pre", gpll_cpll_npll_p, 0,
+ RK3568_CLKSEL_CON(44), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3568_CLKGATE_CON(24), 0, GFLAGS),
+ COMPOSITE_NOMUX(HCLK_RKVENC_PRE, "hclk_rkvenc_pre", "aclk_rkvenc_pre", 0,
+ RK3568_CLKSEL_CON(44), 8, 4, DFLAGS,
+ RK3568_CLKGATE_CON(24), 1, GFLAGS),
+ GATE(ACLK_RKVENC, "aclk_rkvenc", "aclk_rkvenc_pre", 0,
+ RK3568_CLKGATE_CON(24), 6, GFLAGS),
+ GATE(HCLK_RKVENC, "hclk_rkvenc", "hclk_rkvenc_pre", 0,
+ RK3568_CLKGATE_CON(24), 7, GFLAGS),
+ COMPOSITE(CLK_RKVENC_CORE, "clk_rkvenc_core", gpll_cpll_npll_vpll_p, 0,
+ RK3568_CLKSEL_CON(45), 14, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3568_CLKGATE_CON(24), 8, GFLAGS),
+ COMPOSITE(ACLK_RKVDEC_PRE, "aclk_rkvdec_pre", aclk_rkvdec_pre_p, CLK_SET_RATE_NO_REPARENT,
+ RK3568_CLKSEL_CON(47), 7, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3568_CLKGATE_CON(25), 0, GFLAGS),
+ COMPOSITE_NOMUX(HCLK_RKVDEC_PRE, "hclk_rkvdec_pre", "aclk_rkvdec_pre", 0,
+ RK3568_CLKSEL_CON(47), 8, 4, DFLAGS,
+ RK3568_CLKGATE_CON(25), 1, GFLAGS),
+ GATE(ACLK_RKVDEC, "aclk_rkvdec", "aclk_rkvdec_pre", 0,
+ RK3568_CLKGATE_CON(25), 4, GFLAGS),
+ GATE(HCLK_RKVDEC, "hclk_rkvdec", "hclk_rkvdec_pre", 0,
+ RK3568_CLKGATE_CON(25), 5, GFLAGS),
+ COMPOSITE(CLK_RKVDEC_CA, "clk_rkvdec_ca", gpll_cpll_npll_vpll_p, 0,
+ RK3568_CLKSEL_CON(48), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3568_CLKGATE_CON(25), 6, GFLAGS),
+ COMPOSITE(CLK_RKVDEC_CORE, "clk_rkvdec_core", clk_rkvdec_core_p, CLK_SET_RATE_NO_REPARENT,
+ RK3568_CLKSEL_CON(49), 14, 2, MFLAGS, 8, 5, DFLAGS,
+ RK3568_CLKGATE_CON(25), 7, GFLAGS),
+ COMPOSITE(CLK_RKVDEC_HEVC_CA, "clk_rkvdec_hevc_ca", gpll_cpll_npll_vpll_p, 0,
+ RK3568_CLKSEL_CON(49), 6, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3568_CLKGATE_CON(25), 8, GFLAGS),
+
+ /* PD_BUS */
+ COMPOSITE_NODIV(ACLK_BUS, "aclk_bus", gpll200_gpll150_gpll100_xin24m_p, 0,
+ RK3568_CLKSEL_CON(50), 0, 2, MFLAGS,
+ RK3568_CLKGATE_CON(26), 0, GFLAGS),
+ COMPOSITE_NODIV(PCLK_BUS, "pclk_bus", gpll100_gpll75_cpll50_xin24m_p, 0,
+ RK3568_CLKSEL_CON(50), 4, 2, MFLAGS,
+ RK3568_CLKGATE_CON(26), 1, GFLAGS),
+ GATE(PCLK_TSADC, "pclk_tsadc", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(26), 4, GFLAGS),
+ COMPOSITE(CLK_TSADC_TSEN, "clk_tsadc_tsen", xin24m_gpll100_cpll100_p, 0,
+ RK3568_CLKSEL_CON(51), 4, 2, MFLAGS, 0, 3, DFLAGS,
+ RK3568_CLKGATE_CON(26), 5, GFLAGS),
+ COMPOSITE_NOMUX(CLK_TSADC, "clk_tsadc", "clk_tsadc_tsen", 0,
+ RK3568_CLKSEL_CON(51), 8, 7, DFLAGS,
+ RK3568_CLKGATE_CON(26), 6, GFLAGS),
+ GATE(PCLK_SARADC, "pclk_saradc", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(26), 7, GFLAGS),
+ GATE(CLK_SARADC, "clk_saradc", "xin24m", 0,
+ RK3568_CLKGATE_CON(26), 8, GFLAGS),
+ GATE(PCLK_SCR, "pclk_scr", "pclk_bus", CLK_IGNORE_UNUSED,
+ RK3568_CLKGATE_CON(26), 12, GFLAGS),
+ GATE(PCLK_WDT_NS, "pclk_wdt_ns", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(26), 13, GFLAGS),
+ GATE(TCLK_WDT_NS, "tclk_wdt_ns", "xin24m", 0,
+ RK3568_CLKGATE_CON(26), 14, GFLAGS),
+ GATE(ACLK_MCU, "aclk_mcu", "aclk_bus", CLK_IGNORE_UNUSED,
+ RK3568_CLKGATE_CON(32), 13, GFLAGS),
+ GATE(PCLK_INTMUX, "pclk_intmux", "pclk_bus", CLK_IGNORE_UNUSED,
+ RK3568_CLKGATE_CON(32), 14, GFLAGS),
+ GATE(PCLK_MAILBOX, "pclk_mailbox", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(32), 15, GFLAGS),
+
+ GATE(PCLK_UART1, "pclk_uart1", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(27), 12, GFLAGS),
+ COMPOSITE(CLK_UART1_SRC, "clk_uart1_src", gpll_cpll_usb480m_p, 0,
+ RK3568_CLKSEL_CON(52), 8, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3568_CLKGATE_CON(27), 13, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART1_FRAC, "clk_uart1_frac", "clk_uart1_src", CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(53), 0,
+ RK3568_CLKGATE_CON(27), 14, GFLAGS,
+ &rk3568_uart1_fracmux),
+ GATE(SCLK_UART1, "sclk_uart1", "sclk_uart1_mux", 0,
+ RK3568_CLKGATE_CON(27), 15, GFLAGS),
+
+ GATE(PCLK_UART2, "pclk_uart2", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(28), 0, GFLAGS),
+ COMPOSITE(CLK_UART2_SRC, "clk_uart2_src", gpll_cpll_usb480m_p, 0,
+ RK3568_CLKSEL_CON(54), 8, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3568_CLKGATE_CON(28), 1, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART2_FRAC, "clk_uart2_frac", "clk_uart2_src", CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(55), 0,
+ RK3568_CLKGATE_CON(28), 2, GFLAGS,
+ &rk3568_uart2_fracmux),
+ GATE(SCLK_UART2, "sclk_uart2", "sclk_uart2_mux", 0,
+ RK3568_CLKGATE_CON(28), 3, GFLAGS),
+
+ GATE(PCLK_UART3, "pclk_uart3", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(28), 4, GFLAGS),
+ COMPOSITE(CLK_UART3_SRC, "clk_uart3_src", gpll_cpll_usb480m_p, 0,
+ RK3568_CLKSEL_CON(56), 8, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3568_CLKGATE_CON(28), 5, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART3_FRAC, "clk_uart3_frac", "clk_uart3_src", CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(57), 0,
+ RK3568_CLKGATE_CON(28), 6, GFLAGS,
+ &rk3568_uart3_fracmux),
+ GATE(SCLK_UART3, "sclk_uart3", "sclk_uart3_mux", 0,
+ RK3568_CLKGATE_CON(28), 7, GFLAGS),
+
+ GATE(PCLK_UART4, "pclk_uart4", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(28), 8, GFLAGS),
+ COMPOSITE(CLK_UART4_SRC, "clk_uart4_src", gpll_cpll_usb480m_p, 0,
+ RK3568_CLKSEL_CON(58), 8, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3568_CLKGATE_CON(28), 9, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART4_FRAC, "clk_uart4_frac", "clk_uart4_src", CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(59), 0,
+ RK3568_CLKGATE_CON(28), 10, GFLAGS,
+ &rk3568_uart4_fracmux),
+ GATE(SCLK_UART4, "sclk_uart4", "sclk_uart4_mux", 0,
+ RK3568_CLKGATE_CON(28), 11, GFLAGS),
+
+ GATE(PCLK_UART5, "pclk_uart5", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(28), 12, GFLAGS),
+ COMPOSITE(CLK_UART5_SRC, "clk_uart5_src", gpll_cpll_usb480m_p, 0,
+ RK3568_CLKSEL_CON(60), 8, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3568_CLKGATE_CON(28), 13, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART5_FRAC, "clk_uart5_frac", "clk_uart5_src", CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(61), 0,
+ RK3568_CLKGATE_CON(28), 14, GFLAGS,
+ &rk3568_uart5_fracmux),
+ GATE(SCLK_UART5, "sclk_uart5", "sclk_uart5_mux", 0,
+ RK3568_CLKGATE_CON(28), 15, GFLAGS),
+
+ GATE(PCLK_UART6, "pclk_uart6", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(29), 0, GFLAGS),
+ COMPOSITE(CLK_UART6_SRC, "clk_uart6_src", gpll_cpll_usb480m_p, 0,
+ RK3568_CLKSEL_CON(62), 8, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3568_CLKGATE_CON(29), 1, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART6_FRAC, "clk_uart6_frac", "clk_uart6_src", CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(63), 0,
+ RK3568_CLKGATE_CON(29), 2, GFLAGS,
+ &rk3568_uart6_fracmux),
+ GATE(SCLK_UART6, "sclk_uart6", "sclk_uart6_mux", 0,
+ RK3568_CLKGATE_CON(29), 3, GFLAGS),
+
+ GATE(PCLK_UART7, "pclk_uart7", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(29), 4, GFLAGS),
+ COMPOSITE(CLK_UART7_SRC, "clk_uart7_src", gpll_cpll_usb480m_p, 0,
+ RK3568_CLKSEL_CON(64), 8, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3568_CLKGATE_CON(29), 5, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART7_FRAC, "clk_uart7_frac", "clk_uart7_src", CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(65), 0,
+ RK3568_CLKGATE_CON(29), 6, GFLAGS,
+ &rk3568_uart7_fracmux),
+ GATE(SCLK_UART7, "sclk_uart7", "sclk_uart7_mux", 0,
+ RK3568_CLKGATE_CON(29), 7, GFLAGS),
+
+ GATE(PCLK_UART8, "pclk_uart8", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(29), 8, GFLAGS),
+ COMPOSITE(CLK_UART8_SRC, "clk_uart8_src", gpll_cpll_usb480m_p, 0,
+ RK3568_CLKSEL_CON(66), 8, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3568_CLKGATE_CON(29), 9, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART8_FRAC, "clk_uart8_frac", "clk_uart8_src", CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(67), 0,
+ RK3568_CLKGATE_CON(29), 10, GFLAGS,
+ &rk3568_uart8_fracmux),
+ GATE(SCLK_UART8, "sclk_uart8", "sclk_uart8_mux", 0,
+ RK3568_CLKGATE_CON(29), 11, GFLAGS),
+
+ GATE(PCLK_UART9, "pclk_uart9", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(29), 12, GFLAGS),
+ COMPOSITE(CLK_UART9_SRC, "clk_uart9_src", gpll_cpll_usb480m_p, 0,
+ RK3568_CLKSEL_CON(68), 8, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3568_CLKGATE_CON(29), 13, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART9_FRAC, "clk_uart9_frac", "clk_uart9_src", CLK_SET_RATE_PARENT,
+ RK3568_CLKSEL_CON(69), 0,
+ RK3568_CLKGATE_CON(29), 14, GFLAGS,
+ &rk3568_uart9_fracmux),
+ GATE(SCLK_UART9, "sclk_uart9", "sclk_uart9_mux", 0,
+ RK3568_CLKGATE_CON(29), 15, GFLAGS),
+
+ GATE(PCLK_CAN0, "pclk_can0", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(27), 5, GFLAGS),
+ COMPOSITE(CLK_CAN0, "clk_can0", gpll_cpll_p, 0,
+ RK3568_CLKSEL_CON(70), 7, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3568_CLKGATE_CON(27), 6, GFLAGS),
+ GATE(PCLK_CAN1, "pclk_can1", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(27), 7, GFLAGS),
+ COMPOSITE(CLK_CAN1, "clk_can1", gpll_cpll_p, 0,
+ RK3568_CLKSEL_CON(70), 15, 1, MFLAGS, 8, 5, DFLAGS,
+ RK3568_CLKGATE_CON(27), 8, GFLAGS),
+ GATE(PCLK_CAN2, "pclk_can2", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(27), 9, GFLAGS),
+ COMPOSITE(CLK_CAN2, "clk_can2", gpll_cpll_p, 0,
+ RK3568_CLKSEL_CON(71), 7, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3568_CLKGATE_CON(27), 10, GFLAGS),
+ COMPOSITE_NODIV(CLK_I2C, "clk_i2c", clk_i2c_p, 0,
+ RK3568_CLKSEL_CON(71), 8, 2, MFLAGS,
+ RK3568_CLKGATE_CON(32), 10, GFLAGS),
+ GATE(PCLK_I2C1, "pclk_i2c1", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(30), 0, GFLAGS),
+ GATE(CLK_I2C1, "clk_i2c1", "clk_i2c", 0,
+ RK3568_CLKGATE_CON(30), 1, GFLAGS),
+ GATE(PCLK_I2C2, "pclk_i2c2", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(30), 2, GFLAGS),
+ GATE(CLK_I2C2, "clk_i2c2", "clk_i2c", 0,
+ RK3568_CLKGATE_CON(30), 3, GFLAGS),
+ GATE(PCLK_I2C3, "pclk_i2c3", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(30), 4, GFLAGS),
+ GATE(CLK_I2C3, "clk_i2c3", "clk_i2c", 0,
+ RK3568_CLKGATE_CON(30), 5, GFLAGS),
+ GATE(PCLK_I2C4, "pclk_i2c4", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(30), 6, GFLAGS),
+ GATE(CLK_I2C4, "clk_i2c4", "clk_i2c", 0,
+ RK3568_CLKGATE_CON(30), 7, GFLAGS),
+ GATE(PCLK_I2C5, "pclk_i2c5", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(30), 8, GFLAGS),
+ GATE(CLK_I2C5, "clk_i2c5", "clk_i2c", 0,
+ RK3568_CLKGATE_CON(30), 9, GFLAGS),
+ GATE(PCLK_SPI0, "pclk_spi0", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(30), 10, GFLAGS),
+ COMPOSITE_NODIV(CLK_SPI0, "clk_spi0", gpll200_xin24m_cpll100_p, 0,
+ RK3568_CLKSEL_CON(72), 0, 1, MFLAGS,
+ RK3568_CLKGATE_CON(30), 11, GFLAGS),
+ GATE(PCLK_SPI1, "pclk_spi1", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(30), 12, GFLAGS),
+ COMPOSITE_NODIV(CLK_SPI1, "clk_spi1", gpll200_xin24m_cpll100_p, 0,
+ RK3568_CLKSEL_CON(72), 2, 1, MFLAGS,
+ RK3568_CLKGATE_CON(30), 13, GFLAGS),
+ GATE(PCLK_SPI2, "pclk_spi2", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(30), 14, GFLAGS),
+ COMPOSITE_NODIV(CLK_SPI2, "clk_spi2", gpll200_xin24m_cpll100_p, 0,
+ RK3568_CLKSEL_CON(72), 4, 1, MFLAGS,
+ RK3568_CLKGATE_CON(30), 15, GFLAGS),
+ GATE(PCLK_SPI3, "pclk_spi3", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(31), 0, GFLAGS),
+ COMPOSITE_NODIV(CLK_SPI3, "clk_spi3", gpll200_xin24m_cpll100_p, 0,
+ RK3568_CLKSEL_CON(72), 6, 1, MFLAGS, RK3568_CLKGATE_CON(31), 1, GFLAGS),
+ GATE(PCLK_PWM1, "pclk_pwm1", "pclk_bus", 0, RK3568_CLKGATE_CON(31), 10, GFLAGS),
+ COMPOSITE_NODIV(CLK_PWM1, "clk_pwm1", gpll100_xin24m_cpll100_p, 0,
+ RK3568_CLKSEL_CON(72), 8, 1, MFLAGS,
+ RK3568_CLKGATE_CON(31), 11, GFLAGS),
+ GATE(CLK_PWM1_CAPTURE, "clk_pwm1_capture", "xin24m", 0,
+ RK3568_CLKGATE_CON(31), 12, GFLAGS),
+ GATE(PCLK_PWM2, "pclk_pwm2", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(31), 13, GFLAGS),
+ COMPOSITE_NODIV(CLK_PWM2, "clk_pwm2", gpll100_xin24m_cpll100_p, 0,
+ RK3568_CLKSEL_CON(72), 10, 1, MFLAGS,
+ RK3568_CLKGATE_CON(31), 14, GFLAGS),
+ GATE(CLK_PWM2_CAPTURE, "clk_pwm2_capture", "xin24m", 0,
+ RK3568_CLKGATE_CON(31), 15, GFLAGS),
+ GATE(PCLK_PWM3, "pclk_pwm3", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(32), 0, GFLAGS),
+ COMPOSITE_NODIV(CLK_PWM3, "clk_pwm3", gpll100_xin24m_cpll100_p, 0,
+ RK3568_CLKSEL_CON(72), 12, 1, MFLAGS,
+ RK3568_CLKGATE_CON(32), 1, GFLAGS),
+ GATE(CLK_PWM3_CAPTURE, "clk_pwm3_capture", "xin24m", 0,
+ RK3568_CLKGATE_CON(32), 2, GFLAGS),
+ COMPOSITE_NODIV(DBCLK_GPIO, "dbclk_gpio", xin24m_32k_p, 0,
+ RK3568_CLKSEL_CON(72), 14, 1, MFLAGS,
+ RK3568_CLKGATE_CON(32), 11, GFLAGS),
+ GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(31), 2, GFLAGS),
+ GATE(DBCLK_GPIO1, "dbclk_gpio1", "dbclk_gpio", 0,
+ RK3568_CLKGATE_CON(31), 3, GFLAGS),
+ GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(31), 4, GFLAGS),
+ GATE(DBCLK_GPIO2, "dbclk_gpio2", "dbclk_gpio", 0,
+ RK3568_CLKGATE_CON(31), 5, GFLAGS),
+ GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(31), 6, GFLAGS),
+ GATE(DBCLK_GPIO3, "dbclk_gpio3", "dbclk_gpio", 0,
+ RK3568_CLKGATE_CON(31), 7, GFLAGS),
+ GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(31), 8, GFLAGS),
+ GATE(DBCLK_GPIO4, "dbclk_gpio4", "dbclk_gpio", 0,
+ RK3568_CLKGATE_CON(31), 9, GFLAGS),
+ GATE(PCLK_TIMER, "pclk_timer", "pclk_bus", 0,
+ RK3568_CLKGATE_CON(32), 3, GFLAGS),
+ GATE(CLK_TIMER0, "clk_timer0", "xin24m", 0,
+ RK3568_CLKGATE_CON(32), 4, GFLAGS),
+ GATE(CLK_TIMER1, "clk_timer1", "xin24m", 0,
+ RK3568_CLKGATE_CON(32), 5, GFLAGS),
+ GATE(CLK_TIMER2, "clk_timer2", "xin24m", 0,
+ RK3568_CLKGATE_CON(32), 6, GFLAGS),
+ GATE(CLK_TIMER3, "clk_timer3", "xin24m", 0,
+ RK3568_CLKGATE_CON(32), 7, GFLAGS),
+ GATE(CLK_TIMER4, "clk_timer4", "xin24m", 0,
+ RK3568_CLKGATE_CON(32), 8, GFLAGS),
+ GATE(CLK_TIMER5, "clk_timer5", "xin24m", 0,
+ RK3568_CLKGATE_CON(32), 9, GFLAGS),
+
+ /* PD_TOP */
+ COMPOSITE_NODIV(ACLK_TOP_HIGH, "aclk_top_high", cpll500_gpll400_gpll300_xin24m_p, 0,
+ RK3568_CLKSEL_CON(73), 0, 2, MFLAGS,
+ RK3568_CLKGATE_CON(33), 0, GFLAGS),
+ COMPOSITE_NODIV(ACLK_TOP_LOW, "aclk_top_low", gpll400_gpll300_gpll200_xin24m_p, 0,
+ RK3568_CLKSEL_CON(73), 4, 2, MFLAGS,
+ RK3568_CLKGATE_CON(33), 1, GFLAGS),
+ COMPOSITE_NODIV(HCLK_TOP, "hclk_top", gpll150_gpll100_gpll75_xin24m_p, 0,
+ RK3568_CLKSEL_CON(73), 8, 2, MFLAGS,
+ RK3568_CLKGATE_CON(33), 2, GFLAGS),
+ COMPOSITE_NODIV(PCLK_TOP, "pclk_top", gpll100_gpll75_cpll50_xin24m_p, 0,
+ RK3568_CLKSEL_CON(73), 12, 2, MFLAGS,
+ RK3568_CLKGATE_CON(33), 3, GFLAGS),
+ GATE(PCLK_PCIE30PHY, "pclk_pcie30phy", "pclk_top", 0,
+ RK3568_CLKGATE_CON(33), 8, GFLAGS),
+ COMPOSITE_NODIV(CLK_OPTC_ARB, "clk_optc_arb", xin24m_cpll100_p, 0,
+ RK3568_CLKSEL_CON(73), 15, 1, MFLAGS,
+ RK3568_CLKGATE_CON(33), 9, GFLAGS),
+ GATE(PCLK_MIPICSIPHY, "pclk_mipicsiphy", "pclk_top", 0,
+ RK3568_CLKGATE_CON(33), 13, GFLAGS),
+ GATE(PCLK_MIPIDSIPHY0, "pclk_mipidsiphy0", "pclk_top", 0,
+ RK3568_CLKGATE_CON(33), 14, GFLAGS),
+ GATE(PCLK_MIPIDSIPHY1, "pclk_mipidsiphy1", "pclk_top", 0,
+ RK3568_CLKGATE_CON(33), 15, GFLAGS),
+ GATE(PCLK_PIPEPHY0, "pclk_pipephy0", "pclk_top", 0,
+ RK3568_CLKGATE_CON(34), 4, GFLAGS),
+ GATE(PCLK_PIPEPHY1, "pclk_pipephy1", "pclk_top", 0,
+ RK3568_CLKGATE_CON(34), 5, GFLAGS),
+ GATE(PCLK_PIPEPHY2, "pclk_pipephy2", "pclk_top", 0,
+ RK3568_CLKGATE_CON(34), 6, GFLAGS),
+ GATE(PCLK_CPU_BOOST, "pclk_cpu_boost", "pclk_top", 0,
+ RK3568_CLKGATE_CON(34), 11, GFLAGS),
+ GATE(CLK_CPU_BOOST, "clk_cpu_boost", "xin24m", 0,
+ RK3568_CLKGATE_CON(34), 12, GFLAGS),
+ GATE(PCLK_OTPPHY, "pclk_otpphy", "pclk_top", 0,
+ RK3568_CLKGATE_CON(34), 13, GFLAGS),
+ GATE(PCLK_EDPPHY_GRF, "pclk_edpphy_grf", "pclk_top", 0,
+ RK3568_CLKGATE_CON(34), 14, GFLAGS),
+};
+
+static struct rockchip_clk_branch rk3568_clk_pmu_branches[] __initdata = {
+ /* PD_PMU */
+ FACTOR(0, "ppll_ph0", "ppll", 0, 1, 2),
+ FACTOR(0, "ppll_ph180", "ppll", 0, 1, 2),
+ FACTOR(0, "hpll_ph0", "hpll", 0, 1, 2),
+
+ MUX(CLK_PDPMU, "clk_pdpmu", clk_pdpmu_p, 0,
+ RK3568_PMU_CLKSEL_CON(2), 15, 1, MFLAGS),
+ COMPOSITE_NOMUX(PCLK_PDPMU, "pclk_pdpmu", "clk_pdpmu", 0,
+ RK3568_PMU_CLKSEL_CON(2), 0, 5, DFLAGS,
+ RK3568_PMU_CLKGATE_CON(0), 2, GFLAGS),
+ GATE(PCLK_PMU, "pclk_pmu", "pclk_pdpmu", 0,
+ RK3568_PMU_CLKGATE_CON(0), 6, GFLAGS),
+ GATE(CLK_PMU, "clk_pmu", "xin24m", 0,
+ RK3568_PMU_CLKGATE_CON(0), 7, GFLAGS),
+ GATE(PCLK_I2C0, "pclk_i2c0", "pclk_pdpmu", 0,
+ RK3568_PMU_CLKGATE_CON(1), 0, GFLAGS),
+ COMPOSITE_NOMUX(CLK_I2C0, "clk_i2c0", "clk_pdpmu", 0,
+ RK3568_PMU_CLKSEL_CON(3), 0, 7, DFLAGS,
+ RK3568_PMU_CLKGATE_CON(1), 1, GFLAGS),
+ GATE(PCLK_UART0, "pclk_uart0", "pclk_pdpmu", 0,
+ RK3568_PMU_CLKGATE_CON(1), 2, GFLAGS),
+
+ COMPOSITE_FRACMUX(CLK_RTC32K_FRAC, "clk_rtc32k_frac", "xin24m", CLK_IGNORE_UNUSED,
+ RK3568_PMU_CLKSEL_CON(1), 0,
+ RK3568_PMU_CLKGATE_CON(0), 1, GFLAGS,
+ &rk3568_rtc32k_pmu_fracmux),
+
+ COMPOSITE_NOMUX(XIN_OSC0_DIV, "xin_osc0_div", "xin24m", CLK_IGNORE_UNUSED,
+ RK3568_PMU_CLKSEL_CON(0), 0, 5, DFLAGS,
+ RK3568_PMU_CLKGATE_CON(0), 0, GFLAGS),
+
+ COMPOSITE(CLK_UART0_DIV, "sclk_uart0_div", ppll_usb480m_cpll_gpll_p, 0,
+ RK3568_PMU_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3568_PMU_CLKGATE_CON(1), 3, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART0_FRAC, "sclk_uart0_frac", "sclk_uart0_div", CLK_SET_RATE_PARENT,
+ RK3568_PMU_CLKSEL_CON(5), 0,
+ RK3568_PMU_CLKGATE_CON(1), 4, GFLAGS,
+ &rk3568_uart0_fracmux),
+ GATE(SCLK_UART0, "sclk_uart0", "sclk_uart0_mux", 0,
+ RK3568_PMU_CLKGATE_CON(1), 5, GFLAGS),
+
+ GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pdpmu", 0,
+ RK3568_PMU_CLKGATE_CON(1), 9, GFLAGS),
+ COMPOSITE_NODIV(DBCLK_GPIO0, "dbclk_gpio0", xin24m_32k_p, 0,
+ RK3568_PMU_CLKSEL_CON(6), 15, 1, MFLAGS,
+ RK3568_PMU_CLKGATE_CON(1), 10, GFLAGS),
+ GATE(PCLK_PWM0, "pclk_pwm0", "pclk_pdpmu", 0,
+ RK3568_PMU_CLKGATE_CON(1), 6, GFLAGS),
+ COMPOSITE(CLK_PWM0, "clk_pwm0", clk_pwm0_p, 0,
+ RK3568_PMU_CLKSEL_CON(6), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3568_PMU_CLKGATE_CON(1), 7, GFLAGS),
+ GATE(CLK_CAPTURE_PWM0_NDFT, "clk_capture_pwm0_ndft", "xin24m", 0,
+ RK3568_PMU_CLKGATE_CON(1), 8, GFLAGS),
+ GATE(PCLK_PMUPVTM, "pclk_pmupvtm", "pclk_pdpmu", 0,
+ RK3568_PMU_CLKGATE_CON(1), 11, GFLAGS),
+ GATE(CLK_PMUPVTM, "clk_pmupvtm", "xin24m", 0,
+ RK3568_PMU_CLKGATE_CON(1), 12, GFLAGS),
+ GATE(CLK_CORE_PMUPVTM, "clk_core_pmupvtm", "xin24m", 0,
+ RK3568_PMU_CLKGATE_CON(1), 13, GFLAGS),
+ COMPOSITE_NOMUX(CLK_REF24M, "clk_ref24m", "clk_pdpmu", 0,
+ RK3568_PMU_CLKSEL_CON(7), 0, 6, DFLAGS,
+ RK3568_PMU_CLKGATE_CON(2), 0, GFLAGS),
+ GATE(XIN_OSC0_USBPHY0_G, "xin_osc0_usbphy0_g", "xin24m", 0,
+ RK3568_PMU_CLKGATE_CON(2), 1, GFLAGS),
+ MUX(CLK_USBPHY0_REF, "clk_usbphy0_ref", clk_usbphy0_ref_p, 0,
+ RK3568_PMU_CLKSEL_CON(8), 0, 1, MFLAGS),
+ GATE(XIN_OSC0_USBPHY1_G, "xin_osc0_usbphy1_g", "xin24m", 0,
+ RK3568_PMU_CLKGATE_CON(2), 2, GFLAGS),
+ MUX(CLK_USBPHY1_REF, "clk_usbphy1_ref", clk_usbphy1_ref_p, 0,
+ RK3568_PMU_CLKSEL_CON(8), 1, 1, MFLAGS),
+ GATE(XIN_OSC0_MIPIDSIPHY0_G, "xin_osc0_mipidsiphy0_g", "xin24m", 0,
+ RK3568_PMU_CLKGATE_CON(2), 3, GFLAGS),
+ MUX(CLK_MIPIDSIPHY0_REF, "clk_mipidsiphy0_ref", clk_mipidsiphy0_ref_p, 0,
+ RK3568_PMU_CLKSEL_CON(8), 2, 1, MFLAGS),
+ GATE(XIN_OSC0_MIPIDSIPHY1_G, "xin_osc0_mipidsiphy1_g", "xin24m", 0,
+ RK3568_PMU_CLKGATE_CON(2), 4, GFLAGS),
+ MUX(CLK_MIPIDSIPHY1_REF, "clk_mipidsiphy1_ref", clk_mipidsiphy1_ref_p, 0,
+ RK3568_PMU_CLKSEL_CON(8), 3, 1, MFLAGS),
+ COMPOSITE_NOMUX(CLK_WIFI_DIV, "clk_wifi_div", "clk_pdpmu", 0,
+ RK3568_PMU_CLKSEL_CON(8), 8, 6, DFLAGS,
+ RK3568_PMU_CLKGATE_CON(2), 5, GFLAGS),
+ GATE(CLK_WIFI_OSC0, "clk_wifi_osc0", "xin24m", 0,
+ RK3568_PMU_CLKGATE_CON(2), 6, GFLAGS),
+ MUX(CLK_WIFI, "clk_wifi", clk_wifi_p, CLK_SET_RATE_PARENT,
+ RK3568_PMU_CLKSEL_CON(8), 15, 1, MFLAGS),
+ COMPOSITE_NOMUX(CLK_PCIEPHY0_DIV, "clk_pciephy0_div", "ppll_ph0", 0,
+ RK3568_PMU_CLKSEL_CON(9), 0, 3, DFLAGS,
+ RK3568_PMU_CLKGATE_CON(2), 7, GFLAGS),
+ GATE(CLK_PCIEPHY0_OSC0, "clk_pciephy0_osc0", "xin24m", 0,
+ RK3568_PMU_CLKGATE_CON(2), 8, GFLAGS),
+ MUX(CLK_PCIEPHY0_REF, "clk_pciephy0_ref", clk_pciephy0_ref_p, CLK_SET_RATE_PARENT,
+ RK3568_PMU_CLKSEL_CON(9), 3, 1, MFLAGS),
+ COMPOSITE_NOMUX(CLK_PCIEPHY1_DIV, "clk_pciephy1_div", "ppll_ph0", 0,
+ RK3568_PMU_CLKSEL_CON(9), 4, 3, DFLAGS,
+ RK3568_PMU_CLKGATE_CON(2), 9, GFLAGS),
+ GATE(CLK_PCIEPHY1_OSC0, "clk_pciephy1_osc0", "xin24m", 0,
+ RK3568_PMU_CLKGATE_CON(2), 10, GFLAGS),
+ MUX(CLK_PCIEPHY1_REF, "clk_pciephy1_ref", clk_pciephy1_ref_p, CLK_SET_RATE_PARENT,
+ RK3568_PMU_CLKSEL_CON(9), 7, 1, MFLAGS),
+ COMPOSITE_NOMUX(CLK_PCIEPHY2_DIV, "clk_pciephy2_div", "ppll_ph0", 0,
+ RK3568_PMU_CLKSEL_CON(9), 8, 3, DFLAGS,
+ RK3568_PMU_CLKGATE_CON(2), 11, GFLAGS),
+ GATE(CLK_PCIEPHY2_OSC0, "clk_pciephy2_osc0", "xin24m", 0,
+ RK3568_PMU_CLKGATE_CON(2), 12, GFLAGS),
+ MUX(CLK_PCIEPHY2_REF, "clk_pciephy2_ref", clk_pciephy2_ref_p, CLK_SET_RATE_PARENT,
+ RK3568_PMU_CLKSEL_CON(9), 11, 1, MFLAGS),
+ GATE(CLK_PCIE30PHY_REF_M, "clk_pcie30phy_ref_m", "ppll_ph0", 0,
+ RK3568_PMU_CLKGATE_CON(2), 13, GFLAGS),
+ GATE(CLK_PCIE30PHY_REF_N, "clk_pcie30phy_ref_n", "ppll_ph180", 0,
+ RK3568_PMU_CLKGATE_CON(2), 14, GFLAGS),
+ GATE(XIN_OSC0_EDPPHY_G, "xin_osc0_edpphy_g", "xin24m", 0,
+ RK3568_PMU_CLKGATE_CON(2), 15, GFLAGS),
+ MUX(CLK_HDMI_REF, "clk_hdmi_ref", clk_hdmi_ref_p, 0,
+ RK3568_PMU_CLKSEL_CON(8), 7, 1, MFLAGS),
+};
+
+static const char *const rk3568_cru_critical_clocks[] __initconst = {
+ "armclk",
+ "pclk_core_pre",
+ "aclk_bus",
+ "pclk_bus",
+ "aclk_top_high",
+ "aclk_top_low",
+ "hclk_top",
+ "pclk_top",
+ "aclk_perimid",
+ "hclk_perimid",
+ "aclk_secure_flash",
+ "hclk_secure_flash",
+ "aclk_core_niu2bus",
+ "npll",
+ "clk_optc_arb",
+ "hclk_php",
+ "pclk_php",
+ "hclk_usb",
+};
+
+static const char *const rk3568_pmucru_critical_clocks[] __initconst = {
+ "pclk_pdpmu",
+ "pclk_pmu",
+ "clk_pmu",
+};
+
+static void __init rk3568_pmu_clk_init(struct device_node *np)
+{
+ struct rockchip_clk_provider *ctx;
+ void __iomem *reg_base;
+
+ reg_base = of_iomap(np, 0);
+ if (!reg_base) {
+ pr_err("%s: could not map cru pmu region\n", __func__);
+ return;
+ }
+
+ ctx = rockchip_clk_init(np, reg_base, CLKPMU_NR_CLKS);
+ if (IS_ERR(ctx)) {
+ pr_err("%s: rockchip pmu clk init failed\n", __func__);
+ return;
+ }
+
+ rockchip_clk_register_plls(ctx, rk3568_pmu_pll_clks,
+ ARRAY_SIZE(rk3568_pmu_pll_clks),
+ RK3568_GRF_SOC_STATUS0);
+
+ rockchip_clk_register_branches(ctx, rk3568_clk_pmu_branches,
+ ARRAY_SIZE(rk3568_clk_pmu_branches));
+
+ rockchip_register_softrst(np, 1, reg_base + RK3568_PMU_SOFTRST_CON(0),
+ ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+ rockchip_clk_protect_critical(rk3568_pmucru_critical_clocks,
+ ARRAY_SIZE(rk3568_pmucru_critical_clocks));
+
+ rockchip_clk_of_add_provider(np, ctx);
+
+ clk_name_set_parent("ppll", "pll_ppll");
+ clk_name_set_parent("clk_rtc_32k", "clk_rtc32k_frac");
+ clk_name_set_rate("clk_rtc_32k", 32768);
+ clk_name_set_rate("pclk_pmu", 100000000);
+ clk_name_set_rate("pll_ppll", 200000000);
+}
+
+static void __init rk3568_clk_init(struct device_node *np)
+{
+ struct rockchip_clk_provider *ctx;
+ void __iomem *reg_base;
+
+ reg_base = of_iomap(np, 0);
+ if (!reg_base) {
+ pr_err("%s: could not map cru region\n", __func__);
+ return;
+ }
+
+ ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+ if (IS_ERR(ctx)) {
+ pr_err("%s: rockchip clk init failed\n", __func__);
+ return;
+ }
+
+ rockchip_clk_register_plls(ctx, rk3568_pll_clks,
+ ARRAY_SIZE(rk3568_pll_clks),
+ RK3568_GRF_SOC_STATUS0);
+
+ rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
+ mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
+ &rk3568_cpuclk_data, rk3568_cpuclk_rates,
+ ARRAY_SIZE(rk3568_cpuclk_rates));
+
+ rockchip_clk_register_branches(ctx, rk3568_clk_branches,
+ ARRAY_SIZE(rk3568_clk_branches));
+
+ rockchip_register_softrst(np, 30, reg_base + RK3568_SOFTRST_CON(0),
+ ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+ rockchip_register_restart_notifier(ctx, RK3568_GLB_SRST_FST);
+
+ rockchip_clk_protect_critical(rk3568_cru_critical_clocks,
+ ARRAY_SIZE(rk3568_cru_critical_clocks));
+
+ rockchip_clk_of_add_provider(np, ctx);
+
+ clk_name_set_parent("npll", "pll_npll");
+ clk_name_set_parent("vpll", "pll_vpll");
+ clk_name_set_parent("pclk_bus", "gpll_100m");
+ clk_name_set_parent("clk_sdmmc0", "cpll_50m");
+ clk_name_set_parent("cclk_emmc", "gpll_200m");
+
+ clk_name_set_rate("pll_cpll", 1000000000);
+ clk_name_set_rate("pll_gpll", 1188000000);
+ clk_name_set_rate("armclk", 600000000);
+ clk_name_set_rate("aclk_bus", 150000000);
+ clk_name_set_rate("pclk_bus", 100000000);
+ clk_name_set_rate("aclk_top_high", 300000000);
+ clk_name_set_rate("aclk_top_low", 200000000);
+ clk_name_set_rate("hclk_top", 150000000);
+ clk_name_set_rate("pclk_top", 100000000);
+ clk_name_set_rate("aclk_perimid", 300000000);
+ clk_name_set_rate("hclk_perimid", 150000000);
+ clk_name_set_rate("pll_npll", 1200000000);
+ clk_name_set_rate("pll_apll", 816000000);
+
+ clk_name_set_parent("pclk_top", "gpll_100m");
+}
+
+struct clk_rk3568_inits {
+ void (*inits)(struct device_node *np);
+};
+
+static const struct clk_rk3568_inits clk_rk3568_pmucru_init = {
+ .inits = rk3568_pmu_clk_init,
+};
+
+static const struct clk_rk3568_inits clk_3568_cru_init = {
+ .inits = rk3568_clk_init,
+};
+
+static const struct of_device_id clk_rk3568_match_table[] = {
+ {
+ .compatible = "rockchip,rk3568-cru",
+ .data = &clk_3568_cru_init,
+ }, {
+ .compatible = "rockchip,rk3568-pmucru",
+ .data = &clk_rk3568_pmucru_init,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, clk_rk3568_match_table);
+
+static int __init clk_rk3568_probe(struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ const struct clk_rk3568_inits *init_data;
+
+ init_data = of_device_get_match_data(dev);
+ if (init_data->inits)
+ init_data->inits(np);
+
+ return 0;
+}
+
+static struct driver clk_rk3568_driver = {
+ .probe = clk_rk3568_probe,
+ .name = "clk-rk3568",
+ .of_compatible = DRV_OF_COMPAT(clk_rk3568_match_table),
+};
+
+core_platform_driver(clk_rk3568_driver);
diff --git a/drivers/clk/rockchip/clk-rk3588.c b/drivers/clk/rockchip/clk-rk3588.c
new file mode 100644
index 0000000000..8b5c68debe
--- /dev/null
+++ b/drivers/clk/rockchip/clk-rk3588.c
@@ -0,0 +1,2530 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021 Rockchip Electronics Co. Ltd.
+ * Author: Elaine Zhang <zhangqing@rock-chips.com>
+ */
+
+#include <common.h>
+#include <linux/clk.h>
+#include <of.h>
+#include <of_address.h>
+#include <linux/barebox-wrapper.h>
+#include <init.h>
+#include <linux/spinlock.h>
+#include <of_device.h>
+#include <dt-bindings/clock/rockchip,rk3588-cru.h>
+#include "clk.h"
+
+/*
+ * GATE with additional linked clock. Downstream enables the linked clock
+ * (via runtime PM) whenever the gate is enabled. The downstream implementation
+ * does this via separate clock nodes for each of the linked gate clocks,
+ * which leaks parts of the clock tree into DT. It is unclear why this is
+ * actually needed and things work without it for simple use cases. Thus
+ * the linked clock is ignored for now.
+ */
+#define GATE_LINK(_id, cname, pname, linkname, f, o, b, gf) \
+ GATE(_id, cname, pname, f, o, b, gf)
+
+
+#define RK3588_GRF_SOC_STATUS0 0x600
+#define RK3588_PHYREF_ALT_GATE 0xc38
+
+enum rk3588_plls {
+ b0pll, b1pll, lpll, v0pll, aupll, cpll, gpll, npll, ppll,
+};
+
+static struct rockchip_pll_rate_table rk3588_pll_rates[] = {
+ /* _mhz, _p, _m, _s, _k */
+ RK3588_PLL_RATE(2520000000, 2, 210, 0, 0),
+ RK3588_PLL_RATE(2496000000, 2, 208, 0, 0),
+ RK3588_PLL_RATE(2472000000, 2, 206, 0, 0),
+ RK3588_PLL_RATE(2448000000, 2, 204, 0, 0),
+ RK3588_PLL_RATE(2424000000, 2, 202, 0, 0),
+ RK3588_PLL_RATE(2400000000, 2, 200, 0, 0),
+ RK3588_PLL_RATE(2376000000, 2, 198, 0, 0),
+ RK3588_PLL_RATE(2352000000, 2, 196, 0, 0),
+ RK3588_PLL_RATE(2328000000, 2, 194, 0, 0),
+ RK3588_PLL_RATE(2304000000, 2, 192, 0, 0),
+ RK3588_PLL_RATE(2280000000, 2, 190, 0, 0),
+ RK3588_PLL_RATE(2256000000, 2, 376, 1, 0),
+ RK3588_PLL_RATE(2232000000, 2, 372, 1, 0),
+ RK3588_PLL_RATE(2208000000, 2, 368, 1, 0),
+ RK3588_PLL_RATE(2184000000, 2, 364, 1, 0),
+ RK3588_PLL_RATE(2160000000, 2, 360, 1, 0),
+ RK3588_PLL_RATE(2136000000, 2, 356, 1, 0),
+ RK3588_PLL_RATE(2112000000, 2, 352, 1, 0),
+ RK3588_PLL_RATE(2088000000, 2, 348, 1, 0),
+ RK3588_PLL_RATE(2064000000, 2, 344, 1, 0),
+ RK3588_PLL_RATE(2040000000, 2, 340, 1, 0),
+ RK3588_PLL_RATE(2016000000, 2, 336, 1, 0),
+ RK3588_PLL_RATE(1992000000, 2, 332, 1, 0),
+ RK3588_PLL_RATE(1968000000, 2, 328, 1, 0),
+ RK3588_PLL_RATE(1944000000, 2, 324, 1, 0),
+ RK3588_PLL_RATE(1920000000, 2, 320, 1, 0),
+ RK3588_PLL_RATE(1896000000, 2, 316, 1, 0),
+ RK3588_PLL_RATE(1872000000, 2, 312, 1, 0),
+ RK3588_PLL_RATE(1848000000, 2, 308, 1, 0),
+ RK3588_PLL_RATE(1824000000, 2, 304, 1, 0),
+ RK3588_PLL_RATE(1800000000, 2, 300, 1, 0),
+ RK3588_PLL_RATE(1776000000, 2, 296, 1, 0),
+ RK3588_PLL_RATE(1752000000, 2, 292, 1, 0),
+ RK3588_PLL_RATE(1728000000, 2, 288, 1, 0),
+ RK3588_PLL_RATE(1704000000, 2, 284, 1, 0),
+ RK3588_PLL_RATE(1680000000, 2, 280, 1, 0),
+ RK3588_PLL_RATE(1656000000, 2, 276, 1, 0),
+ RK3588_PLL_RATE(1632000000, 2, 272, 1, 0),
+ RK3588_PLL_RATE(1608000000, 2, 268, 1, 0),
+ RK3588_PLL_RATE(1584000000, 2, 264, 1, 0),
+ RK3588_PLL_RATE(1560000000, 2, 260, 1, 0),
+ RK3588_PLL_RATE(1536000000, 2, 256, 1, 0),
+ RK3588_PLL_RATE(1512000000, 2, 252, 1, 0),
+ RK3588_PLL_RATE(1488000000, 2, 248, 1, 0),
+ RK3588_PLL_RATE(1464000000, 2, 244, 1, 0),
+ RK3588_PLL_RATE(1440000000, 2, 240, 1, 0),
+ RK3588_PLL_RATE(1416000000, 2, 236, 1, 0),
+ RK3588_PLL_RATE(1392000000, 2, 232, 1, 0),
+ RK3588_PLL_RATE(1320000000, 2, 220, 1, 0),
+ RK3588_PLL_RATE(1200000000, 2, 200, 1, 0),
+ RK3588_PLL_RATE(1188000000, 2, 198, 1, 0),
+ RK3588_PLL_RATE(1100000000, 3, 550, 2, 0),
+ RK3588_PLL_RATE(1008000000, 2, 336, 2, 0),
+ RK3588_PLL_RATE(1000000000, 3, 500, 2, 0),
+ RK3588_PLL_RATE(983040000, 4, 655, 2, 23592),
+ RK3588_PLL_RATE(955520000, 3, 477, 2, 49806),
+ RK3588_PLL_RATE(903168000, 6, 903, 2, 11009),
+ RK3588_PLL_RATE(900000000, 2, 300, 2, 0),
+ RK3588_PLL_RATE(850000000, 3, 425, 2, 0),
+ RK3588_PLL_RATE(816000000, 2, 272, 2, 0),
+ RK3588_PLL_RATE(786432000, 2, 262, 2, 9437),
+ RK3588_PLL_RATE(786000000, 1, 131, 2, 0),
+ RK3588_PLL_RATE(785560000, 3, 392, 2, 51117),
+ RK3588_PLL_RATE(722534400, 8, 963, 2, 24850),
+ RK3588_PLL_RATE(600000000, 2, 200, 2, 0),
+ RK3588_PLL_RATE(594000000, 2, 198, 2, 0),
+ RK3588_PLL_RATE(408000000, 2, 272, 3, 0),
+ RK3588_PLL_RATE(312000000, 2, 208, 3, 0),
+ RK3588_PLL_RATE(216000000, 2, 288, 4, 0),
+ RK3588_PLL_RATE(100000000, 3, 400, 5, 0),
+ RK3588_PLL_RATE(96000000, 2, 256, 5, 0),
+ { /* sentinel */ },
+};
+
+#define RK3588_CLK_CORE_B0_SEL_CLEAN_MASK 0x3
+#define RK3588_CLK_CORE_B0_SEL_CLEAN_SHIFT 13
+#define RK3588_CLK_CORE_B1_SEL_CLEAN_MASK 0x3
+#define RK3588_CLK_CORE_B1_SEL_CLEAN_SHIFT 5
+#define RK3588_CLK_CORE_B0_GPLL_DIV_MASK 0x1f
+#define RK3588_CLK_CORE_B0_GPLL_DIV_SHIFT 1
+#define RK3588_CLK_CORE_L_SEL_CLEAN_MASK 0x3
+#define RK3588_CLK_CORE_L1_SEL_CLEAN_SHIFT 12
+#define RK3588_CLK_CORE_L0_SEL_CLEAN_SHIFT 5
+#define RK3588_CLK_DSU_SEL_DF_MASK 0x1
+#define RK3588_CLK_DSU_SEL_DF_SHIFT 15
+#define RK3588_CLK_DSU_DF_SRC_MASK 0x3
+#define RK3588_CLK_DSU_DF_SRC_SHIFT 12
+#define RK3588_CLK_DSU_DF_DIV_MASK 0x1f
+#define RK3588_CLK_DSU_DF_DIV_SHIFT 7
+#define RK3588_ACLKM_DSU_DIV_MASK 0x1f
+#define RK3588_ACLKM_DSU_DIV_SHIFT 1
+#define RK3588_ACLKS_DSU_DIV_MASK 0x1f
+#define RK3588_ACLKS_DSU_DIV_SHIFT 6
+#define RK3588_ACLKMP_DSU_DIV_MASK 0x1f
+#define RK3588_ACLKMP_DSU_DIV_SHIFT 11
+#define RK3588_PERIPH_DSU_DIV_MASK 0x1f
+#define RK3588_PERIPH_DSU_DIV_SHIFT 0
+#define RK3588_ATCLK_DSU_DIV_MASK 0x1f
+#define RK3588_ATCLK_DSU_DIV_SHIFT 0
+#define RK3588_GICCLK_DSU_DIV_MASK 0x1f
+#define RK3588_GICCLK_DSU_DIV_SHIFT 5
+
+#define RK3588_CORE_B0_SEL(_apllcore) \
+{ \
+ .reg = RK3588_BIGCORE0_CLKSEL_CON(0), \
+ .val = HIWORD_UPDATE(_apllcore, RK3588_CLK_CORE_B0_SEL_CLEAN_MASK, \
+ RK3588_CLK_CORE_B0_SEL_CLEAN_SHIFT) | \
+ HIWORD_UPDATE(0, RK3588_CLK_CORE_B0_GPLL_DIV_MASK, \
+ RK3588_CLK_CORE_B0_GPLL_DIV_SHIFT), \
+}
+
+#define RK3588_CORE_B1_SEL(_apllcore) \
+{ \
+ .reg = RK3588_BIGCORE0_CLKSEL_CON(1), \
+ .val = HIWORD_UPDATE(_apllcore, RK3588_CLK_CORE_B1_SEL_CLEAN_MASK, \
+ RK3588_CLK_CORE_B1_SEL_CLEAN_SHIFT), \
+}
+
+#define RK3588_CORE_B2_SEL(_apllcore) \
+{ \
+ .reg = RK3588_BIGCORE1_CLKSEL_CON(0), \
+ .val = HIWORD_UPDATE(_apllcore, RK3588_CLK_CORE_B0_SEL_CLEAN_MASK, \
+ RK3588_CLK_CORE_B0_SEL_CLEAN_SHIFT) | \
+ HIWORD_UPDATE(0, RK3588_CLK_CORE_B0_GPLL_DIV_MASK, \
+ RK3588_CLK_CORE_B0_GPLL_DIV_SHIFT), \
+}
+
+#define RK3588_CORE_B3_SEL(_apllcore) \
+{ \
+ .reg = RK3588_BIGCORE1_CLKSEL_CON(1), \
+ .val = HIWORD_UPDATE(_apllcore, RK3588_CLK_CORE_B1_SEL_CLEAN_MASK, \
+ RK3588_CLK_CORE_B1_SEL_CLEAN_SHIFT), \
+}
+
+#define RK3588_CORE_L_SEL0(_offs, _apllcore) \
+{ \
+ .reg = RK3588_DSU_CLKSEL_CON(6 + _offs), \
+ .val = HIWORD_UPDATE(_apllcore, RK3588_CLK_CORE_L_SEL_CLEAN_MASK, \
+ RK3588_CLK_CORE_L0_SEL_CLEAN_SHIFT) | \
+ HIWORD_UPDATE(_apllcore, RK3588_CLK_CORE_L_SEL_CLEAN_MASK, \
+ RK3588_CLK_CORE_L1_SEL_CLEAN_SHIFT), \
+}
+
+#define RK3588_CORE_L_SEL1(_seldsu, _divdsu) \
+{ \
+ .reg = RK3588_DSU_CLKSEL_CON(0), \
+ .val = HIWORD_UPDATE(_seldsu, RK3588_CLK_DSU_DF_SRC_MASK, \
+ RK3588_CLK_DSU_DF_SRC_SHIFT) | \
+ HIWORD_UPDATE(_divdsu - 1, RK3588_CLK_DSU_DF_DIV_MASK, \
+ RK3588_CLK_DSU_DF_DIV_SHIFT), \
+}
+
+#define RK3588_CORE_L_SEL2(_aclkm, _aclkmp, _aclks) \
+{ \
+ .reg = RK3588_DSU_CLKSEL_CON(1), \
+ .val = HIWORD_UPDATE(_aclkm - 1, RK3588_ACLKM_DSU_DIV_MASK, \
+ RK3588_ACLKM_DSU_DIV_SHIFT) | \
+ HIWORD_UPDATE(_aclkmp - 1, RK3588_ACLKMP_DSU_DIV_MASK, \
+ RK3588_ACLKMP_DSU_DIV_SHIFT) | \
+ HIWORD_UPDATE(_aclks - 1, RK3588_ACLKS_DSU_DIV_MASK, \
+ RK3588_ACLKS_DSU_DIV_SHIFT), \
+}
+
+#define RK3588_CORE_L_SEL3(_periph) \
+{ \
+ .reg = RK3588_DSU_CLKSEL_CON(2), \
+ .val = HIWORD_UPDATE(_periph - 1, RK3588_PERIPH_DSU_DIV_MASK, \
+ RK3588_PERIPH_DSU_DIV_SHIFT), \
+}
+
+#define RK3588_CORE_L_SEL4(_gicclk, _atclk) \
+{ \
+ .reg = RK3588_DSU_CLKSEL_CON(3), \
+ .val = HIWORD_UPDATE(_gicclk - 1, RK3588_GICCLK_DSU_DIV_MASK, \
+ RK3588_GICCLK_DSU_DIV_SHIFT) | \
+ HIWORD_UPDATE(_atclk - 1, RK3588_ATCLK_DSU_DIV_MASK, \
+ RK3588_ATCLK_DSU_DIV_SHIFT), \
+}
+
+#define RK3588_CPUB01CLK_RATE(_prate, _apllcore) \
+{ \
+ .prate = _prate##U, \
+ .pre_muxs = { \
+ RK3588_CORE_B0_SEL(0), \
+ RK3588_CORE_B1_SEL(0), \
+ }, \
+ .post_muxs = { \
+ RK3588_CORE_B0_SEL(_apllcore), \
+ RK3588_CORE_B1_SEL(_apllcore), \
+ }, \
+}
+
+#define RK3588_CPUB23CLK_RATE(_prate, _apllcore) \
+{ \
+ .prate = _prate##U, \
+ .pre_muxs = { \
+ RK3588_CORE_B2_SEL(0), \
+ RK3588_CORE_B3_SEL(0), \
+ }, \
+ .post_muxs = { \
+ RK3588_CORE_B2_SEL(_apllcore), \
+ RK3588_CORE_B3_SEL(_apllcore), \
+ }, \
+}
+
+#define RK3588_CPULCLK_RATE(_prate, _apllcore, _seldsu, _divdsu) \
+{ \
+ .prate = _prate##U, \
+ .pre_muxs = { \
+ RK3588_CORE_L_SEL0(0, 0), \
+ RK3588_CORE_L_SEL0(1, 0), \
+ RK3588_CORE_L_SEL1(3, 2), \
+ RK3588_CORE_L_SEL2(2, 3, 3), \
+ RK3588_CORE_L_SEL3(4), \
+ RK3588_CORE_L_SEL4(4, 4), \
+ }, \
+ .post_muxs = { \
+ RK3588_CORE_L_SEL0(0, _apllcore), \
+ RK3588_CORE_L_SEL0(1, _apllcore), \
+ RK3588_CORE_L_SEL1(_seldsu, _divdsu), \
+ }, \
+}
+
+static struct rockchip_cpuclk_rate_table rk3588_cpub0clk_rates[] __initdata = {
+ RK3588_CPUB01CLK_RATE(2496000000, 1),
+ RK3588_CPUB01CLK_RATE(2400000000, 1),
+ RK3588_CPUB01CLK_RATE(2304000000, 1),
+ RK3588_CPUB01CLK_RATE(2208000000, 1),
+ RK3588_CPUB01CLK_RATE(2184000000, 1),
+ RK3588_CPUB01CLK_RATE(2088000000, 1),
+ RK3588_CPUB01CLK_RATE(2040000000, 1),
+ RK3588_CPUB01CLK_RATE(2016000000, 1),
+ RK3588_CPUB01CLK_RATE(1992000000, 1),
+ RK3588_CPUB01CLK_RATE(1896000000, 1),
+ RK3588_CPUB01CLK_RATE(1800000000, 1),
+ RK3588_CPUB01CLK_RATE(1704000000, 0),
+ RK3588_CPUB01CLK_RATE(1608000000, 0),
+ RK3588_CPUB01CLK_RATE(1584000000, 0),
+ RK3588_CPUB01CLK_RATE(1560000000, 0),
+ RK3588_CPUB01CLK_RATE(1536000000, 0),
+ RK3588_CPUB01CLK_RATE(1512000000, 0),
+ RK3588_CPUB01CLK_RATE(1488000000, 0),
+ RK3588_CPUB01CLK_RATE(1464000000, 0),
+ RK3588_CPUB01CLK_RATE(1440000000, 0),
+ RK3588_CPUB01CLK_RATE(1416000000, 0),
+ RK3588_CPUB01CLK_RATE(1392000000, 0),
+ RK3588_CPUB01CLK_RATE(1368000000, 0),
+ RK3588_CPUB01CLK_RATE(1344000000, 0),
+ RK3588_CPUB01CLK_RATE(1320000000, 0),
+ RK3588_CPUB01CLK_RATE(1296000000, 0),
+ RK3588_CPUB01CLK_RATE(1272000000, 0),
+ RK3588_CPUB01CLK_RATE(1248000000, 0),
+ RK3588_CPUB01CLK_RATE(1224000000, 0),
+ RK3588_CPUB01CLK_RATE(1200000000, 0),
+ RK3588_CPUB01CLK_RATE(1104000000, 0),
+ RK3588_CPUB01CLK_RATE(1008000000, 0),
+ RK3588_CPUB01CLK_RATE(912000000, 0),
+ RK3588_CPUB01CLK_RATE(816000000, 0),
+ RK3588_CPUB01CLK_RATE(696000000, 0),
+ RK3588_CPUB01CLK_RATE(600000000, 0),
+ RK3588_CPUB01CLK_RATE(408000000, 0),
+ RK3588_CPUB01CLK_RATE(312000000, 0),
+ RK3588_CPUB01CLK_RATE(216000000, 0),
+ RK3588_CPUB01CLK_RATE(96000000, 0),
+};
+
+static const struct rockchip_cpuclk_reg_data rk3588_cpub0clk_data = {
+ .core_reg[0] = RK3588_BIGCORE0_CLKSEL_CON(0),
+ .div_core_shift[0] = 8,
+ .div_core_mask[0] = 0x1f,
+ .core_reg[1] = RK3588_BIGCORE0_CLKSEL_CON(1),
+ .div_core_shift[1] = 0,
+ .div_core_mask[1] = 0x1f,
+ .num_cores = 2,
+ .mux_core_alt = 1,
+ .mux_core_main = 2,
+ .mux_core_shift = 6,
+ .mux_core_mask = 0x3,
+};
+
+static struct rockchip_cpuclk_rate_table rk3588_cpub1clk_rates[] __initdata = {
+ RK3588_CPUB23CLK_RATE(2496000000, 1),
+ RK3588_CPUB23CLK_RATE(2400000000, 1),
+ RK3588_CPUB23CLK_RATE(2304000000, 1),
+ RK3588_CPUB23CLK_RATE(2208000000, 1),
+ RK3588_CPUB23CLK_RATE(2184000000, 1),
+ RK3588_CPUB23CLK_RATE(2088000000, 1),
+ RK3588_CPUB23CLK_RATE(2040000000, 1),
+ RK3588_CPUB23CLK_RATE(2016000000, 1),
+ RK3588_CPUB23CLK_RATE(1992000000, 1),
+ RK3588_CPUB23CLK_RATE(1896000000, 1),
+ RK3588_CPUB23CLK_RATE(1800000000, 1),
+ RK3588_CPUB23CLK_RATE(1704000000, 0),
+ RK3588_CPUB23CLK_RATE(1608000000, 0),
+ RK3588_CPUB23CLK_RATE(1584000000, 0),
+ RK3588_CPUB23CLK_RATE(1560000000, 0),
+ RK3588_CPUB23CLK_RATE(1536000000, 0),
+ RK3588_CPUB23CLK_RATE(1512000000, 0),
+ RK3588_CPUB23CLK_RATE(1488000000, 0),
+ RK3588_CPUB23CLK_RATE(1464000000, 0),
+ RK3588_CPUB23CLK_RATE(1440000000, 0),
+ RK3588_CPUB23CLK_RATE(1416000000, 0),
+ RK3588_CPUB23CLK_RATE(1392000000, 0),
+ RK3588_CPUB23CLK_RATE(1368000000, 0),
+ RK3588_CPUB23CLK_RATE(1344000000, 0),
+ RK3588_CPUB23CLK_RATE(1320000000, 0),
+ RK3588_CPUB23CLK_RATE(1296000000, 0),
+ RK3588_CPUB23CLK_RATE(1272000000, 0),
+ RK3588_CPUB23CLK_RATE(1248000000, 0),
+ RK3588_CPUB23CLK_RATE(1224000000, 0),
+ RK3588_CPUB23CLK_RATE(1200000000, 0),
+ RK3588_CPUB23CLK_RATE(1104000000, 0),
+ RK3588_CPUB23CLK_RATE(1008000000, 0),
+ RK3588_CPUB23CLK_RATE(912000000, 0),
+ RK3588_CPUB23CLK_RATE(816000000, 0),
+ RK3588_CPUB23CLK_RATE(696000000, 0),
+ RK3588_CPUB23CLK_RATE(600000000, 0),
+ RK3588_CPUB23CLK_RATE(408000000, 0),
+ RK3588_CPUB23CLK_RATE(312000000, 0),
+ RK3588_CPUB23CLK_RATE(216000000, 0),
+ RK3588_CPUB23CLK_RATE(96000000, 0),
+};
+
+static const struct rockchip_cpuclk_reg_data rk3588_cpub1clk_data = {
+ .core_reg[0] = RK3588_BIGCORE1_CLKSEL_CON(0),
+ .div_core_shift[0] = 8,
+ .div_core_mask[0] = 0x1f,
+ .core_reg[1] = RK3588_BIGCORE1_CLKSEL_CON(1),
+ .div_core_shift[1] = 0,
+ .div_core_mask[1] = 0x1f,
+ .num_cores = 2,
+ .mux_core_alt = 1,
+ .mux_core_main = 2,
+ .mux_core_shift = 6,
+ .mux_core_mask = 0x3,
+};
+
+static struct rockchip_cpuclk_rate_table rk3588_cpulclk_rates[] __initdata = {
+ RK3588_CPULCLK_RATE(2208000000, 1, 3, 1),
+ RK3588_CPULCLK_RATE(2184000000, 1, 3, 1),
+ RK3588_CPULCLK_RATE(2088000000, 1, 3, 1),
+ RK3588_CPULCLK_RATE(2040000000, 1, 3, 1),
+ RK3588_CPULCLK_RATE(2016000000, 1, 3, 1),
+ RK3588_CPULCLK_RATE(1992000000, 1, 3, 1),
+ RK3588_CPULCLK_RATE(1896000000, 1, 3, 1),
+ RK3588_CPULCLK_RATE(1800000000, 1, 3, 1),
+ RK3588_CPULCLK_RATE(1704000000, 0, 3, 1),
+ RK3588_CPULCLK_RATE(1608000000, 0, 3, 1),
+ RK3588_CPULCLK_RATE(1584000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1560000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1536000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1512000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1488000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1464000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1440000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1416000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1392000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1368000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1344000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1320000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1296000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1272000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1248000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1224000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1200000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1104000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1008000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(912000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(816000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(696000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(600000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(408000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(312000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(216000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(96000000, 0, 2, 1),
+};
+
+static const struct rockchip_cpuclk_reg_data rk3588_cpulclk_data = {
+ .core_reg[0] = RK3588_DSU_CLKSEL_CON(6),
+ .div_core_shift[0] = 0,
+ .div_core_mask[0] = 0x1f,
+ .core_reg[1] = RK3588_DSU_CLKSEL_CON(6),
+ .div_core_shift[1] = 7,
+ .div_core_mask[1] = 0x1f,
+ .core_reg[2] = RK3588_DSU_CLKSEL_CON(7),
+ .div_core_shift[2] = 0,
+ .div_core_mask[2] = 0x1f,
+ .core_reg[3] = RK3588_DSU_CLKSEL_CON(7),
+ .div_core_shift[3] = 7,
+ .div_core_mask[3] = 0x1f,
+ .num_cores = 4,
+ .mux_core_reg = RK3588_DSU_CLKSEL_CON(5),
+ .mux_core_alt = 1,
+ .mux_core_main = 2,
+ .mux_core_shift = 14,
+ .mux_core_mask = 0x3,
+};
+
+PNAME(mux_pll_p) = { "xin24m", "xin32k" };
+PNAME(mux_armclkl_p) = { "xin24m", "gpll", "lpll" };
+PNAME(mux_armclkb01_p) = { "xin24m", "gpll", "b0pll",};
+PNAME(mux_armclkb23_p) = { "xin24m", "gpll", "b1pll",};
+PNAME(b0pll_b1pll_lpll_gpll_p) = { "b0pll", "b1pll", "lpll", "gpll" };
+PNAME(gpll_24m_p) = { "gpll", "xin24m" };
+PNAME(gpll_aupll_p) = { "gpll", "aupll" };
+PNAME(gpll_lpll_p) = { "gpll", "lpll" };
+PNAME(gpll_cpll_p) = { "gpll", "cpll" };
+PNAME(gpll_spll_p) = { "gpll", "spll" };
+PNAME(gpll_cpll_24m_p) = { "gpll", "cpll", "xin24m"};
+PNAME(gpll_cpll_aupll_p) = { "gpll", "cpll", "aupll"};
+PNAME(gpll_cpll_npll_p) = { "gpll", "cpll", "npll"};
+PNAME(gpll_cpll_npll_v0pll_p) = { "gpll", "cpll", "npll", "v0pll"};
+PNAME(gpll_cpll_24m_spll_p) = { "gpll", "cpll", "xin24m", "spll" };
+PNAME(gpll_cpll_aupll_spll_p) = { "gpll", "cpll", "aupll", "spll" };
+PNAME(gpll_cpll_aupll_npll_p) = { "gpll", "cpll", "aupll", "npll" };
+PNAME(gpll_cpll_v0pll_aupll_p) = { "gpll", "cpll", "v0pll", "aupll" };
+PNAME(gpll_cpll_v0pll_spll_p) = { "gpll", "cpll", "v0pll", "spll" };
+PNAME(gpll_cpll_aupll_npll_spll_p) = { "gpll", "cpll", "aupll", "npll", "spll" };
+PNAME(gpll_cpll_dmyaupll_npll_spll_p) = { "gpll", "cpll", "dummy_aupll", "npll", "spll" };
+PNAME(gpll_cpll_npll_aupll_spll_p) = { "gpll", "cpll", "npll", "aupll", "spll" };
+PNAME(gpll_cpll_npll_1000m_p) = { "gpll", "cpll", "npll", "clk_1000m_src" };
+PNAME(mux_24m_spll_gpll_cpll_p) = { "xin24m", "spll", "gpll", "cpll" };
+PNAME(mux_24m_32k_p) = { "xin24m", "xin32k" };
+PNAME(mux_24m_100m_p) = { "xin24m", "clk_100m_src" };
+PNAME(mux_200m_100m_p) = { "clk_200m_src", "clk_100m_src" };
+PNAME(mux_100m_50m_24m_p) = { "clk_100m_src", "clk_50m_src", "xin24m" };
+PNAME(mux_150m_50m_24m_p) = { "clk_150m_src", "clk_50m_src", "xin24m" };
+PNAME(mux_150m_100m_24m_p) = { "clk_150m_src", "clk_100m_src", "xin24m" };
+PNAME(mux_200m_150m_24m_p) = { "clk_200m_src", "clk_150m_src", "xin24m" };
+PNAME(mux_150m_100m_50m_24m_p) = { "clk_150m_src", "clk_100m_src", "clk_50m_src", "xin24m" };
+PNAME(mux_200m_100m_50m_24m_p) = { "clk_200m_src", "clk_100m_src", "clk_50m_src", "xin24m" };
+PNAME(mux_300m_200m_100m_24m_p) = { "clk_300m_src", "clk_200m_src", "clk_100m_src", "xin24m" };
+PNAME(mux_700m_400m_200m_24m_p) = { "clk_700m_src", "clk_400m_src", "clk_200m_src", "xin24m" };
+PNAME(mux_500m_250m_100m_24m_p) = { "clk_500m_src", "clk_250m_src", "clk_100m_src", "xin24m" };
+PNAME(mux_500m_300m_100m_24m_p) = { "clk_500m_src", "clk_300m_src", "clk_100m_src", "xin24m" };
+PNAME(mux_400m_200m_100m_24m_p) = { "clk_400m_src", "clk_200m_src", "clk_100m_src", "xin24m" };
+PNAME(clk_i2s2_2ch_p) = { "clk_i2s2_2ch_src", "clk_i2s2_2ch_frac", "i2s2_mclkin", "xin12m" };
+PNAME(i2s2_2ch_mclkout_p) = { "mclk_i2s2_2ch", "xin12m" };
+PNAME(clk_i2s3_2ch_p) = { "clk_i2s3_2ch_src", "clk_i2s3_2ch_frac", "i2s3_mclkin", "xin12m" };
+PNAME(i2s3_2ch_mclkout_p) = { "mclk_i2s3_2ch", "xin12m" };
+PNAME(clk_i2s0_8ch_tx_p) = { "clk_i2s0_8ch_tx_src", "clk_i2s0_8ch_tx_frac", "i2s0_mclkin", "xin12m" };
+PNAME(clk_i2s0_8ch_rx_p) = { "clk_i2s0_8ch_rx_src", "clk_i2s0_8ch_rx_frac", "i2s0_mclkin", "xin12m" };
+PNAME(i2s0_8ch_mclkout_p) = { "mclk_i2s0_8ch_tx", "mclk_i2s0_8ch_rx", "xin12m" };
+PNAME(clk_i2s1_8ch_tx_p) = { "clk_i2s1_8ch_tx_src", "clk_i2s1_8ch_tx_frac", "i2s1_mclkin", "xin12m" };
+PNAME(clk_i2s1_8ch_rx_p) = { "clk_i2s1_8ch_rx_src", "clk_i2s1_8ch_rx_frac", "i2s1_mclkin", "xin12m" };
+PNAME(i2s1_8ch_mclkout_p) = { "mclk_i2s1_8ch_tx", "mclk_i2s1_8ch_rx", "xin12m" };
+PNAME(clk_i2s4_8ch_tx_p) = { "clk_i2s4_8ch_tx_src", "clk_i2s4_8ch_tx_frac", "i2s4_mclkin", "xin12m" };
+PNAME(clk_i2s5_8ch_tx_p) = { "clk_i2s5_8ch_tx_src", "clk_i2s5_8ch_tx_frac", "i2s5_mclkin", "xin12m" };
+PNAME(clk_i2s6_8ch_tx_p) = { "clk_i2s6_8ch_tx_src", "clk_i2s6_8ch_tx_frac", "i2s6_mclkin", "xin12m" };
+PNAME(clk_i2s6_8ch_rx_p) = { "clk_i2s6_8ch_rx_src", "clk_i2s6_8ch_rx_frac", "i2s6_mclkin", "xin12m" };
+PNAME(i2s6_8ch_mclkout_p) = { "mclk_i2s6_8ch_tx", "mclk_i2s6_8ch_rx", "xin12m" };
+PNAME(clk_i2s7_8ch_rx_p) = { "clk_i2s7_8ch_rx_src", "clk_i2s7_8ch_rx_frac", "i2s7_mclkin", "xin12m" };
+PNAME(clk_i2s8_8ch_tx_p) = { "clk_i2s8_8ch_tx_src", "clk_i2s8_8ch_tx_frac", "i2s8_mclkin", "xin12m" };
+PNAME(clk_i2s9_8ch_rx_p) = { "clk_i2s9_8ch_rx_src", "clk_i2s9_8ch_rx_frac", "i2s9_mclkin", "xin12m" };
+PNAME(clk_i2s10_8ch_rx_p) = { "clk_i2s10_8ch_rx_src", "clk_i2s10_8ch_rx_frac", "i2s10_mclkin", "xin12m" };
+PNAME(clk_spdif0_p) = { "clk_spdif0_src", "clk_spdif0_frac", "xin12m" };
+PNAME(clk_spdif1_p) = { "clk_spdif1_src", "clk_spdif1_frac", "xin12m" };
+PNAME(clk_spdif2_dp0_p) = { "clk_spdif2_dp0_src", "clk_spdif2_dp0_frac", "xin12m" };
+PNAME(clk_spdif3_p) = { "clk_spdif3_src", "clk_spdif3_frac", "xin12m" };
+PNAME(clk_spdif4_p) = { "clk_spdif4_src", "clk_spdif4_frac", "xin12m" };
+PNAME(clk_spdif5_dp1_p) = { "clk_spdif5_dp1_src", "clk_spdif5_dp1_frac", "xin12m" };
+PNAME(clk_uart0_p) = { "clk_uart0_src", "clk_uart0_frac", "xin24m" };
+PNAME(clk_uart1_p) = { "clk_uart1_src", "clk_uart1_frac", "xin24m" };
+PNAME(clk_uart2_p) = { "clk_uart2_src", "clk_uart2_frac", "xin24m" };
+PNAME(clk_uart3_p) = { "clk_uart3_src", "clk_uart3_frac", "xin24m" };
+PNAME(clk_uart4_p) = { "clk_uart4_src", "clk_uart4_frac", "xin24m" };
+PNAME(clk_uart5_p) = { "clk_uart5_src", "clk_uart5_frac", "xin24m" };
+PNAME(clk_uart6_p) = { "clk_uart6_src", "clk_uart6_frac", "xin24m" };
+PNAME(clk_uart7_p) = { "clk_uart7_src", "clk_uart7_frac", "xin24m" };
+PNAME(clk_uart8_p) = { "clk_uart8_src", "clk_uart8_frac", "xin24m" };
+PNAME(clk_uart9_p) = { "clk_uart9_src", "clk_uart9_frac", "xin24m" };
+PNAME(clk_gmac0_ptp_ref_p) = { "cpll", "clk_gmac0_ptpref_io" };
+PNAME(clk_gmac1_ptp_ref_p) = { "cpll", "clk_gmac1_ptpref_io" };
+PNAME(clk_hdmirx_aud_p) = { "clk_hdmirx_aud_src", "clk_hdmirx_aud_frac" };
+PNAME(aclk_hdcp1_root_p) = { "gpll", "cpll", "clk_hdmitrx_refsrc" };
+PNAME(aclk_vop_sub_src_p) = { "aclk_vop_root", "aclk_vop_div2_src" };
+PNAME(dclk_vop0_p) = { "dclk_vop0_src", "clk_hdmiphy_pixel0", "clk_hdmiphy_pixel1" };
+PNAME(dclk_vop1_p) = { "dclk_vop1_src", "clk_hdmiphy_pixel0", "clk_hdmiphy_pixel1" };
+PNAME(dclk_vop2_p) = { "dclk_vop2_src", "clk_hdmiphy_pixel0", "clk_hdmiphy_pixel1" };
+PNAME(pmu_200m_100m_p) = { "clk_pmu1_200m_src", "clk_pmu1_100m_src" };
+PNAME(pmu_300m_24m_p) = { "clk_300m_src", "xin24m" };
+PNAME(pmu_400m_24m_p) = { "clk_400m_src", "xin24m" };
+PNAME(pmu_100m_50m_24m_src_p) = { "clk_pmu1_100m_src", "clk_pmu1_50m_src", "xin24m" };
+PNAME(pmu_24m_32k_100m_src_p) = { "xin24m", "32k", "clk_pmu1_100m_src" };
+PNAME(hclk_pmu1_root_p) = { "clk_pmu1_200m_src", "clk_pmu1_100m_src", "clk_pmu1_50m_src", "xin24m" };
+PNAME(hclk_pmu_cm0_root_p) = { "clk_pmu1_400m_src", "clk_pmu1_200m_src", "clk_pmu1_100m_src", "xin24m" };
+PNAME(mclk_pdm0_p) = { "clk_pmu1_300m_src", "clk_pmu1_200m_src" };
+PNAME(mux_24m_ppll_spll_p) = { "xin24m", "ppll", "spll" };
+PNAME(mux_24m_ppll_p) = { "xin24m", "ppll" };
+PNAME(clk_ref_pipe_phy0_p) = { "clk_ref_pipe_phy0_osc_src", "clk_ref_pipe_phy0_pll_src" };
+PNAME(clk_ref_pipe_phy1_p) = { "clk_ref_pipe_phy1_osc_src", "clk_ref_pipe_phy1_pll_src" };
+PNAME(clk_ref_pipe_phy2_p) = { "clk_ref_pipe_phy2_osc_src", "clk_ref_pipe_phy2_pll_src" };
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+
+static struct rockchip_clk_branch rk3588_i2s0_8ch_tx_fracmux __initdata =
+ MUX(CLK_I2S0_8CH_TX, "clk_i2s0_8ch_tx", clk_i2s0_8ch_tx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(26), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s0_8ch_rx_fracmux __initdata =
+ MUX(CLK_I2S0_8CH_RX, "clk_i2s0_8ch_rx", clk_i2s0_8ch_rx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(28), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s1_8ch_tx_fracmux __initdata =
+ MUX(CLK_I2S1_8CH_TX, "clk_i2s1_8ch_tx", clk_i2s1_8ch_tx_p, CLK_SET_RATE_PARENT,
+ RK3588_PMU_CLKSEL_CON(7), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s1_8ch_rx_fracmux __initdata =
+ MUX(CLK_I2S1_8CH_RX, "clk_i2s1_8ch_rx", clk_i2s1_8ch_rx_p, CLK_SET_RATE_PARENT,
+ RK3588_PMU_CLKSEL_CON(9), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s2_2ch_fracmux __initdata =
+ MUX(CLK_I2S2_2CH, "clk_i2s2_2ch", clk_i2s2_2ch_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(30), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s3_2ch_fracmux __initdata =
+ MUX(CLK_I2S3_2CH, "clk_i2s3_2ch", clk_i2s3_2ch_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(32), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s4_8ch_tx_fracmux __initdata =
+ MUX(CLK_I2S4_8CH_TX, "clk_i2s4_8ch_tx", clk_i2s4_8ch_tx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(120), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s5_8ch_tx_fracmux __initdata =
+ MUX(CLK_I2S5_8CH_TX, "clk_i2s5_8ch_tx", clk_i2s5_8ch_tx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(142), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s6_8ch_tx_fracmux __initdata =
+ MUX(CLK_I2S6_8CH_TX, "clk_i2s6_8ch_tx", clk_i2s6_8ch_tx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(146), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s6_8ch_rx_fracmux __initdata =
+ MUX(CLK_I2S6_8CH_RX, "clk_i2s6_8ch_rx", clk_i2s6_8ch_rx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(148), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s7_8ch_rx_fracmux __initdata =
+ MUX(CLK_I2S7_8CH_RX, "clk_i2s7_8ch_rx", clk_i2s7_8ch_rx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(131), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s8_8ch_tx_fracmux __initdata =
+ MUX(CLK_I2S8_8CH_TX, "clk_i2s8_8ch_tx", clk_i2s8_8ch_tx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(122), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s9_8ch_rx_fracmux __initdata =
+ MUX(CLK_I2S9_8CH_RX, "clk_i2s9_8ch_rx", clk_i2s9_8ch_rx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(155), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s10_8ch_rx_fracmux __initdata =
+ MUX(CLK_I2S10_8CH_RX, "clk_i2s10_8ch_rx", clk_i2s10_8ch_rx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(157), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_spdif0_fracmux __initdata =
+ MUX(CLK_SPDIF0, "clk_spdif0", clk_spdif0_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(34), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_spdif1_fracmux __initdata =
+ MUX(CLK_SPDIF1, "clk_spdif1", clk_spdif1_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(36), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_spdif2_dp0_fracmux __initdata =
+ MUX(CLK_SPDIF2_DP0, "clk_spdif2_dp0", clk_spdif2_dp0_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(124), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_spdif3_fracmux __initdata =
+ MUX(CLK_SPDIF3, "clk_spdif3", clk_spdif3_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(150), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_spdif4_fracmux __initdata =
+ MUX(CLK_SPDIF4, "clk_spdif4", clk_spdif4_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(152), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_spdif5_dp1_fracmux __initdata =
+ MUX(CLK_SPDIF5_DP1, "clk_spdif5_dp1", clk_spdif5_dp1_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(126), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart0_fracmux __initdata =
+ MUX(CLK_UART0, "clk_uart0", clk_uart0_p, CLK_SET_RATE_PARENT,
+ RK3588_PMU_CLKSEL_CON(5), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart1_fracmux __initdata =
+ MUX(CLK_UART1, "clk_uart1", clk_uart1_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(43), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart2_fracmux __initdata =
+ MUX(CLK_UART2, "clk_uart2", clk_uart2_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(45), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart3_fracmux __initdata =
+ MUX(CLK_UART3, "clk_uart3", clk_uart3_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(47), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart4_fracmux __initdata =
+ MUX(CLK_UART4, "clk_uart4", clk_uart4_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(49), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart5_fracmux __initdata =
+ MUX(CLK_UART5, "clk_uart5", clk_uart5_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(51), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart6_fracmux __initdata =
+ MUX(CLK_UART6, "clk_uart6", clk_uart6_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(53), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart7_fracmux __initdata =
+ MUX(CLK_UART7, "clk_uart7", clk_uart7_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(55), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart8_fracmux __initdata =
+ MUX(CLK_UART8, "clk_uart8", clk_uart8_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(57), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart9_fracmux __initdata =
+ MUX(CLK_UART9, "clk_uart9", clk_uart9_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(59), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_hdmirx_aud_fracmux __initdata =
+ MUX(CLK_HDMIRX_AUD_P_MUX, "clk_hdmirx_aud_mux", clk_hdmirx_aud_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(140), 0, 1, MFLAGS);
+
+static struct rockchip_pll_clock rk3588_pll_clks[] __initdata = {
+ [b0pll] = PLL(pll_rk3588_core, PLL_B0PLL, "b0pll", mux_pll_p,
+ CLK_IGNORE_UNUSED, RK3588_B0_PLL_CON(0),
+ RK3588_B0_PLL_MODE_CON0, 0, 15, 0, rk3588_pll_rates),
+ [b1pll] = PLL(pll_rk3588_core, PLL_B1PLL, "b1pll", mux_pll_p,
+ CLK_IGNORE_UNUSED, RK3588_B1_PLL_CON(8),
+ RK3588_B1_PLL_MODE_CON0, 0, 15, 0, rk3588_pll_rates),
+ [lpll] = PLL(pll_rk3588_core, PLL_LPLL, "lpll", mux_pll_p,
+ CLK_IGNORE_UNUSED, RK3588_LPLL_CON(16),
+ RK3588_LPLL_MODE_CON0, 0, 15, 0, rk3588_pll_rates),
+ [v0pll] = PLL(pll_rk3588, PLL_V0PLL, "v0pll", mux_pll_p,
+ 0, RK3588_PLL_CON(88),
+ RK3588_MODE_CON0, 4, 15, 0, rk3588_pll_rates),
+ [aupll] = PLL(pll_rk3588, PLL_AUPLL, "aupll", mux_pll_p,
+ 0, RK3588_PLL_CON(96),
+ RK3588_MODE_CON0, 6, 15, 0, rk3588_pll_rates),
+ [cpll] = PLL(pll_rk3588, PLL_CPLL, "cpll", mux_pll_p,
+ CLK_IGNORE_UNUSED, RK3588_PLL_CON(104),
+ RK3588_MODE_CON0, 8, 15, 0, rk3588_pll_rates),
+ [gpll] = PLL(pll_rk3588, PLL_GPLL, "gpll", mux_pll_p,
+ CLK_IGNORE_UNUSED, RK3588_PLL_CON(112),
+ RK3588_MODE_CON0, 2, 15, 0, rk3588_pll_rates),
+ [npll] = PLL(pll_rk3588, PLL_NPLL, "npll", mux_pll_p,
+ 0, RK3588_PLL_CON(120),
+ RK3588_MODE_CON0, 0, 15, 0, rk3588_pll_rates),
+ [ppll] = PLL(pll_rk3588_core, PLL_PPLL, "ppll", mux_pll_p,
+ CLK_IGNORE_UNUSED, RK3588_PMU_PLL_CON(128),
+ RK3588_MODE_CON0, 10, 15, 0, rk3588_pll_rates),
+};
+
+static struct rockchip_clk_branch rk3588_clk_branches[] __initdata = {
+ /*
+ * CRU Clock-Architecture
+ */
+ /* fixed */
+ FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
+
+ /* top */
+ COMPOSITE(CLK_50M_SRC, "clk_50m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(0), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 0, GFLAGS),
+ COMPOSITE(CLK_100M_SRC, "clk_100m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(0), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 1, GFLAGS),
+ COMPOSITE(CLK_150M_SRC, "clk_150m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(1), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 2, GFLAGS),
+ COMPOSITE(CLK_200M_SRC, "clk_200m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(1), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 3, GFLAGS),
+ COMPOSITE(CLK_250M_SRC, "clk_250m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(2), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 4, GFLAGS),
+ COMPOSITE(CLK_300M_SRC, "clk_300m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(2), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 5, GFLAGS),
+ COMPOSITE(CLK_350M_SRC, "clk_350m_src", gpll_spll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(3), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 6, GFLAGS),
+ COMPOSITE(CLK_400M_SRC, "clk_400m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(3), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 7, GFLAGS),
+ COMPOSITE_HALFDIV(CLK_450M_SRC, "clk_450m_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(4), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 8, GFLAGS),
+ COMPOSITE(CLK_500M_SRC, "clk_500m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(4), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 9, GFLAGS),
+ COMPOSITE(CLK_600M_SRC, "clk_600m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(5), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 10, GFLAGS),
+ COMPOSITE(CLK_650M_SRC, "clk_650m_src", gpll_lpll_p, 0,
+ RK3588_CLKSEL_CON(5), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 11, GFLAGS),
+ COMPOSITE(CLK_700M_SRC, "clk_700m_src", gpll_spll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(6), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 12, GFLAGS),
+ COMPOSITE(CLK_800M_SRC, "clk_800m_src", gpll_aupll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(6), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 13, GFLAGS),
+ COMPOSITE_HALFDIV(CLK_1000M_SRC, "clk_1000m_src", gpll_cpll_npll_v0pll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(7), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 14, GFLAGS),
+ COMPOSITE(CLK_1200M_SRC, "clk_1200m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(7), 12, 1, MFLAGS, 7, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 15, GFLAGS),
+ COMPOSITE_NODIV(ACLK_TOP_M300_ROOT, "aclk_top_m300_root", mux_300m_200m_100m_24m_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(9), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(1), 10, GFLAGS),
+ COMPOSITE_NODIV(ACLK_TOP_M500_ROOT, "aclk_top_m500_root", mux_500m_300m_100m_24m_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(9), 2, 2, MFLAGS,
+ RK3588_CLKGATE_CON(1), 11, GFLAGS),
+ COMPOSITE_NODIV(ACLK_TOP_M400_ROOT, "aclk_top_m400_root", mux_400m_200m_100m_24m_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(9), 4, 2, MFLAGS,
+ RK3588_CLKGATE_CON(1), 12, GFLAGS),
+ COMPOSITE_NODIV(ACLK_TOP_S200_ROOT, "aclk_top_s200_root", mux_200m_100m_50m_24m_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(9), 6, 2, MFLAGS,
+ RK3588_CLKGATE_CON(1), 13, GFLAGS),
+ COMPOSITE_NODIV(ACLK_TOP_S400_ROOT, "aclk_top_s400_root", mux_400m_200m_100m_24m_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(9), 8, 2, MFLAGS,
+ RK3588_CLKGATE_CON(1), 14, GFLAGS),
+ COMPOSITE(ACLK_TOP_ROOT, "aclk_top_root", gpll_cpll_aupll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(8), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(1), 0, GFLAGS),
+ COMPOSITE_NODIV(PCLK_TOP_ROOT, "pclk_top_root", mux_100m_50m_24m_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(8), 7, 2, MFLAGS,
+ RK3588_CLKGATE_CON(1), 1, GFLAGS),
+ COMPOSITE(ACLK_LOW_TOP_ROOT, "aclk_low_top_root", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(8), 14, 1, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(1), 2, GFLAGS),
+ COMPOSITE(CLK_MIPI_CAMARAOUT_M0, "clk_mipi_camaraout_m0", mux_24m_spll_gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(18), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3588_CLKGATE_CON(5), 9, GFLAGS),
+ COMPOSITE(CLK_MIPI_CAMARAOUT_M1, "clk_mipi_camaraout_m1", mux_24m_spll_gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(19), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3588_CLKGATE_CON(5), 10, GFLAGS),
+ COMPOSITE(CLK_MIPI_CAMARAOUT_M2, "clk_mipi_camaraout_m2", mux_24m_spll_gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(20), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3588_CLKGATE_CON(5), 11, GFLAGS),
+ COMPOSITE(CLK_MIPI_CAMARAOUT_M3, "clk_mipi_camaraout_m3", mux_24m_spll_gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(21), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3588_CLKGATE_CON(5), 12, GFLAGS),
+ COMPOSITE(CLK_MIPI_CAMARAOUT_M4, "clk_mipi_camaraout_m4", mux_24m_spll_gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(22), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3588_CLKGATE_CON(5), 13, GFLAGS),
+ COMPOSITE(MCLK_GMAC0_OUT, "mclk_gmac0_out", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(15), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3588_CLKGATE_CON(5), 3, GFLAGS),
+ COMPOSITE(REFCLKO25M_ETH0_OUT, "refclko25m_eth0_out", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(15), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ RK3588_CLKGATE_CON(5), 4, GFLAGS),
+ COMPOSITE(REFCLKO25M_ETH1_OUT, "refclko25m_eth1_out", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(16), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3588_CLKGATE_CON(5), 5, GFLAGS),
+ COMPOSITE(CLK_CIFOUT_OUT, "clk_cifout_out", gpll_cpll_24m_spll_p, 0,
+ RK3588_CLKSEL_CON(17), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3588_CLKGATE_CON(5), 6, GFLAGS),
+ GATE(PCLK_MIPI_DCPHY0, "pclk_mipi_dcphy0", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(3), 14, GFLAGS),
+ GATE(PCLK_MIPI_DCPHY1, "pclk_mipi_dcphy1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(4), 3, GFLAGS),
+ GATE(PCLK_CSIPHY0, "pclk_csiphy0", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(1), 6, GFLAGS),
+ GATE(PCLK_CSIPHY1, "pclk_csiphy1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(1), 8, GFLAGS),
+ GATE(PCLK_CRU, "pclk_cru", "pclk_top_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(5), 0, GFLAGS),
+
+ /* bigcore0 */
+ COMPOSITE_NODIV(PCLK_BIGCORE0_ROOT, "pclk_bigcore0_root", mux_100m_50m_24m_p,
+ CLK_IS_CRITICAL,
+ RK3588_BIGCORE0_CLKSEL_CON(2), 0, 2, MFLAGS,
+ RK3588_BIGCORE0_CLKGATE_CON(0), 14, GFLAGS),
+ GATE(PCLK_BIGCORE0_PVTM, "pclk_bigcore0_pvtm", "pclk_bigcore0_root", 0,
+ RK3588_BIGCORE0_CLKGATE_CON(1), 0, GFLAGS),
+ GATE(CLK_BIGCORE0_PVTM, "clk_bigcore0_pvtm", "xin24m", 0,
+ RK3588_BIGCORE0_CLKGATE_CON(0), 12, GFLAGS),
+ GATE(CLK_CORE_BIGCORE0_PVTM, "clk_core_bigcore0_pvtm", "armclk_b01", 0,
+ RK3588_BIGCORE0_CLKGATE_CON(0), 13, GFLAGS),
+
+ /* bigcore1 */
+ COMPOSITE_NODIV(PCLK_BIGCORE1_ROOT, "pclk_bigcore1_root", mux_100m_50m_24m_p,
+ CLK_IS_CRITICAL,
+ RK3588_BIGCORE1_CLKSEL_CON(2), 0, 2, MFLAGS,
+ RK3588_BIGCORE1_CLKGATE_CON(0), 14, GFLAGS),
+ GATE(PCLK_BIGCORE1_PVTM, "pclk_bigcore1_pvtm", "pclk_bigcore1_root", 0,
+ RK3588_BIGCORE1_CLKGATE_CON(1), 0, GFLAGS),
+ GATE(CLK_BIGCORE1_PVTM, "clk_bigcore1_pvtm", "xin24m", 0,
+ RK3588_BIGCORE1_CLKGATE_CON(0), 12, GFLAGS),
+ GATE(CLK_CORE_BIGCORE1_PVTM, "clk_core_bigcore1_pvtm", "armclk_b23", 0,
+ RK3588_BIGCORE1_CLKGATE_CON(0), 13, GFLAGS),
+
+ /* dsu */
+ COMPOSITE(0, "sclk_dsu", b0pll_b1pll_lpll_gpll_p, CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(0), 12, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_DSU_CLKGATE_CON(0), 4, GFLAGS),
+ COMPOSITE_NOMUX(0, "atclk_dsu", "sclk_dsu", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(3), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3588_DSU_CLKGATE_CON(1), 0, GFLAGS),
+ COMPOSITE_NOMUX(0, "gicclk_dsu", "sclk_dsu", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(3), 5, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3588_DSU_CLKGATE_CON(1), 1, GFLAGS),
+ COMPOSITE_NOMUX(0, "aclkmp_dsu", "sclk_dsu", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(1), 11, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3588_DSU_CLKGATE_CON(0), 12, GFLAGS),
+ COMPOSITE_NOMUX(0, "aclkm_dsu", "sclk_dsu", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(1), 1, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3588_DSU_CLKGATE_CON(0), 8, GFLAGS),
+ COMPOSITE_NOMUX(0, "aclks_dsu", "sclk_dsu", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(1), 6, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3588_DSU_CLKGATE_CON(0), 9, GFLAGS),
+ COMPOSITE_NOMUX(0, "periph_dsu", "sclk_dsu", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(2), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3588_DSU_CLKGATE_CON(0), 13, GFLAGS),
+ COMPOSITE_NOMUX(0, "cntclk_dsu", "periph_dsu", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(2), 5, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3588_DSU_CLKGATE_CON(0), 14, GFLAGS),
+ COMPOSITE_NOMUX(0, "tsclk_dsu", "periph_dsu", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(2), 10, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3588_DSU_CLKGATE_CON(0), 15, GFLAGS),
+ COMPOSITE_NODIV(PCLK_DSU_S_ROOT, "pclk_dsu_s_root", mux_100m_50m_24m_p, CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(4), 11, 2, MFLAGS,
+ RK3588_DSU_CLKGATE_CON(2), 2, GFLAGS),
+ COMPOSITE(PCLK_DSU_ROOT, "pclk_dsu_root", b0pll_b1pll_lpll_gpll_p, CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(4), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_DSU_CLKGATE_CON(1), 3, GFLAGS),
+ COMPOSITE_NODIV(PCLK_DSU_NS_ROOT, "pclk_dsu_ns_root", mux_100m_50m_24m_p, CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(4), 7, 2, MFLAGS,
+ RK3588_DSU_CLKGATE_CON(1), 4, GFLAGS),
+ GATE(PCLK_LITCORE_PVTM, "pclk_litcore_pvtm", "pclk_dsu_ns_root", 0,
+ RK3588_DSU_CLKGATE_CON(2), 6, GFLAGS),
+ GATE(PCLK_DBG, "pclk_dbg", "pclk_dsu_root", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKGATE_CON(1), 7, GFLAGS),
+ GATE(PCLK_DSU, "pclk_dsu", "pclk_dsu_root", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKGATE_CON(1), 6, GFLAGS),
+ GATE(PCLK_S_DAPLITE, "pclk_s_daplite", "pclk_dsu_ns_root", CLK_IGNORE_UNUSED,
+ RK3588_DSU_CLKGATE_CON(1), 8, GFLAGS),
+ GATE(PCLK_M_DAPLITE, "pclk_m_daplite", "pclk_dsu_root", CLK_IGNORE_UNUSED,
+ RK3588_DSU_CLKGATE_CON(1), 9, GFLAGS),
+ GATE(CLK_LITCORE_PVTM, "clk_litcore_pvtm", "xin24m", 0,
+ RK3588_DSU_CLKGATE_CON(2), 0, GFLAGS),
+ GATE(CLK_CORE_LITCORE_PVTM, "clk_core_litcore_pvtm", "armclk_l", 0,
+ RK3588_DSU_CLKGATE_CON(2), 1, GFLAGS),
+
+ /* audio */
+ COMPOSITE_NODIV(HCLK_AUDIO_ROOT, "hclk_audio_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(24), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(7), 0, GFLAGS),
+ COMPOSITE_NODIV(PCLK_AUDIO_ROOT, "pclk_audio_root", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(24), 2, 2, MFLAGS,
+ RK3588_CLKGATE_CON(7), 1, GFLAGS),
+ GATE(HCLK_I2S2_2CH, "hclk_i2s2_2ch", "hclk_audio_root", 0,
+ RK3588_CLKGATE_CON(7), 12, GFLAGS),
+ GATE(HCLK_I2S3_2CH, "hclk_i2s3_2ch", "hclk_audio_root", 0,
+ RK3588_CLKGATE_CON(7), 13, GFLAGS),
+ COMPOSITE(CLK_I2S2_2CH_SRC, "clk_i2s2_2ch_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(28), 9, 1, MFLAGS, 4, 5, DFLAGS,
+ RK3588_CLKGATE_CON(7), 14, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S2_2CH_FRAC, "clk_i2s2_2ch_frac", "clk_i2s2_2ch_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(29), 0,
+ RK3588_CLKGATE_CON(7), 15, GFLAGS,
+ &rk3588_i2s2_2ch_fracmux),
+ GATE(MCLK_I2S2_2CH, "mclk_i2s2_2ch", "clk_i2s2_2ch", 0,
+ RK3588_CLKGATE_CON(8), 0, GFLAGS),
+ MUX(I2S2_2CH_MCLKOUT, "i2s2_2ch_mclkout", i2s2_2ch_mclkout_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(30), 2, 1, MFLAGS),
+
+ COMPOSITE(CLK_I2S3_2CH_SRC, "clk_i2s3_2ch_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(30), 8, 1, MFLAGS, 3, 5, DFLAGS,
+ RK3588_CLKGATE_CON(8), 1, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S3_2CH_FRAC, "clk_i2s3_2ch_frac", "clk_i2s3_2ch_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(31), 0,
+ RK3588_CLKGATE_CON(8), 2, GFLAGS,
+ &rk3588_i2s3_2ch_fracmux),
+ GATE(MCLK_I2S3_2CH, "mclk_i2s3_2ch", "clk_i2s3_2ch", 0,
+ RK3588_CLKGATE_CON(8), 3, GFLAGS),
+ GATE(CLK_DAC_ACDCDIG, "clk_dac_acdcdig", "mclk_i2s3_2ch", 0,
+ RK3588_CLKGATE_CON(8), 4, GFLAGS),
+ MUX(I2S3_2CH_MCLKOUT, "i2s3_2ch_mclkout", i2s3_2ch_mclkout_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(32), 2, 1, MFLAGS),
+ GATE(PCLK_ACDCDIG, "pclk_acdcdig", "pclk_audio_root", 0,
+ RK3588_CLKGATE_CON(7), 11, GFLAGS),
+ GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_audio_root", 0,
+ RK3588_CLKGATE_CON(7), 4, GFLAGS),
+
+ COMPOSITE(CLK_I2S0_8CH_TX_SRC, "clk_i2s0_8ch_tx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(24), 9, 1, MFLAGS, 4, 5, DFLAGS,
+ RK3588_CLKGATE_CON(7), 5, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S0_8CH_TX_FRAC, "clk_i2s0_8ch_tx_frac", "clk_i2s0_8ch_tx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(25), 0,
+ RK3588_CLKGATE_CON(7), 6, GFLAGS,
+ &rk3588_i2s0_8ch_tx_fracmux),
+ GATE(MCLK_I2S0_8CH_TX, "mclk_i2s0_8ch_tx", "clk_i2s0_8ch_tx", 0,
+ RK3588_CLKGATE_CON(7), 7, GFLAGS),
+
+ COMPOSITE(CLK_I2S0_8CH_RX_SRC, "clk_i2s0_8ch_rx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(26), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(7), 8, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S0_8CH_RX_FRAC, "clk_i2s0_8ch_rx_frac", "clk_i2s0_8ch_rx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(27), 0,
+ RK3588_CLKGATE_CON(7), 9, GFLAGS,
+ &rk3588_i2s0_8ch_rx_fracmux),
+ GATE(MCLK_I2S0_8CH_RX, "mclk_i2s0_8ch_rx", "clk_i2s0_8ch_rx", 0,
+ RK3588_CLKGATE_CON(7), 10, GFLAGS),
+ MUX(I2S0_8CH_MCLKOUT, "i2s0_8ch_mclkout", i2s0_8ch_mclkout_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(28), 2, 2, MFLAGS),
+
+ GATE(HCLK_PDM1, "hclk_pdm1", "hclk_audio_root", 0,
+ RK3588_CLKGATE_CON(9), 6, GFLAGS),
+ COMPOSITE(MCLK_PDM1, "mclk_pdm1", gpll_cpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(36), 7, 2, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(9), 7, GFLAGS),
+
+ GATE(HCLK_SPDIF0, "hclk_spdif0", "hclk_audio_root", 0,
+ RK3588_CLKGATE_CON(8), 14, GFLAGS),
+ COMPOSITE(CLK_SPDIF0_SRC, "clk_spdif0_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(32), 8, 1, MFLAGS, 3, 5, DFLAGS,
+ RK3588_CLKGATE_CON(8), 15, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_SPDIF0_FRAC, "clk_spdif0_frac", "clk_spdif0_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(33), 0,
+ RK3588_CLKGATE_CON(9), 0, GFLAGS,
+ &rk3588_spdif0_fracmux),
+ GATE(MCLK_SPDIF0, "mclk_spdif0", "clk_spdif0", 0,
+ RK3588_CLKGATE_CON(9), 1, GFLAGS),
+
+ GATE(HCLK_SPDIF1, "hclk_spdif1", "hclk_audio_root", 0,
+ RK3588_CLKGATE_CON(9), 2, GFLAGS),
+ COMPOSITE(CLK_SPDIF1_SRC, "clk_spdif1_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(34), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(9), 3, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_SPDIF1_FRAC, "clk_spdif1_frac", "clk_spdif1_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(35), 0,
+ RK3588_CLKGATE_CON(9), 4, GFLAGS,
+ &rk3588_spdif1_fracmux),
+ GATE(MCLK_SPDIF1, "mclk_spdif1", "clk_spdif1", 0,
+ RK3588_CLKGATE_CON(9), 5, GFLAGS),
+
+ COMPOSITE(ACLK_AV1_ROOT, "aclk_av1_root", gpll_cpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(163), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(68), 0, GFLAGS),
+ COMPOSITE_NODIV(PCLK_AV1_ROOT, "pclk_av1_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(163), 7, 2, MFLAGS,
+ RK3588_CLKGATE_CON(68), 3, GFLAGS),
+
+ /* bus */
+ COMPOSITE(ACLK_BUS_ROOT, "aclk_bus_root", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(38), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(10), 0, GFLAGS),
+
+ GATE(PCLK_MAILBOX0, "pclk_mailbox0", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(16), 11, GFLAGS),
+ GATE(PCLK_MAILBOX1, "pclk_mailbox1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(16), 12, GFLAGS),
+ GATE(PCLK_MAILBOX2, "pclk_mailbox2", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(16), 13, GFLAGS),
+ GATE(PCLK_PMU2, "pclk_pmu2", "pclk_top_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(19), 3, GFLAGS),
+ GATE(PCLK_PMUCM0_INTMUX, "pclk_pmucm0_intmux", "pclk_top_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(19), 4, GFLAGS),
+ GATE(PCLK_DDRCM0_INTMUX, "pclk_ddrcm0_intmux", "pclk_top_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(19), 5, GFLAGS),
+
+ GATE(PCLK_PWM1, "pclk_pwm1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(15), 3, GFLAGS),
+ COMPOSITE_NODIV(CLK_PWM1, "clk_pwm1", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(59), 12, 2, MFLAGS,
+ RK3588_CLKGATE_CON(15), 4, GFLAGS),
+ GATE(CLK_PWM1_CAPTURE, "clk_pwm1_capture", "xin24m", 0,
+ RK3588_CLKGATE_CON(15), 5, GFLAGS),
+ GATE(PCLK_PWM2, "pclk_pwm2", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(15), 6, GFLAGS),
+ COMPOSITE_NODIV(CLK_PWM2, "clk_pwm2", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(59), 14, 2, MFLAGS,
+ RK3588_CLKGATE_CON(15), 7, GFLAGS),
+ GATE(CLK_PWM2_CAPTURE, "clk_pwm2_capture", "xin24m", 0,
+ RK3588_CLKGATE_CON(15), 8, GFLAGS),
+ GATE(PCLK_PWM3, "pclk_pwm3", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(15), 9, GFLAGS),
+ COMPOSITE_NODIV(CLK_PWM3, "clk_pwm3", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(60), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(15), 10, GFLAGS),
+ GATE(CLK_PWM3_CAPTURE, "clk_pwm3_capture", "xin24m", 0,
+ RK3588_CLKGATE_CON(15), 11, GFLAGS),
+
+ GATE(PCLK_BUSTIMER0, "pclk_bustimer0", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(15), 12, GFLAGS),
+ GATE(PCLK_BUSTIMER1, "pclk_bustimer1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(15), 13, GFLAGS),
+ COMPOSITE_NODIV(CLK_BUS_TIMER_ROOT, "clk_bus_timer_root", mux_24m_100m_p, 0,
+ RK3588_CLKSEL_CON(60), 2, 1, MFLAGS,
+ RK3588_CLKGATE_CON(15), 14, GFLAGS),
+ GATE(CLK_BUSTIMER0, "clk_bustimer0", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(15), 15, GFLAGS),
+ GATE(CLK_BUSTIMER1, "clk_bustimer1", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 0, GFLAGS),
+ GATE(CLK_BUSTIMER2, "clk_bustimer2", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 1, GFLAGS),
+ GATE(CLK_BUSTIMER3, "clk_bustimer3", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 2, GFLAGS),
+ GATE(CLK_BUSTIMER4, "clk_bustimer4", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 3, GFLAGS),
+ GATE(CLK_BUSTIMER5, "clk_bustimer5", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 4, GFLAGS),
+ GATE(CLK_BUSTIMER6, "clk_bustimer6", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 5, GFLAGS),
+ GATE(CLK_BUSTIMER7, "clk_bustimer7", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 6, GFLAGS),
+ GATE(CLK_BUSTIMER8, "clk_bustimer8", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 7, GFLAGS),
+ GATE(CLK_BUSTIMER9, "clk_bustimer9", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 8, GFLAGS),
+ GATE(CLK_BUSTIMER10, "clk_bustimer10", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 9, GFLAGS),
+ GATE(CLK_BUSTIMER11, "clk_bustimer11", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 10, GFLAGS),
+
+ GATE(PCLK_WDT0, "pclk_wdt0", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(15), 0, GFLAGS),
+ GATE(TCLK_WDT0, "tclk_wdt0", "xin24m", 0,
+ RK3588_CLKGATE_CON(15), 1, GFLAGS),
+
+ GATE(PCLK_CAN0, "pclk_can0", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(11), 8, GFLAGS),
+ COMPOSITE(CLK_CAN0, "clk_can0", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(39), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(11), 9, GFLAGS),
+ GATE(PCLK_CAN1, "pclk_can1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(11), 10, GFLAGS),
+ COMPOSITE(CLK_CAN1, "clk_can1", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(39), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(11), 11, GFLAGS),
+ GATE(PCLK_CAN2, "pclk_can2", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(11), 12, GFLAGS),
+ COMPOSITE(CLK_CAN2, "clk_can2", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(40), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(11), 13, GFLAGS),
+
+ GATE(ACLK_DECOM, "aclk_decom", "aclk_bus_root", 0,
+ RK3588_CLKGATE_CON(17), 6, GFLAGS),
+ GATE(PCLK_DECOM, "pclk_decom", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(17), 7, GFLAGS),
+ COMPOSITE(DCLK_DECOM, "dclk_decom", gpll_spll_p, 0,
+ RK3588_CLKSEL_CON(62), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(17), 8, GFLAGS),
+ GATE(ACLK_DMAC0, "aclk_dmac0", "aclk_bus_root", 0,
+ RK3588_CLKGATE_CON(10), 5, GFLAGS),
+ GATE(ACLK_DMAC1, "aclk_dmac1", "aclk_bus_root", 0,
+ RK3588_CLKGATE_CON(10), 6, GFLAGS),
+ GATE(ACLK_DMAC2, "aclk_dmac2", "aclk_bus_root", 0,
+ RK3588_CLKGATE_CON(10), 7, GFLAGS),
+ GATE(ACLK_GIC, "aclk_gic", "aclk_bus_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(10), 3, GFLAGS),
+
+ GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(16), 14, GFLAGS),
+ COMPOSITE(DBCLK_GPIO1, "dbclk_gpio1", mux_24m_32k_p, 0,
+ RK3588_CLKSEL_CON(60), 8, 1, MFLAGS, 3, 5, DFLAGS,
+ RK3588_CLKGATE_CON(16), 15, GFLAGS),
+ GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(17), 0, GFLAGS),
+ COMPOSITE(DBCLK_GPIO2, "dbclk_gpio2", mux_24m_32k_p, 0,
+ RK3588_CLKSEL_CON(60), 14, 1, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(17), 1, GFLAGS),
+ GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(17), 2, GFLAGS),
+ COMPOSITE(DBCLK_GPIO3, "dbclk_gpio3", mux_24m_32k_p, 0,
+ RK3588_CLKSEL_CON(61), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(17), 3, GFLAGS),
+ GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(17), 4, GFLAGS),
+ COMPOSITE(DBCLK_GPIO4, "dbclk_gpio4", mux_24m_32k_p, 0,
+ RK3588_CLKSEL_CON(61), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(17), 5, GFLAGS),
+
+ GATE(PCLK_I2C1, "pclk_i2c1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(10), 8, GFLAGS),
+ GATE(PCLK_I2C2, "pclk_i2c2", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(10), 9, GFLAGS),
+ GATE(PCLK_I2C3, "pclk_i2c3", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(10), 10, GFLAGS),
+ GATE(PCLK_I2C4, "pclk_i2c4", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(10), 11, GFLAGS),
+ GATE(PCLK_I2C5, "pclk_i2c5", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(10), 12, GFLAGS),
+ GATE(PCLK_I2C6, "pclk_i2c6", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(10), 13, GFLAGS),
+ GATE(PCLK_I2C7, "pclk_i2c7", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(10), 14, GFLAGS),
+ GATE(PCLK_I2C8, "pclk_i2c8", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(10), 15, GFLAGS),
+ COMPOSITE_NODIV(CLK_I2C1, "clk_i2c1", mux_200m_100m_p, 0,
+ RK3588_CLKSEL_CON(38), 6, 1, MFLAGS,
+ RK3588_CLKGATE_CON(11), 0, GFLAGS),
+ COMPOSITE_NODIV(CLK_I2C2, "clk_i2c2", mux_200m_100m_p, 0,
+ RK3588_CLKSEL_CON(38), 7, 1, MFLAGS,
+ RK3588_CLKGATE_CON(11), 1, GFLAGS),
+ COMPOSITE_NODIV(CLK_I2C3, "clk_i2c3", mux_200m_100m_p, 0,
+ RK3588_CLKSEL_CON(38), 8, 1, MFLAGS,
+ RK3588_CLKGATE_CON(11), 2, GFLAGS),
+ COMPOSITE_NODIV(CLK_I2C4, "clk_i2c4", mux_200m_100m_p, 0,
+ RK3588_CLKSEL_CON(38), 9, 1, MFLAGS,
+ RK3588_CLKGATE_CON(11), 3, GFLAGS),
+ COMPOSITE_NODIV(CLK_I2C5, "clk_i2c5", mux_200m_100m_p, 0,
+ RK3588_CLKSEL_CON(38), 10, 1, MFLAGS,
+ RK3588_CLKGATE_CON(11), 4, GFLAGS),
+ COMPOSITE_NODIV(CLK_I2C6, "clk_i2c6", mux_200m_100m_p, 0,
+ RK3588_CLKSEL_CON(38), 11, 1, MFLAGS,
+ RK3588_CLKGATE_CON(11), 5, GFLAGS),
+ COMPOSITE_NODIV(CLK_I2C7, "clk_i2c7", mux_200m_100m_p, 0,
+ RK3588_CLKSEL_CON(38), 12, 1, MFLAGS,
+ RK3588_CLKGATE_CON(11), 6, GFLAGS),
+ COMPOSITE_NODIV(CLK_I2C8, "clk_i2c8", mux_200m_100m_p, 0,
+ RK3588_CLKSEL_CON(38), 13, 1, MFLAGS,
+ RK3588_CLKGATE_CON(11), 7, GFLAGS),
+
+ GATE(PCLK_OTPC_NS, "pclk_otpc_ns", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(18), 9, GFLAGS),
+ GATE(CLK_OTPC_NS, "clk_otpc_ns", "xin24m", 0,
+ RK3588_CLKGATE_CON(18), 10, GFLAGS),
+ GATE(CLK_OTPC_ARB, "clk_otpc_arb", "xin24m", 0,
+ RK3588_CLKGATE_CON(18), 11, GFLAGS),
+ GATE(CLK_OTP_PHY_G, "clk_otp_phy_g", "xin24m", 0,
+ RK3588_CLKGATE_CON(18), 13, GFLAGS),
+ GATE(CLK_OTPC_AUTO_RD_G, "clk_otpc_auto_rd_g", "xin24m", 0,
+ RK3588_CLKGATE_CON(18), 12, GFLAGS),
+
+ GATE(PCLK_SARADC, "pclk_saradc", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(11), 14, GFLAGS),
+ COMPOSITE(CLK_SARADC, "clk_saradc", gpll_24m_p, 0,
+ RK3588_CLKSEL_CON(40), 14, 1, MFLAGS, 6, 8, DFLAGS,
+ RK3588_CLKGATE_CON(11), 15, GFLAGS),
+
+ GATE(PCLK_SPI0, "pclk_spi0", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(14), 6, GFLAGS),
+ GATE(PCLK_SPI1, "pclk_spi1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(14), 7, GFLAGS),
+ GATE(PCLK_SPI2, "pclk_spi2", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(14), 8, GFLAGS),
+ GATE(PCLK_SPI3, "pclk_spi3", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(14), 9, GFLAGS),
+ GATE(PCLK_SPI4, "pclk_spi4", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(14), 10, GFLAGS),
+ COMPOSITE_NODIV(CLK_SPI0, "clk_spi0", mux_200m_150m_24m_p, 0,
+ RK3588_CLKSEL_CON(59), 2, 2, MFLAGS,
+ RK3588_CLKGATE_CON(14), 11, GFLAGS),
+ COMPOSITE_NODIV(CLK_SPI1, "clk_spi1", mux_200m_150m_24m_p, 0,
+ RK3588_CLKSEL_CON(59), 4, 2, MFLAGS,
+ RK3588_CLKGATE_CON(14), 12, GFLAGS),
+ COMPOSITE_NODIV(CLK_SPI2, "clk_spi2", mux_200m_150m_24m_p, 0,
+ RK3588_CLKSEL_CON(59), 6, 2, MFLAGS,
+ RK3588_CLKGATE_CON(14), 13, GFLAGS),
+ COMPOSITE_NODIV(CLK_SPI3, "clk_spi3", mux_200m_150m_24m_p, 0,
+ RK3588_CLKSEL_CON(59), 8, 2, MFLAGS,
+ RK3588_CLKGATE_CON(14), 14, GFLAGS),
+ COMPOSITE_NODIV(CLK_SPI4, "clk_spi4", mux_200m_150m_24m_p, 0,
+ RK3588_CLKSEL_CON(59), 10, 2, MFLAGS,
+ RK3588_CLKGATE_CON(14), 15, GFLAGS),
+
+ GATE(ACLK_SPINLOCK, "aclk_spinlock", "aclk_bus_root", CLK_IGNORE_UNUSED,
+ RK3588_CLKGATE_CON(18), 6, GFLAGS),
+ GATE(PCLK_TSADC, "pclk_tsadc", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 0, GFLAGS),
+ COMPOSITE(CLK_TSADC, "clk_tsadc", gpll_24m_p, 0,
+ RK3588_CLKSEL_CON(41), 8, 1, MFLAGS, 0, 8, DFLAGS,
+ RK3588_CLKGATE_CON(12), 1, GFLAGS),
+
+ GATE(PCLK_UART1, "pclk_uart1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 2, GFLAGS),
+ GATE(PCLK_UART2, "pclk_uart2", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 3, GFLAGS),
+ GATE(PCLK_UART3, "pclk_uart3", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 4, GFLAGS),
+ GATE(PCLK_UART4, "pclk_uart4", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 5, GFLAGS),
+ GATE(PCLK_UART5, "pclk_uart5", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 6, GFLAGS),
+ GATE(PCLK_UART6, "pclk_uart6", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 7, GFLAGS),
+ GATE(PCLK_UART7, "pclk_uart7", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 8, GFLAGS),
+ GATE(PCLK_UART8, "pclk_uart8", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 9, GFLAGS),
+ GATE(PCLK_UART9, "pclk_uart9", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 10, GFLAGS),
+
+ COMPOSITE(CLK_UART1_SRC, "clk_uart1_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(41), 14, 1, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(12), 11, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART1_FRAC, "clk_uart1_frac", "clk_uart1_src", CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(42), 0,
+ RK3588_CLKGATE_CON(12), 12, GFLAGS,
+ &rk3588_uart1_fracmux),
+ GATE(SCLK_UART1, "sclk_uart1", "clk_uart1", 0,
+ RK3588_CLKGATE_CON(12), 13, GFLAGS),
+ COMPOSITE(CLK_UART2_SRC, "clk_uart2_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(43), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(12), 14, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART2_FRAC, "clk_uart2_frac", "clk_uart2_src", CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(44), 0,
+ RK3588_CLKGATE_CON(12), 15, GFLAGS,
+ &rk3588_uart2_fracmux),
+ GATE(SCLK_UART2, "sclk_uart2", "clk_uart2", 0,
+ RK3588_CLKGATE_CON(13), 0, GFLAGS),
+ COMPOSITE(CLK_UART3_SRC, "clk_uart3_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(45), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(13), 1, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART3_FRAC, "clk_uart3_frac", "clk_uart3_src", CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(46), 0,
+ RK3588_CLKGATE_CON(13), 2, GFLAGS,
+ &rk3588_uart3_fracmux),
+ GATE(SCLK_UART3, "sclk_uart3", "clk_uart3", 0,
+ RK3588_CLKGATE_CON(13), 3, GFLAGS),
+ COMPOSITE(CLK_UART4_SRC, "clk_uart4_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(47), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(13), 4, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART4_FRAC, "clk_uart4_frac", "clk_uart4_src", CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(48), 0,
+ RK3588_CLKGATE_CON(13), 5, GFLAGS,
+ &rk3588_uart4_fracmux),
+ GATE(SCLK_UART4, "sclk_uart4", "clk_uart4", 0,
+ RK3588_CLKGATE_CON(13), 6, GFLAGS),
+ COMPOSITE(CLK_UART5_SRC, "clk_uart5_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(49), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(13), 7, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART5_FRAC, "clk_uart5_frac", "clk_uart5_src", CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(50), 0,
+ RK3588_CLKGATE_CON(13), 8, GFLAGS,
+ &rk3588_uart5_fracmux),
+ GATE(SCLK_UART5, "sclk_uart5", "clk_uart5", 0,
+ RK3588_CLKGATE_CON(13), 9, GFLAGS),
+ COMPOSITE(CLK_UART6_SRC, "clk_uart6_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(51), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(13), 10, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART6_FRAC, "clk_uart6_frac", "clk_uart6_src", CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(52), 0,
+ RK3588_CLKGATE_CON(13), 11, GFLAGS,
+ &rk3588_uart6_fracmux),
+ GATE(SCLK_UART6, "sclk_uart6", "clk_uart6", 0,
+ RK3588_CLKGATE_CON(13), 12, GFLAGS),
+ COMPOSITE(CLK_UART7_SRC, "clk_uart7_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(53), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(13), 13, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART7_FRAC, "clk_uart7_frac", "clk_uart7_src", CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(54), 0,
+ RK3588_CLKGATE_CON(13), 14, GFLAGS,
+ &rk3588_uart7_fracmux),
+ GATE(SCLK_UART7, "sclk_uart7", "clk_uart7", 0,
+ RK3588_CLKGATE_CON(13), 15, GFLAGS),
+ COMPOSITE(CLK_UART8_SRC, "clk_uart8_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(55), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(14), 0, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART8_FRAC, "clk_uart8_frac", "clk_uart8_src", CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(56), 0,
+ RK3588_CLKGATE_CON(14), 1, GFLAGS,
+ &rk3588_uart8_fracmux),
+ GATE(SCLK_UART8, "sclk_uart8", "clk_uart8", 0,
+ RK3588_CLKGATE_CON(14), 2, GFLAGS),
+ COMPOSITE(CLK_UART9_SRC, "clk_uart9_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(57), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(14), 3, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART9_FRAC, "clk_uart9_frac", "clk_uart9_src", CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(58), 0,
+ RK3588_CLKGATE_CON(14), 4, GFLAGS,
+ &rk3588_uart9_fracmux),
+ GATE(SCLK_UART9, "sclk_uart9", "clk_uart9", 0,
+ RK3588_CLKGATE_CON(14), 5, GFLAGS),
+
+ /* center */
+ COMPOSITE_NODIV(ACLK_CENTER_ROOT, "aclk_center_root", mux_700m_400m_200m_24m_p,
+ CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(165), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(69), 0, GFLAGS),
+ COMPOSITE_NODIV(ACLK_CENTER_LOW_ROOT, "aclk_center_low_root", mux_500m_250m_100m_24m_p,
+ CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(165), 2, 2, MFLAGS,
+ RK3588_CLKGATE_CON(69), 1, GFLAGS),
+ COMPOSITE_NODIV(HCLK_CENTER_ROOT, "hclk_center_root", mux_400m_200m_100m_24m_p,
+ CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(165), 4, 2, MFLAGS,
+ RK3588_CLKGATE_CON(69), 2, GFLAGS),
+ COMPOSITE_NODIV(PCLK_CENTER_ROOT, "pclk_center_root", mux_200m_100m_50m_24m_p,
+ CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(165), 6, 2, MFLAGS | CLK_MUX_READ_ONLY,
+ RK3588_CLKGATE_CON(69), 3, GFLAGS),
+ GATE(ACLK_DMA2DDR, "aclk_dma2ddr", "aclk_center_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(69), 5, GFLAGS),
+ GATE(ACLK_DDR_SHAREMEM, "aclk_ddr_sharemem", "aclk_center_low_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(69), 6, GFLAGS),
+ COMPOSITE_NODIV(ACLK_CENTER_S200_ROOT, "aclk_center_s200_root", mux_200m_100m_50m_24m_p,
+ CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(165), 8, 2, MFLAGS,
+ RK3588_CLKGATE_CON(69), 8, GFLAGS),
+ COMPOSITE_NODIV(ACLK_CENTER_S400_ROOT, "aclk_center_s400_root", mux_400m_200m_100m_24m_p,
+ CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(165), 10, 2, MFLAGS,
+ RK3588_CLKGATE_CON(69), 9, GFLAGS),
+ GATE(FCLK_DDR_CM0_CORE, "fclk_ddr_cm0_core", "hclk_center_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(69), 14, GFLAGS),
+ COMPOSITE_NODIV(CLK_DDR_TIMER_ROOT, "clk_ddr_timer_root", mux_24m_100m_p, CLK_IGNORE_UNUSED,
+ RK3588_CLKSEL_CON(165), 12, 1, MFLAGS,
+ RK3588_CLKGATE_CON(69), 15, GFLAGS),
+ GATE(CLK_DDR_TIMER0, "clk_ddr_timer0", "clk_ddr_timer_root", 0,
+ RK3588_CLKGATE_CON(70), 0, GFLAGS),
+ GATE(CLK_DDR_TIMER1, "clk_ddr_timer1", "clk_ddr_timer_root", 0,
+ RK3588_CLKGATE_CON(70), 1, GFLAGS),
+ GATE(TCLK_WDT_DDR, "tclk_wdt_ddr", "xin24m", 0,
+ RK3588_CLKGATE_CON(70), 2, GFLAGS),
+ COMPOSITE(CLK_DDR_CM0_RTC, "clk_ddr_cm0_rtc", mux_24m_32k_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(166), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(70), 4, GFLAGS),
+ GATE(PCLK_WDT, "pclk_wdt", "pclk_center_root", 0,
+ RK3588_CLKGATE_CON(70), 7, GFLAGS),
+ GATE(PCLK_TIMER, "pclk_timer", "pclk_center_root", 0,
+ RK3588_CLKGATE_CON(70), 8, GFLAGS),
+ GATE(PCLK_DMA2DDR, "pclk_dma2ddr", "pclk_center_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(70), 9, GFLAGS),
+ GATE(PCLK_SHAREMEM, "pclk_sharemem", "pclk_center_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(70), 10, GFLAGS),
+
+ /* gpu */
+ COMPOSITE(CLK_GPU_SRC, "clk_gpu_src", gpll_cpll_aupll_npll_spll_p, 0,
+ RK3588_CLKSEL_CON(158), 5, 3, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(66), 1, GFLAGS),
+ GATE(CLK_GPU, "clk_gpu", "clk_gpu_src", 0,
+ RK3588_CLKGATE_CON(66), 4, GFLAGS),
+ GATE(CLK_GPU_COREGROUP, "clk_gpu_coregroup", "clk_gpu_src", 0,
+ RK3588_CLKGATE_CON(66), 6, GFLAGS),
+ COMPOSITE_NOMUX(CLK_GPU_STACKS, "clk_gpu_stacks", "clk_gpu_src", 0,
+ RK3588_CLKSEL_CON(159), 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(66), 7, GFLAGS),
+ GATE(CLK_GPU_PVTM, "clk_gpu_pvtm", "xin24m", 0,
+ RK3588_CLKGATE_CON(67), 0, GFLAGS),
+ GATE(CLK_CORE_GPU_PVTM, "clk_core_gpu_pvtm", "clk_gpu_src", 0,
+ RK3588_CLKGATE_CON(67), 1, GFLAGS),
+
+ /* isp1 */
+ COMPOSITE(ACLK_ISP1_ROOT, "aclk_isp1_root", gpll_cpll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(67), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(26), 0, GFLAGS),
+ COMPOSITE_NODIV(HCLK_ISP1_ROOT, "hclk_isp1_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(67), 7, 2, MFLAGS,
+ RK3588_CLKGATE_CON(26), 1, GFLAGS),
+ COMPOSITE(CLK_ISP1_CORE, "clk_isp1_core", gpll_cpll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(67), 14, 2, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(26), 2, GFLAGS),
+ GATE(CLK_ISP1_CORE_MARVIN, "clk_isp1_core_marvin", "clk_isp1_core", 0,
+ RK3588_CLKGATE_CON(26), 3, GFLAGS),
+ GATE(CLK_ISP1_CORE_VICAP, "clk_isp1_core_vicap", "clk_isp1_core", 0,
+ RK3588_CLKGATE_CON(26), 4, GFLAGS),
+
+ /* npu */
+ COMPOSITE_NODIV(HCLK_NPU_ROOT, "hclk_npu_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(73), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(29), 0, GFLAGS),
+ COMPOSITE(CLK_NPU_DSU0, "clk_npu_dsu0", gpll_cpll_aupll_npll_spll_p, 0,
+ RK3588_CLKSEL_CON(73), 7, 3, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(29), 1, GFLAGS),
+ COMPOSITE_NODIV(PCLK_NPU_ROOT, "pclk_npu_root", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(74), 1, 2, MFLAGS,
+ RK3588_CLKGATE_CON(29), 4, GFLAGS),
+ GATE(ACLK_NPU1, "aclk_npu1", "clk_npu_dsu0", 0,
+ RK3588_CLKGATE_CON(27), 0, GFLAGS),
+ GATE(HCLK_NPU1, "hclk_npu1", "hclk_npu_root", 0,
+ RK3588_CLKGATE_CON(27), 2, GFLAGS),
+ GATE(ACLK_NPU2, "aclk_npu2", "clk_npu_dsu0", 0,
+ RK3588_CLKGATE_CON(28), 0, GFLAGS),
+ GATE(HCLK_NPU2, "hclk_npu2", "hclk_npu_root", 0,
+ RK3588_CLKGATE_CON(28), 2, GFLAGS),
+ COMPOSITE_NODIV(HCLK_NPU_CM0_ROOT, "hclk_npu_cm0_root", mux_400m_200m_100m_24m_p, 0,
+ RK3588_CLKSEL_CON(74), 5, 2, MFLAGS,
+ RK3588_CLKGATE_CON(30), 1, GFLAGS),
+ GATE(FCLK_NPU_CM0_CORE, "fclk_npu_cm0_core", "hclk_npu_cm0_root", 0,
+ RK3588_CLKGATE_CON(30), 3, GFLAGS),
+ COMPOSITE(CLK_NPU_CM0_RTC, "clk_npu_cm0_rtc", mux_24m_32k_p, 0,
+ RK3588_CLKSEL_CON(74), 12, 1, MFLAGS, 7, 5, DFLAGS,
+ RK3588_CLKGATE_CON(30), 5, GFLAGS),
+ GATE(PCLK_NPU_PVTM, "pclk_npu_pvtm", "pclk_npu_root", 0,
+ RK3588_CLKGATE_CON(29), 12, GFLAGS),
+ GATE(PCLK_NPU_GRF, "pclk_npu_grf", "pclk_npu_root", CLK_IGNORE_UNUSED,
+ RK3588_CLKGATE_CON(29), 13, GFLAGS),
+ GATE(CLK_NPU_PVTM, "clk_npu_pvtm", "xin24m", 0,
+ RK3588_CLKGATE_CON(29), 14, GFLAGS),
+ GATE(CLK_CORE_NPU_PVTM, "clk_core_npu_pvtm", "clk_npu_dsu0", 0,
+ RK3588_CLKGATE_CON(29), 15, GFLAGS),
+ GATE(ACLK_NPU0, "aclk_npu0", "clk_npu_dsu0", 0,
+ RK3588_CLKGATE_CON(30), 6, GFLAGS),
+ GATE(HCLK_NPU0, "hclk_npu0", "hclk_npu_root", 0,
+ RK3588_CLKGATE_CON(30), 8, GFLAGS),
+ GATE(PCLK_NPU_TIMER, "pclk_npu_timer", "pclk_npu_root", 0,
+ RK3588_CLKGATE_CON(29), 6, GFLAGS),
+ COMPOSITE_NODIV(CLK_NPUTIMER_ROOT, "clk_nputimer_root", mux_24m_100m_p, 0,
+ RK3588_CLKSEL_CON(74), 3, 1, MFLAGS,
+ RK3588_CLKGATE_CON(29), 7, GFLAGS),
+ GATE(CLK_NPUTIMER0, "clk_nputimer0", "clk_nputimer_root", 0,
+ RK3588_CLKGATE_CON(29), 8, GFLAGS),
+ GATE(CLK_NPUTIMER1, "clk_nputimer1", "clk_nputimer_root", 0,
+ RK3588_CLKGATE_CON(29), 9, GFLAGS),
+ GATE(PCLK_NPU_WDT, "pclk_npu_wdt", "pclk_npu_root", 0,
+ RK3588_CLKGATE_CON(29), 10, GFLAGS),
+ GATE(TCLK_NPU_WDT, "tclk_npu_wdt", "xin24m", 0,
+ RK3588_CLKGATE_CON(29), 11, GFLAGS),
+
+ /* nvm */
+ COMPOSITE_NODIV(HCLK_NVM_ROOT, "hclk_nvm_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(77), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(31), 0, GFLAGS),
+ COMPOSITE(ACLK_NVM_ROOT, "aclk_nvm_root", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(77), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(31), 1, GFLAGS),
+ GATE(ACLK_EMMC, "aclk_emmc", "aclk_nvm_root", 0,
+ RK3588_CLKGATE_CON(31), 5, GFLAGS),
+ COMPOSITE(CCLK_EMMC, "cclk_emmc", gpll_cpll_24m_p, 0,
+ RK3588_CLKSEL_CON(77), 14, 2, MFLAGS, 8, 6, DFLAGS,
+ RK3588_CLKGATE_CON(31), 6, GFLAGS),
+ COMPOSITE(BCLK_EMMC, "bclk_emmc", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(78), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(31), 7, GFLAGS),
+ GATE(TMCLK_EMMC, "tmclk_emmc", "xin24m", 0,
+ RK3588_CLKGATE_CON(31), 8, GFLAGS),
+
+ COMPOSITE(SCLK_SFC, "sclk_sfc", gpll_cpll_24m_p, 0,
+ RK3588_CLKSEL_CON(78), 12, 2, MFLAGS, 6, 6, DFLAGS,
+ RK3588_CLKGATE_CON(31), 9, GFLAGS),
+
+ /* php */
+ COMPOSITE(CLK_GMAC0_PTP_REF, "clk_gmac0_ptp_ref", clk_gmac0_ptp_ref_p, 0,
+ RK3588_CLKSEL_CON(81), 6, 1, MFLAGS, 0, 6, DFLAGS,
+ RK3588_CLKGATE_CON(34), 10, GFLAGS),
+ COMPOSITE(CLK_GMAC1_PTP_REF, "clk_gmac1_ptp_ref", clk_gmac1_ptp_ref_p, 0,
+ RK3588_CLKSEL_CON(81), 13, 1, MFLAGS, 7, 6, DFLAGS,
+ RK3588_CLKGATE_CON(34), 11, GFLAGS),
+ COMPOSITE(CLK_GMAC_125M, "clk_gmac_125m", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(83), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ RK3588_CLKGATE_CON(35), 5, GFLAGS),
+ COMPOSITE(CLK_GMAC_50M, "clk_gmac_50m", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(84), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3588_CLKGATE_CON(35), 6, GFLAGS),
+
+ COMPOSITE(ACLK_PCIE_ROOT, "aclk_pcie_root", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(80), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(32), 6, GFLAGS),
+ COMPOSITE(ACLK_PHP_ROOT, "aclk_php_root", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(80), 13, 1, MFLAGS, 8, 5, DFLAGS,
+ RK3588_CLKGATE_CON(32), 7, GFLAGS),
+ COMPOSITE_NODIV(PCLK_PHP_ROOT, "pclk_php_root", mux_150m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(80), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(32), 0, GFLAGS),
+ GATE(ACLK_PHP_GIC_ITS, "aclk_php_gic_its", "aclk_pcie_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(34), 6, GFLAGS),
+ GATE(ACLK_PCIE_BRIDGE, "aclk_pcie_bridge", "aclk_pcie_root", 0,
+ RK3588_CLKGATE_CON(32), 8, GFLAGS),
+ GATE(ACLK_MMU_PCIE, "aclk_mmu_pcie", "aclk_pcie_bridge", 0,
+ RK3588_CLKGATE_CON(34), 7, GFLAGS),
+ GATE(ACLK_MMU_PHP, "aclk_mmu_php", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(34), 8, GFLAGS),
+ GATE(ACLK_PCIE_4L_DBI, "aclk_pcie_4l_dbi", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(32), 13, GFLAGS),
+ GATE(ACLK_PCIE_2L_DBI, "aclk_pcie_2l_dbi", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(32), 14, GFLAGS),
+ GATE(ACLK_PCIE_1L0_DBI, "aclk_pcie_1l0_dbi", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(32), 15, GFLAGS),
+ GATE(ACLK_PCIE_1L1_DBI, "aclk_pcie_1l1_dbi", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 0, GFLAGS),
+ GATE(ACLK_PCIE_1L2_DBI, "aclk_pcie_1l2_dbi", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 1, GFLAGS),
+ GATE(ACLK_PCIE_4L_MSTR, "aclk_pcie_4l_mstr", "aclk_mmu_pcie", 0,
+ RK3588_CLKGATE_CON(33), 2, GFLAGS),
+ GATE(ACLK_PCIE_2L_MSTR, "aclk_pcie_2l_mstr", "aclk_mmu_pcie", 0,
+ RK3588_CLKGATE_CON(33), 3, GFLAGS),
+ GATE(ACLK_PCIE_1L0_MSTR, "aclk_pcie_1l0_mstr", "aclk_mmu_pcie", 0,
+ RK3588_CLKGATE_CON(33), 4, GFLAGS),
+ GATE(ACLK_PCIE_1L1_MSTR, "aclk_pcie_1l1_mstr", "aclk_mmu_pcie", 0,
+ RK3588_CLKGATE_CON(33), 5, GFLAGS),
+ GATE(ACLK_PCIE_1L2_MSTR, "aclk_pcie_1l2_mstr", "aclk_mmu_pcie", 0,
+ RK3588_CLKGATE_CON(33), 6, GFLAGS),
+ GATE(ACLK_PCIE_4L_SLV, "aclk_pcie_4l_slv", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 7, GFLAGS),
+ GATE(ACLK_PCIE_2L_SLV, "aclk_pcie_2l_slv", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 8, GFLAGS),
+ GATE(ACLK_PCIE_1L0_SLV, "aclk_pcie_1l0_slv", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 9, GFLAGS),
+ GATE(ACLK_PCIE_1L1_SLV, "aclk_pcie_1l1_slv", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 10, GFLAGS),
+ GATE(ACLK_PCIE_1L2_SLV, "aclk_pcie_1l2_slv", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 11, GFLAGS),
+ GATE(PCLK_PCIE_4L, "pclk_pcie_4l", "pclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 12, GFLAGS),
+ GATE(PCLK_PCIE_2L, "pclk_pcie_2l", "pclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 13, GFLAGS),
+ GATE(PCLK_PCIE_1L0, "pclk_pcie_1l0", "pclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 14, GFLAGS),
+ GATE(PCLK_PCIE_1L1, "pclk_pcie_1l1", "pclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 15, GFLAGS),
+ GATE(PCLK_PCIE_1L2, "pclk_pcie_1l2", "pclk_php_root", 0,
+ RK3588_CLKGATE_CON(34), 0, GFLAGS),
+ GATE(CLK_PCIE_AUX0, "clk_pcie_aux0", "xin24m", 0,
+ RK3588_CLKGATE_CON(34), 1, GFLAGS),
+ GATE(CLK_PCIE_AUX1, "clk_pcie_aux1", "xin24m", 0,
+ RK3588_CLKGATE_CON(34), 2, GFLAGS),
+ GATE(CLK_PCIE_AUX2, "clk_pcie_aux2", "xin24m", 0,
+ RK3588_CLKGATE_CON(34), 3, GFLAGS),
+ GATE(CLK_PCIE_AUX3, "clk_pcie_aux3", "xin24m", 0,
+ RK3588_CLKGATE_CON(34), 4, GFLAGS),
+ GATE(CLK_PCIE_AUX4, "clk_pcie_aux4", "xin24m", 0,
+ RK3588_CLKGATE_CON(34), 5, GFLAGS),
+ GATE(CLK_PIPEPHY0_REF, "clk_pipephy0_ref", "xin24m", 0,
+ RK3588_CLKGATE_CON(37), 0, GFLAGS),
+ GATE(CLK_PIPEPHY1_REF, "clk_pipephy1_ref", "xin24m", 0,
+ RK3588_CLKGATE_CON(37), 1, GFLAGS),
+ GATE(CLK_PIPEPHY2_REF, "clk_pipephy2_ref", "xin24m", 0,
+ RK3588_CLKGATE_CON(37), 2, GFLAGS),
+ GATE(PCLK_GMAC0, "pclk_gmac0", "pclk_php_root", 0,
+ RK3588_CLKGATE_CON(32), 3, GFLAGS),
+ GATE(PCLK_GMAC1, "pclk_gmac1", "pclk_php_root", 0,
+ RK3588_CLKGATE_CON(32), 4, GFLAGS),
+ GATE(ACLK_GMAC0, "aclk_gmac0", "aclk_mmu_php", 0,
+ RK3588_CLKGATE_CON(32), 10, GFLAGS),
+ GATE(ACLK_GMAC1, "aclk_gmac1", "aclk_mmu_php", 0,
+ RK3588_CLKGATE_CON(32), 11, GFLAGS),
+ GATE(CLK_PMALIVE0, "clk_pmalive0", "xin24m", 0,
+ RK3588_CLKGATE_CON(37), 4, GFLAGS),
+ GATE(CLK_PMALIVE1, "clk_pmalive1", "xin24m", 0,
+ RK3588_CLKGATE_CON(37), 5, GFLAGS),
+ GATE(CLK_PMALIVE2, "clk_pmalive2", "xin24m", 0,
+ RK3588_CLKGATE_CON(37), 6, GFLAGS),
+ GATE(ACLK_SATA0, "aclk_sata0", "aclk_mmu_php", 0,
+ RK3588_CLKGATE_CON(37), 7, GFLAGS),
+ GATE(ACLK_SATA1, "aclk_sata1", "aclk_mmu_php", 0,
+ RK3588_CLKGATE_CON(37), 8, GFLAGS),
+ GATE(ACLK_SATA2, "aclk_sata2", "aclk_mmu_php", 0,
+ RK3588_CLKGATE_CON(37), 9, GFLAGS),
+ COMPOSITE(CLK_RXOOB0, "clk_rxoob0", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(82), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3588_CLKGATE_CON(37), 10, GFLAGS),
+ COMPOSITE(CLK_RXOOB1, "clk_rxoob1", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(82), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ RK3588_CLKGATE_CON(37), 11, GFLAGS),
+ COMPOSITE(CLK_RXOOB2, "clk_rxoob2", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(83), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3588_CLKGATE_CON(37), 12, GFLAGS),
+ GATE(ACLK_USB3OTG2, "aclk_usb3otg2", "aclk_mmu_php", 0,
+ RK3588_CLKGATE_CON(35), 7, GFLAGS),
+ GATE(SUSPEND_CLK_USB3OTG2, "suspend_clk_usb3otg2", "xin24m", 0,
+ RK3588_CLKGATE_CON(35), 8, GFLAGS),
+ GATE(REF_CLK_USB3OTG2, "ref_clk_usb3otg2", "xin24m", 0,
+ RK3588_CLKGATE_CON(35), 9, GFLAGS),
+ COMPOSITE(CLK_UTMI_OTG2, "clk_utmi_otg2", mux_150m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(84), 12, 2, MFLAGS, 8, 4, DFLAGS,
+ RK3588_CLKGATE_CON(35), 10, GFLAGS),
+ GATE(PCLK_PCIE_COMBO_PIPE_PHY0, "pclk_pcie_combo_pipe_phy0", "pclk_top_root", 0,
+ RK3588_PHP_CLKGATE_CON(0), 5, GFLAGS),
+ GATE(PCLK_PCIE_COMBO_PIPE_PHY1, "pclk_pcie_combo_pipe_phy1", "pclk_top_root", 0,
+ RK3588_PHP_CLKGATE_CON(0), 6, GFLAGS),
+ GATE(PCLK_PCIE_COMBO_PIPE_PHY2, "pclk_pcie_combo_pipe_phy2", "pclk_top_root", 0,
+ RK3588_PHP_CLKGATE_CON(0), 7, GFLAGS),
+ GATE(PCLK_PCIE_COMBO_PIPE_PHY, "pclk_pcie_combo_pipe_phy", "pclk_top_root", 0,
+ RK3588_PHP_CLKGATE_CON(0), 8, GFLAGS),
+
+ /* rga */
+ COMPOSITE(CLK_RGA3_1_CORE, "clk_rga3_1_core", gpll_cpll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(174), 14, 2, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(76), 6, GFLAGS),
+ COMPOSITE(ACLK_RGA3_ROOT, "aclk_rga3_root", gpll_cpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(174), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(76), 0, GFLAGS),
+ COMPOSITE_NODIV(HCLK_RGA3_ROOT, "hclk_rga3_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(174), 7, 2, MFLAGS,
+ RK3588_CLKGATE_CON(76), 1, GFLAGS),
+ GATE(HCLK_RGA3_1, "hclk_rga3_1", "hclk_rga3_root", 0,
+ RK3588_CLKGATE_CON(76), 4, GFLAGS),
+ GATE(ACLK_RGA3_1, "aclk_rga3_1", "aclk_rga3_root", 0,
+ RK3588_CLKGATE_CON(76), 5, GFLAGS),
+
+ /* vdec */
+ COMPOSITE_NODIV(0, "hclk_rkvdec0_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(89), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(40), 0, GFLAGS),
+ COMPOSITE(0, "aclk_rkvdec0_root", gpll_cpll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(89), 7, 2, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(40), 1, GFLAGS),
+ COMPOSITE(ACLK_RKVDEC_CCU, "aclk_rkvdec_ccu", gpll_cpll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(89), 14, 2, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(40), 2, GFLAGS),
+ COMPOSITE(CLK_RKVDEC0_CA, "clk_rkvdec0_ca", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(90), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(40), 7, GFLAGS),
+ COMPOSITE(CLK_RKVDEC0_HEVC_CA, "clk_rkvdec0_hevc_ca", gpll_cpll_npll_1000m_p, 0,
+ RK3588_CLKSEL_CON(90), 11, 2, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(40), 8, GFLAGS),
+ COMPOSITE(CLK_RKVDEC0_CORE, "clk_rkvdec0_core", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(91), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(40), 9, GFLAGS),
+ COMPOSITE_NODIV(0, "hclk_rkvdec1_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(93), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(41), 0, GFLAGS),
+ COMPOSITE(0, "aclk_rkvdec1_root", gpll_cpll_aupll_npll_p, 0,
+ RK3588_CLKSEL_CON(93), 7, 2, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(41), 1, GFLAGS),
+ COMPOSITE(CLK_RKVDEC1_CA, "clk_rkvdec1_ca", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(93), 14, 1, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(41), 6, GFLAGS),
+ COMPOSITE(CLK_RKVDEC1_HEVC_CA, "clk_rkvdec1_hevc_ca", gpll_cpll_npll_1000m_p, 0,
+ RK3588_CLKSEL_CON(94), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(41), 7, GFLAGS),
+ COMPOSITE(CLK_RKVDEC1_CORE, "clk_rkvdec1_core", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(94), 12, 1, MFLAGS, 7, 5, DFLAGS,
+ RK3588_CLKGATE_CON(41), 8, GFLAGS),
+
+ /* sdio */
+ COMPOSITE_NODIV(0, "hclk_sdio_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(172), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(75), 0, GFLAGS),
+ COMPOSITE(CCLK_SRC_SDIO, "cclk_src_sdio", gpll_cpll_24m_p, 0,
+ RK3588_CLKSEL_CON(172), 8, 2, MFLAGS, 2, 6, DFLAGS,
+ RK3588_CLKGATE_CON(75), 3, GFLAGS),
+ MMC(SCLK_SDIO_DRV, "sdio_drv", "cclk_src_sdio", RK3588_SDIO_CON0, 1),
+ MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "cclk_src_sdio", RK3588_SDIO_CON1, 1),
+
+ /* usb */
+ COMPOSITE(ACLK_USB_ROOT, "aclk_usb_root", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(96), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(42), 0, GFLAGS),
+ COMPOSITE_NODIV(HCLK_USB_ROOT, "hclk_usb_root", mux_150m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(96), 6, 2, MFLAGS,
+ RK3588_CLKGATE_CON(42), 1, GFLAGS),
+ GATE(SUSPEND_CLK_USB3OTG0, "suspend_clk_usb3otg0", "xin24m", 0,
+ RK3588_CLKGATE_CON(42), 5, GFLAGS),
+ GATE(REF_CLK_USB3OTG0, "ref_clk_usb3otg0", "xin24m", 0,
+ RK3588_CLKGATE_CON(42), 6, GFLAGS),
+ GATE(SUSPEND_CLK_USB3OTG1, "suspend_clk_usb3otg1", "xin24m", 0,
+ RK3588_CLKGATE_CON(42), 8, GFLAGS),
+ GATE(REF_CLK_USB3OTG1, "ref_clk_usb3otg1", "xin24m", 0,
+ RK3588_CLKGATE_CON(42), 9, GFLAGS),
+
+ /* vdpu */
+ COMPOSITE(ACLK_VDPU_ROOT, "aclk_vdpu_root", gpll_cpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(98), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(44), 0, GFLAGS),
+ COMPOSITE_NODIV(ACLK_VDPU_LOW_ROOT, "aclk_vdpu_low_root", mux_400m_200m_100m_24m_p, 0,
+ RK3588_CLKSEL_CON(98), 7, 2, MFLAGS,
+ RK3588_CLKGATE_CON(44), 1, GFLAGS),
+ COMPOSITE_NODIV(HCLK_VDPU_ROOT, "hclk_vdpu_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(98), 9, 2, MFLAGS,
+ RK3588_CLKGATE_CON(44), 2, GFLAGS),
+ COMPOSITE(ACLK_JPEG_DECODER_ROOT, "aclk_jpeg_decoder_root", gpll_cpll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(99), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(44), 3, GFLAGS),
+ GATE(HCLK_IEP2P0, "hclk_iep2p0", "hclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(45), 4, GFLAGS),
+ COMPOSITE(CLK_IEP2P0_CORE, "clk_iep2p0_core", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(99), 12, 1, MFLAGS, 7, 5, DFLAGS,
+ RK3588_CLKGATE_CON(45), 6, GFLAGS),
+ GATE(HCLK_JPEG_ENCODER0, "hclk_jpeg_encoder0", "hclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(44), 11, GFLAGS),
+ GATE(HCLK_JPEG_ENCODER1, "hclk_jpeg_encoder1", "hclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(44), 13, GFLAGS),
+ GATE(HCLK_JPEG_ENCODER2, "hclk_jpeg_encoder2", "hclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(44), 15, GFLAGS),
+ GATE(HCLK_JPEG_ENCODER3, "hclk_jpeg_encoder3", "hclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(45), 1, GFLAGS),
+ GATE(HCLK_JPEG_DECODER, "hclk_jpeg_decoder", "hclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(45), 3, GFLAGS),
+ GATE(HCLK_RGA2, "hclk_rga2", "hclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(45), 7, GFLAGS),
+ GATE(ACLK_RGA2, "aclk_rga2", "aclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(45), 8, GFLAGS),
+ COMPOSITE(CLK_RGA2_CORE, "clk_rga2_core", gpll_cpll_npll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(100), 5, 3, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(45), 9, GFLAGS),
+ GATE(HCLK_RGA3_0, "hclk_rga3_0", "hclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(45), 10, GFLAGS),
+ GATE(ACLK_RGA3_0, "aclk_rga3_0", "aclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(45), 11, GFLAGS),
+ COMPOSITE(CLK_RGA3_0_CORE, "clk_rga3_0_core", gpll_cpll_npll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(100), 13, 3, MFLAGS, 8, 5, DFLAGS,
+ RK3588_CLKGATE_CON(45), 12, GFLAGS),
+ GATE(HCLK_VPU, "hclk_vpu", "hclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(44), 9, GFLAGS),
+
+ /* venc */
+ COMPOSITE_NODIV(HCLK_RKVENC1_ROOT, "hclk_rkvenc1_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(104), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(48), 0, GFLAGS),
+ COMPOSITE(ACLK_RKVENC1_ROOT, "aclk_rkvenc1_root", gpll_cpll_npll_p, 0,
+ RK3588_CLKSEL_CON(104), 7, 2, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(48), 1, GFLAGS),
+ COMPOSITE_NODIV(HCLK_RKVENC0_ROOT, "hclk_rkvenc0_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(102), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(47), 0, GFLAGS),
+ COMPOSITE(ACLK_RKVENC0_ROOT, "aclk_rkvenc0_root", gpll_cpll_npll_p, 0,
+ RK3588_CLKSEL_CON(102), 7, 2, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(47), 1, GFLAGS),
+ GATE(HCLK_RKVENC0, "hclk_rkvenc0", "hclk_rkvenc0_root", 0,
+ RK3588_CLKGATE_CON(47), 4, GFLAGS),
+ GATE(ACLK_RKVENC0, "aclk_rkvenc0", "aclk_rkvenc0_root", 0,
+ RK3588_CLKGATE_CON(47), 5, GFLAGS),
+ COMPOSITE(CLK_RKVENC0_CORE, "clk_rkvenc0_core", gpll_cpll_aupll_npll_p, 0,
+ RK3588_CLKSEL_CON(102), 14, 2, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(47), 6, GFLAGS),
+ COMPOSITE(CLK_RKVENC1_CORE, "clk_rkvenc1_core", gpll_cpll_aupll_npll_p, 0,
+ RK3588_CLKSEL_CON(104), 14, 2, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(48), 6, GFLAGS),
+
+ /* vi */
+ COMPOSITE(ACLK_VI_ROOT, "aclk_vi_root", gpll_cpll_npll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(106), 5, 3, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(49), 0, GFLAGS),
+ COMPOSITE_NODIV(HCLK_VI_ROOT, "hclk_vi_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(106), 8, 2, MFLAGS,
+ RK3588_CLKGATE_CON(49), 1, GFLAGS),
+ COMPOSITE_NODIV(PCLK_VI_ROOT, "pclk_vi_root", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(106), 10, 2, MFLAGS,
+ RK3588_CLKGATE_CON(49), 2, GFLAGS),
+ COMPOSITE_NODIV(ICLK_CSIHOST01, "iclk_csihost01", mux_400m_200m_100m_24m_p, 0,
+ RK3588_CLKSEL_CON(108), 14, 2, MFLAGS,
+ RK3588_CLKGATE_CON(51), 10, GFLAGS),
+ GATE(ICLK_CSIHOST0, "iclk_csihost0", "iclk_csihost01", 0,
+ RK3588_CLKGATE_CON(51), 11, GFLAGS),
+ GATE(ICLK_CSIHOST1, "iclk_csihost1", "iclk_csihost01", 0,
+ RK3588_CLKGATE_CON(51), 12, GFLAGS),
+ GATE(PCLK_CSI_HOST_0, "pclk_csi_host_0", "pclk_vi_root", 0,
+ RK3588_CLKGATE_CON(50), 4, GFLAGS),
+ GATE(PCLK_CSI_HOST_1, "pclk_csi_host_1", "pclk_vi_root", 0,
+ RK3588_CLKGATE_CON(50), 5, GFLAGS),
+ GATE(PCLK_CSI_HOST_2, "pclk_csi_host_2", "pclk_vi_root", 0,
+ RK3588_CLKGATE_CON(50), 6, GFLAGS),
+ GATE(PCLK_CSI_HOST_3, "pclk_csi_host_3", "pclk_vi_root", 0,
+ RK3588_CLKGATE_CON(50), 7, GFLAGS),
+ GATE(PCLK_CSI_HOST_4, "pclk_csi_host_4", "pclk_vi_root", 0,
+ RK3588_CLKGATE_CON(50), 8, GFLAGS),
+ GATE(PCLK_CSI_HOST_5, "pclk_csi_host_5", "pclk_vi_root", 0,
+ RK3588_CLKGATE_CON(50), 9, GFLAGS),
+ GATE(ACLK_FISHEYE0, "aclk_fisheye0", "aclk_vi_root", 0,
+ RK3588_CLKGATE_CON(49), 14, GFLAGS),
+ GATE(HCLK_FISHEYE0, "hclk_fisheye0", "hclk_vi_root", 0,
+ RK3588_CLKGATE_CON(49), 15, GFLAGS),
+ COMPOSITE(CLK_FISHEYE0_CORE, "clk_fisheye0_core", gpll_cpll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(108), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(50), 0, GFLAGS),
+ GATE(ACLK_FISHEYE1, "aclk_fisheye1", "aclk_vi_root", 0,
+ RK3588_CLKGATE_CON(50), 1, GFLAGS),
+ GATE(HCLK_FISHEYE1, "hclk_fisheye1", "hclk_vi_root", 0,
+ RK3588_CLKGATE_CON(50), 2, GFLAGS),
+ COMPOSITE(CLK_FISHEYE1_CORE, "clk_fisheye1_core", gpll_cpll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(108), 12, 2, MFLAGS, 7, 5, DFLAGS,
+ RK3588_CLKGATE_CON(50), 3, GFLAGS),
+ COMPOSITE(CLK_ISP0_CORE, "clk_isp0_core", gpll_cpll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(107), 11, 2, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(49), 9, GFLAGS),
+ GATE(CLK_ISP0_CORE_MARVIN, "clk_isp0_core_marvin", "clk_isp0_core", 0,
+ RK3588_CLKGATE_CON(49), 10, GFLAGS),
+ GATE(CLK_ISP0_CORE_VICAP, "clk_isp0_core_vicap", "clk_isp0_core", 0,
+ RK3588_CLKGATE_CON(49), 11, GFLAGS),
+ GATE(ACLK_ISP0, "aclk_isp0", "aclk_vi_root", 0,
+ RK3588_CLKGATE_CON(49), 12, GFLAGS),
+ GATE(HCLK_ISP0, "hclk_isp0", "hclk_vi_root", 0,
+ RK3588_CLKGATE_CON(49), 13, GFLAGS),
+ COMPOSITE(DCLK_VICAP, "dclk_vicap", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(107), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(49), 6, GFLAGS),
+ GATE(ACLK_VICAP, "aclk_vicap", "aclk_vi_root", 0,
+ RK3588_CLKGATE_CON(49), 7, GFLAGS),
+ GATE(HCLK_VICAP, "hclk_vicap", "hclk_vi_root", 0,
+ RK3588_CLKGATE_CON(49), 8, GFLAGS),
+
+ /* vo0 */
+ COMPOSITE(ACLK_VO0_ROOT, "aclk_vo0_root", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(116), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(55), 0, GFLAGS),
+ COMPOSITE_NODIV(HCLK_VO0_ROOT, "hclk_vo0_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(116), 6, 2, MFLAGS,
+ RK3588_CLKGATE_CON(55), 1, GFLAGS),
+ COMPOSITE_NODIV(HCLK_VO0_S_ROOT, "hclk_vo0_s_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(116), 8, 2, MFLAGS,
+ RK3588_CLKGATE_CON(55), 2, GFLAGS),
+ COMPOSITE_NODIV(PCLK_VO0_ROOT, "pclk_vo0_root", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(116), 10, 2, MFLAGS,
+ RK3588_CLKGATE_CON(55), 3, GFLAGS),
+ COMPOSITE_NODIV(PCLK_VO0_S_ROOT, "pclk_vo0_s_root", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(116), 12, 2, MFLAGS,
+ RK3588_CLKGATE_CON(55), 4, GFLAGS),
+ GATE(PCLK_DP0, "pclk_dp0", "pclk_vo0_root", 0,
+ RK3588_CLKGATE_CON(56), 4, GFLAGS),
+ GATE(PCLK_DP1, "pclk_dp1", "pclk_vo0_root", 0,
+ RK3588_CLKGATE_CON(56), 5, GFLAGS),
+ GATE(PCLK_S_DP0, "pclk_s_dp0", "pclk_vo0_s_root", 0,
+ RK3588_CLKGATE_CON(56), 6, GFLAGS),
+ GATE(PCLK_S_DP1, "pclk_s_dp1", "pclk_vo0_s_root", 0,
+ RK3588_CLKGATE_CON(56), 7, GFLAGS),
+ GATE(CLK_DP0, "clk_dp0", "aclk_vo0_root", 0,
+ RK3588_CLKGATE_CON(56), 8, GFLAGS),
+ GATE(CLK_DP1, "clk_dp1", "aclk_vo0_root", 0,
+ RK3588_CLKGATE_CON(56), 9, GFLAGS),
+ GATE(HCLK_HDCP_KEY0, "hclk_hdcp_key0", "hclk_vo0_s_root", 0,
+ RK3588_CLKGATE_CON(55), 11, GFLAGS),
+ GATE(PCLK_HDCP0, "pclk_hdcp0", "pclk_vo0_root", 0,
+ RK3588_CLKGATE_CON(55), 14, GFLAGS),
+ GATE(ACLK_TRNG0, "aclk_trng0", "aclk_vo0_root", 0,
+ RK3588_CLKGATE_CON(56), 0, GFLAGS),
+ GATE(PCLK_TRNG0, "pclk_trng0", "pclk_vo0_root", 0,
+ RK3588_CLKGATE_CON(56), 1, GFLAGS),
+ GATE(PCLK_VO0GRF, "pclk_vo0grf", "pclk_vo0_root", CLK_IGNORE_UNUSED,
+ RK3588_CLKGATE_CON(55), 10, GFLAGS),
+ COMPOSITE(CLK_I2S4_8CH_TX_SRC, "clk_i2s4_8ch_tx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(118), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(56), 11, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S4_8CH_TX_FRAC, "clk_i2s4_8ch_tx_frac", "clk_i2s4_8ch_tx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(119), 0,
+ RK3588_CLKGATE_CON(56), 12, GFLAGS,
+ &rk3588_i2s4_8ch_tx_fracmux),
+ GATE(MCLK_I2S4_8CH_TX, "mclk_i2s4_8ch_tx", "clk_i2s4_8ch_tx", 0,
+ RK3588_CLKGATE_CON(56), 13, GFLAGS),
+ COMPOSITE(CLK_I2S8_8CH_TX_SRC, "clk_i2s8_8ch_tx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(120), 8, 1, MFLAGS, 3, 5, DFLAGS,
+ RK3588_CLKGATE_CON(56), 15, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S8_8CH_TX_FRAC, "clk_i2s8_8ch_tx_frac", "clk_i2s8_8ch_tx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(121), 0,
+ RK3588_CLKGATE_CON(57), 0, GFLAGS,
+ &rk3588_i2s8_8ch_tx_fracmux),
+ GATE(MCLK_I2S8_8CH_TX, "mclk_i2s8_8ch_tx", "clk_i2s8_8ch_tx", 0,
+ RK3588_CLKGATE_CON(57), 1, GFLAGS),
+ COMPOSITE(CLK_SPDIF2_DP0_SRC, "clk_spdif2_dp0_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(122), 8, 1, MFLAGS, 3, 5, DFLAGS,
+ RK3588_CLKGATE_CON(57), 3, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_SPDIF2_DP0_FRAC, "clk_spdif2_dp0_frac", "clk_spdif2_dp0_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(123), 0,
+ RK3588_CLKGATE_CON(57), 4, GFLAGS,
+ &rk3588_spdif2_dp0_fracmux),
+ GATE(MCLK_SPDIF2_DP0, "mclk_spdif2_dp0", "clk_spdif2_dp0", 0,
+ RK3588_CLKGATE_CON(57), 5, GFLAGS),
+ GATE(MCLK_SPDIF2, "mclk_spdif2", "clk_spdif2_dp0", 0,
+ RK3588_CLKGATE_CON(57), 6, GFLAGS),
+ COMPOSITE(CLK_SPDIF5_DP1_SRC, "clk_spdif5_dp1_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(124), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(57), 8, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_SPDIF5_DP1_FRAC, "clk_spdif5_dp1_frac", "clk_spdif5_dp1_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(125), 0,
+ RK3588_CLKGATE_CON(57), 9, GFLAGS,
+ &rk3588_spdif5_dp1_fracmux),
+ GATE(MCLK_SPDIF5_DP1, "mclk_spdif5_dp1", "clk_spdif5_dp1", 0,
+ RK3588_CLKGATE_CON(57), 10, GFLAGS),
+ GATE(MCLK_SPDIF5, "mclk_spdif5", "clk_spdif5_dp1", 0,
+ RK3588_CLKGATE_CON(57), 11, GFLAGS),
+ COMPOSITE_NOMUX(CLK_AUX16M_0, "clk_aux16m_0", "gpll", 0,
+ RK3588_CLKSEL_CON(117), 0, 8, DFLAGS,
+ RK3588_CLKGATE_CON(56), 2, GFLAGS),
+ COMPOSITE_NOMUX(CLK_AUX16M_1, "clk_aux16m_1", "gpll", 0,
+ RK3588_CLKSEL_CON(117), 8, 8, DFLAGS,
+ RK3588_CLKGATE_CON(56), 3, GFLAGS),
+
+ /* vo1 */
+ COMPOSITE_HALFDIV(CLK_HDMITRX_REFSRC, "clk_hdmitrx_refsrc", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(157), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(65), 9, GFLAGS),
+ COMPOSITE(ACLK_HDCP1_ROOT, "aclk_hdcp1_root", aclk_hdcp1_root_p, 0,
+ RK3588_CLKSEL_CON(128), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(59), 0, GFLAGS),
+ COMPOSITE(ACLK_HDMIRX_ROOT, "aclk_hdmirx_root", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(128), 12, 1, MFLAGS, 7, 5, DFLAGS,
+ RK3588_CLKGATE_CON(59), 1, GFLAGS),
+ COMPOSITE_NODIV(HCLK_VO1_ROOT, "hclk_vo1_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(128), 13, 2, MFLAGS,
+ RK3588_CLKGATE_CON(59), 2, GFLAGS),
+ COMPOSITE_NODIV(HCLK_VO1_S_ROOT, "hclk_vo1_s_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(129), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(59), 3, GFLAGS),
+ COMPOSITE_NODIV(PCLK_VO1_ROOT, "pclk_vo1_root", mux_150m_100m_24m_p, 0,
+ RK3588_CLKSEL_CON(129), 2, 2, MFLAGS,
+ RK3588_CLKGATE_CON(59), 4, GFLAGS),
+ COMPOSITE_NODIV(PCLK_VO1_S_ROOT, "pclk_vo1_s_root", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(129), 4, 2, MFLAGS,
+ RK3588_CLKGATE_CON(59), 5, GFLAGS),
+ COMPOSITE(ACLK_VOP_ROOT, "aclk_vop_root", gpll_cpll_dmyaupll_npll_spll_p, 0,
+ RK3588_CLKSEL_CON(110), 5, 3, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(52), 0, GFLAGS),
+ COMPOSITE_NODIV(ACLK_VOP_LOW_ROOT, "aclk_vop_low_root", mux_400m_200m_100m_24m_p, 0,
+ RK3588_CLKSEL_CON(110), 8, 2, MFLAGS,
+ RK3588_CLKGATE_CON(52), 1, GFLAGS),
+ COMPOSITE_NODIV(HCLK_VOP_ROOT, "hclk_vop_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(110), 10, 2, MFLAGS,
+ RK3588_CLKGATE_CON(52), 2, GFLAGS),
+ COMPOSITE_NODIV(PCLK_VOP_ROOT, "pclk_vop_root", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(110), 12, 2, MFLAGS,
+ RK3588_CLKGATE_CON(52), 3, GFLAGS),
+ COMPOSITE(ACLK_VO1USB_TOP_ROOT, "aclk_vo1usb_top_root", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(170), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(74), 0, GFLAGS),
+ COMPOSITE_NODIV(HCLK_VO1USB_TOP_ROOT, "hclk_vo1usb_top_root", mux_200m_100m_50m_24m_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(170), 6, 2, MFLAGS,
+ RK3588_CLKGATE_CON(74), 2, GFLAGS),
+ MUX(ACLK_VOP_SUB_SRC, "aclk_vop_sub_src", aclk_vop_sub_src_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(115), 9, 1, MFLAGS),
+ GATE(PCLK_EDP0, "pclk_edp0", "pclk_vo1_root", 0,
+ RK3588_CLKGATE_CON(62), 0, GFLAGS),
+ GATE(CLK_EDP0_24M, "clk_edp0_24m", "xin24m", 0,
+ RK3588_CLKGATE_CON(62), 1, GFLAGS),
+ COMPOSITE_NODIV(CLK_EDP0_200M, "clk_edp0_200m", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(140), 1, 2, MFLAGS,
+ RK3588_CLKGATE_CON(62), 2, GFLAGS),
+ GATE(PCLK_EDP1, "pclk_edp1", "pclk_vo1_root", 0,
+ RK3588_CLKGATE_CON(62), 3, GFLAGS),
+ GATE(CLK_EDP1_24M, "clk_edp1_24m", "xin24m", 0,
+ RK3588_CLKGATE_CON(62), 4, GFLAGS),
+ COMPOSITE_NODIV(CLK_EDP1_200M, "clk_edp1_200m", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(140), 3, 2, MFLAGS,
+ RK3588_CLKGATE_CON(62), 5, GFLAGS),
+ GATE(HCLK_HDCP_KEY1, "hclk_hdcp_key1", "hclk_vo1_s_root", 0,
+ RK3588_CLKGATE_CON(60), 4, GFLAGS),
+ GATE(PCLK_HDCP1, "pclk_hdcp1", "pclk_vo1_root", 0,
+ RK3588_CLKGATE_CON(60), 7, GFLAGS),
+ GATE(ACLK_HDMIRX, "aclk_hdmirx", "aclk_hdmirx_root", 0,
+ RK3588_CLKGATE_CON(61), 9, GFLAGS),
+ GATE(PCLK_HDMIRX, "pclk_hdmirx", "pclk_vo1_root", 0,
+ RK3588_CLKGATE_CON(61), 10, GFLAGS),
+ GATE(CLK_HDMIRX_REF, "clk_hdmirx_ref", "aclk_hdcp1_root", 0,
+ RK3588_CLKGATE_CON(61), 11, GFLAGS),
+ COMPOSITE(CLK_HDMIRX_AUD_SRC, "clk_hdmirx_aud_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(138), 8, 1, MFLAGS, 0, 8, DFLAGS,
+ RK3588_CLKGATE_CON(61), 12, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_HDMIRX_AUD_FRAC, "clk_hdmirx_aud_frac", "clk_hdmirx_aud_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(139), 0,
+ RK3588_CLKGATE_CON(61), 13, GFLAGS,
+ &rk3588_hdmirx_aud_fracmux),
+ GATE(CLK_HDMIRX_AUD, "clk_hdmirx_aud", "clk_hdmirx_aud_mux", 0,
+ RK3588_CLKGATE_CON(61), 14, GFLAGS),
+ GATE(PCLK_HDMITX0, "pclk_hdmitx0", "pclk_vo1_root", 0,
+ RK3588_CLKGATE_CON(60), 11, GFLAGS),
+ COMPOSITE(CLK_HDMITX0_EARC, "clk_hdmitx0_earc", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(133), 6, 1, MFLAGS, 1, 5, DFLAGS,
+ RK3588_CLKGATE_CON(60), 15, GFLAGS),
+ GATE(CLK_HDMITX0_REF, "clk_hdmitx0_ref", "aclk_hdcp1_root", 0,
+ RK3588_CLKGATE_CON(61), 0, GFLAGS),
+ GATE(PCLK_HDMITX1, "pclk_hdmitx1", "pclk_vo1_root", 0,
+ RK3588_CLKGATE_CON(61), 2, GFLAGS),
+ COMPOSITE(CLK_HDMITX1_EARC, "clk_hdmitx1_earc", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(136), 6, 1, MFLAGS, 1, 5, DFLAGS,
+ RK3588_CLKGATE_CON(61), 6, GFLAGS),
+ GATE(CLK_HDMITX1_REF, "clk_hdmitx1_ref", "aclk_hdcp1_root", 0,
+ RK3588_CLKGATE_CON(61), 7, GFLAGS),
+ GATE(ACLK_TRNG1, "aclk_trng1", "aclk_hdcp1_root", 0,
+ RK3588_CLKGATE_CON(60), 9, GFLAGS),
+ GATE(PCLK_TRNG1, "pclk_trng1", "pclk_vo1_root", 0,
+ RK3588_CLKGATE_CON(60), 10, GFLAGS),
+ GATE(0, "pclk_vo1grf", "pclk_vo1_root", CLK_IGNORE_UNUSED,
+ RK3588_CLKGATE_CON(59), 12, GFLAGS),
+ GATE(PCLK_S_EDP0, "pclk_s_edp0", "pclk_vo1_s_root", 0,
+ RK3588_CLKGATE_CON(59), 14, GFLAGS),
+ GATE(PCLK_S_EDP1, "pclk_s_edp1", "pclk_vo1_s_root", 0,
+ RK3588_CLKGATE_CON(59), 15, GFLAGS),
+ GATE(PCLK_S_HDMIRX, "pclk_s_hdmirx", "pclk_vo1_s_root", 0,
+ RK3588_CLKGATE_CON(65), 8, GFLAGS),
+ COMPOSITE(CLK_I2S10_8CH_RX_SRC, "clk_i2s10_8ch_rx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(155), 8, 1, MFLAGS, 3, 5, DFLAGS,
+ RK3588_CLKGATE_CON(65), 5, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S10_8CH_RX_FRAC, "clk_i2s10_8ch_rx_frac", "clk_i2s10_8ch_rx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(156), 0,
+ RK3588_CLKGATE_CON(65), 6, GFLAGS,
+ &rk3588_i2s10_8ch_rx_fracmux),
+ GATE(MCLK_I2S10_8CH_RX, "mclk_i2s10_8ch_rx", "clk_i2s10_8ch_rx", 0,
+ RK3588_CLKGATE_CON(65), 7, GFLAGS),
+ COMPOSITE(CLK_I2S7_8CH_RX_SRC, "clk_i2s7_8ch_rx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(129), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(60), 1, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S7_8CH_RX_FRAC, "clk_i2s7_8ch_rx_frac", "clk_i2s7_8ch_rx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(130), 0,
+ RK3588_CLKGATE_CON(60), 2, GFLAGS,
+ &rk3588_i2s7_8ch_rx_fracmux),
+ GATE(MCLK_I2S7_8CH_RX, "mclk_i2s7_8ch_rx", "clk_i2s7_8ch_rx", 0,
+ RK3588_CLKGATE_CON(60), 3, GFLAGS),
+ COMPOSITE(CLK_I2S9_8CH_RX_SRC, "clk_i2s9_8ch_rx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(153), 12, 1, MFLAGS, 7, 5, DFLAGS,
+ RK3588_CLKGATE_CON(65), 1, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S9_8CH_RX_FRAC, "clk_i2s9_8ch_rx_frac", "clk_i2s9_8ch_rx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(154), 0,
+ RK3588_CLKGATE_CON(65), 2, GFLAGS,
+ &rk3588_i2s9_8ch_rx_fracmux),
+ GATE(MCLK_I2S9_8CH_RX, "mclk_i2s9_8ch_rx", "clk_i2s9_8ch_rx", 0,
+ RK3588_CLKGATE_CON(65), 3, GFLAGS),
+ COMPOSITE(CLK_I2S5_8CH_TX_SRC, "clk_i2s5_8ch_tx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(140), 10, 1, MFLAGS, 5, 5, DFLAGS,
+ RK3588_CLKGATE_CON(62), 6, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S5_8CH_TX_FRAC, "clk_i2s5_8ch_tx_frac", "clk_i2s5_8ch_tx_src", 0,
+ RK3588_CLKSEL_CON(141), 0,
+ RK3588_CLKGATE_CON(62), 7, GFLAGS,
+ &rk3588_i2s5_8ch_tx_fracmux),
+ GATE(MCLK_I2S5_8CH_TX, "mclk_i2s5_8ch_tx", "clk_i2s5_8ch_tx", 0,
+ RK3588_CLKGATE_CON(62), 8, GFLAGS),
+ COMPOSITE(CLK_I2S6_8CH_TX_SRC, "clk_i2s6_8ch_tx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(144), 8, 1, MFLAGS, 3, 5, DFLAGS,
+ RK3588_CLKGATE_CON(62), 13, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S6_8CH_TX_FRAC, "clk_i2s6_8ch_tx_frac", "clk_i2s6_8ch_tx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(145), 0,
+ RK3588_CLKGATE_CON(62), 14, GFLAGS,
+ &rk3588_i2s6_8ch_tx_fracmux),
+ GATE(MCLK_I2S6_8CH_TX, "mclk_i2s6_8ch_tx", "clk_i2s6_8ch_tx", 0,
+ RK3588_CLKGATE_CON(62), 15, GFLAGS),
+ COMPOSITE(CLK_I2S6_8CH_RX_SRC, "clk_i2s6_8ch_rx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(146), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(63), 0, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S6_8CH_RX_FRAC, "clk_i2s6_8ch_rx_frac", "clk_i2s6_8ch_rx_src", 0,
+ RK3588_CLKSEL_CON(147), 0,
+ RK3588_CLKGATE_CON(63), 1, GFLAGS,
+ &rk3588_i2s6_8ch_rx_fracmux),
+ GATE(MCLK_I2S6_8CH_RX, "mclk_i2s6_8ch_rx", "clk_i2s6_8ch_rx", 0,
+ RK3588_CLKGATE_CON(63), 2, GFLAGS),
+ MUX(I2S6_8CH_MCLKOUT, "i2s6_8ch_mclkout", i2s6_8ch_mclkout_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(148), 2, 2, MFLAGS),
+ COMPOSITE(CLK_SPDIF3_SRC, "clk_spdif3_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(148), 9, 1, MFLAGS, 4, 5, DFLAGS,
+ RK3588_CLKGATE_CON(63), 5, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_SPDIF3_FRAC, "clk_spdif3_frac", "clk_spdif3_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(149), 0,
+ RK3588_CLKGATE_CON(63), 6, GFLAGS,
+ &rk3588_spdif3_fracmux),
+ GATE(MCLK_SPDIF3, "mclk_spdif3", "clk_spdif3", 0,
+ RK3588_CLKGATE_CON(63), 7, GFLAGS),
+ COMPOSITE(CLK_SPDIF4_SRC, "clk_spdif4_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(150), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(63), 9, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_SPDIF4_FRAC, "clk_spdif4_frac", "clk_spdif4_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(151), 0,
+ RK3588_CLKGATE_CON(63), 10, GFLAGS,
+ &rk3588_spdif4_fracmux),
+ GATE(MCLK_SPDIF4, "mclk_spdif4", "clk_spdif4", 0,
+ RK3588_CLKGATE_CON(63), 11, GFLAGS),
+ COMPOSITE(MCLK_SPDIFRX0, "mclk_spdifrx0", gpll_cpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(152), 7, 2, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(63), 13, GFLAGS),
+ COMPOSITE(MCLK_SPDIFRX1, "mclk_spdifrx1", gpll_cpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(152), 14, 2, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(63), 15, GFLAGS),
+ COMPOSITE(MCLK_SPDIFRX2, "mclk_spdifrx2", gpll_cpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(153), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(64), 1, GFLAGS),
+ GATE(CLK_HDMIHDP0, "clk_hdmihdp0", "xin24m", 0,
+ RK3588_CLKGATE_CON(73), 12, GFLAGS),
+ GATE(CLK_HDMIHDP1, "clk_hdmihdp1", "xin24m", 0,
+ RK3588_CLKGATE_CON(73), 13, GFLAGS),
+ GATE(PCLK_HDPTX0, "pclk_hdptx0", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(72), 5, GFLAGS),
+ GATE(PCLK_HDPTX1, "pclk_hdptx1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(72), 6, GFLAGS),
+ GATE(PCLK_USBDPPHY0, "pclk_usbdpphy0", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(72), 2, GFLAGS),
+ GATE(PCLK_USBDPPHY1, "pclk_usbdpphy1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(72), 4, GFLAGS),
+ GATE(HCLK_VOP, "hclk_vop", "hclk_vop_root", 0,
+ RK3588_CLKGATE_CON(52), 8, GFLAGS),
+ GATE(ACLK_VOP, "aclk_vop", "aclk_vop_sub_src", 0,
+ RK3588_CLKGATE_CON(52), 9, GFLAGS),
+ COMPOSITE(DCLK_VOP0_SRC, "dclk_vop0_src", gpll_cpll_v0pll_aupll_p, 0,
+ RK3588_CLKSEL_CON(111), 7, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3588_CLKGATE_CON(52), 10, GFLAGS),
+ COMPOSITE(DCLK_VOP1_SRC, "dclk_vop1_src", gpll_cpll_v0pll_aupll_p, 0,
+ RK3588_CLKSEL_CON(111), 14, 2, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(52), 11, GFLAGS),
+ COMPOSITE(DCLK_VOP2_SRC, "dclk_vop2_src", gpll_cpll_v0pll_aupll_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+ RK3588_CLKSEL_CON(112), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(52), 12, GFLAGS),
+ COMPOSITE_NODIV(DCLK_VOP0, "dclk_vop0", dclk_vop0_p,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+ RK3588_CLKSEL_CON(112), 7, 2, MFLAGS,
+ RK3588_CLKGATE_CON(52), 13, GFLAGS),
+ COMPOSITE_NODIV(DCLK_VOP1, "dclk_vop1", dclk_vop1_p,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+ RK3588_CLKSEL_CON(112), 9, 2, MFLAGS,
+ RK3588_CLKGATE_CON(53), 0, GFLAGS),
+ COMPOSITE_NODIV(DCLK_VOP2, "dclk_vop2", dclk_vop2_p,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+ RK3588_CLKSEL_CON(112), 11, 2, MFLAGS,
+ RK3588_CLKGATE_CON(53), 1, GFLAGS),
+ COMPOSITE(DCLK_VOP3, "dclk_vop3", gpll_cpll_v0pll_aupll_p, 0,
+ RK3588_CLKSEL_CON(113), 7, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3588_CLKGATE_CON(53), 2, GFLAGS),
+ GATE(PCLK_DSIHOST0, "pclk_dsihost0", "pclk_vop_root", 0,
+ RK3588_CLKGATE_CON(53), 4, GFLAGS),
+ GATE(PCLK_DSIHOST1, "pclk_dsihost1", "pclk_vop_root", 0,
+ RK3588_CLKGATE_CON(53), 5, GFLAGS),
+ COMPOSITE(CLK_DSIHOST0, "clk_dsihost0", gpll_cpll_v0pll_spll_p, 0,
+ RK3588_CLKSEL_CON(114), 7, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3588_CLKGATE_CON(53), 6, GFLAGS),
+ COMPOSITE(CLK_DSIHOST1, "clk_dsihost1", gpll_cpll_v0pll_spll_p, 0,
+ RK3588_CLKSEL_CON(115), 7, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3588_CLKGATE_CON(53), 7, GFLAGS),
+ GATE(CLK_VOP_PMU, "clk_vop_pmu", "xin24m", CLK_IGNORE_UNUSED,
+ RK3588_CLKGATE_CON(53), 8, GFLAGS),
+ GATE(ACLK_VOP_DOBY, "aclk_vop_doby", "aclk_vop_root", 0,
+ RK3588_CLKGATE_CON(53), 10, GFLAGS),
+ GATE(CLK_USBDP_PHY0_IMMORTAL, "clk_usbdp_phy0_immortal", "xin24m", CLK_IGNORE_UNUSED,
+ RK3588_CLKGATE_CON(2), 8, GFLAGS),
+ GATE(CLK_USBDP_PHY1_IMMORTAL, "clk_usbdp_phy1_immortal", "xin24m", CLK_IGNORE_UNUSED,
+ RK3588_CLKGATE_CON(2), 15, GFLAGS),
+
+ GATE(CLK_REF_PIPE_PHY0_OSC_SRC, "clk_ref_pipe_phy0_osc_src", "xin24m", 0,
+ RK3588_CLKGATE_CON(77), 0, GFLAGS),
+ GATE(CLK_REF_PIPE_PHY1_OSC_SRC, "clk_ref_pipe_phy1_osc_src", "xin24m", 0,
+ RK3588_CLKGATE_CON(77), 1, GFLAGS),
+ GATE(CLK_REF_PIPE_PHY2_OSC_SRC, "clk_ref_pipe_phy2_osc_src", "xin24m", 0,
+ RK3588_CLKGATE_CON(77), 2, GFLAGS),
+ COMPOSITE_NOMUX(CLK_REF_PIPE_PHY0_PLL_SRC, "clk_ref_pipe_phy0_pll_src", "ppll", 0,
+ RK3588_CLKSEL_CON(176), 0, 6, DFLAGS,
+ RK3588_CLKGATE_CON(77), 3, GFLAGS),
+ COMPOSITE_NOMUX(CLK_REF_PIPE_PHY1_PLL_SRC, "clk_ref_pipe_phy1_pll_src", "ppll", 0,
+ RK3588_CLKSEL_CON(176), 6, 6, DFLAGS,
+ RK3588_CLKGATE_CON(77), 4, GFLAGS),
+ COMPOSITE_NOMUX(CLK_REF_PIPE_PHY2_PLL_SRC, "clk_ref_pipe_phy2_pll_src", "ppll", 0,
+ RK3588_CLKSEL_CON(177), 0, 6, DFLAGS,
+ RK3588_CLKGATE_CON(77), 5, GFLAGS),
+ MUX(CLK_REF_PIPE_PHY0, "clk_ref_pipe_phy0", clk_ref_pipe_phy0_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(177), 6, 1, MFLAGS),
+ MUX(CLK_REF_PIPE_PHY1, "clk_ref_pipe_phy1", clk_ref_pipe_phy1_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(177), 7, 1, MFLAGS),
+ MUX(CLK_REF_PIPE_PHY2, "clk_ref_pipe_phy2", clk_ref_pipe_phy2_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(177), 8, 1, MFLAGS),
+
+ /* pmu */
+ COMPOSITE(CLK_PMU1_300M_SRC, "clk_pmu1_300m_src", pmu_300m_24m_p, 0,
+ RK3588_PMU_CLKSEL_CON(0), 15, 1, MFLAGS, 10, 5, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(0), 3, GFLAGS),
+ COMPOSITE(CLK_PMU1_400M_SRC, "clk_pmu1_400m_src", pmu_400m_24m_p, 0,
+ RK3588_PMU_CLKSEL_CON(1), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(0), 4, GFLAGS),
+ COMPOSITE_NOMUX(CLK_PMU1_50M_SRC, "clk_pmu1_50m_src", "clk_pmu1_400m_src", 0,
+ RK3588_PMU_CLKSEL_CON(0), 0, 4, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(0), 0, GFLAGS),
+ COMPOSITE_NOMUX(CLK_PMU1_100M_SRC, "clk_pmu1_100m_src", "clk_pmu1_400m_src", 0,
+ RK3588_PMU_CLKSEL_CON(0), 4, 3, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(0), 1, GFLAGS),
+ COMPOSITE_NOMUX(CLK_PMU1_200M_SRC, "clk_pmu1_200m_src", "clk_pmu1_400m_src", 0,
+ RK3588_PMU_CLKSEL_CON(0), 7, 3, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(0), 2, GFLAGS),
+ COMPOSITE_NODIV(HCLK_PMU1_ROOT, "hclk_pmu1_root", hclk_pmu1_root_p, CLK_IS_CRITICAL,
+ RK3588_PMU_CLKSEL_CON(1), 6, 2, MFLAGS,
+ RK3588_PMU_CLKGATE_CON(0), 5, GFLAGS),
+ COMPOSITE_NODIV(PCLK_PMU1_ROOT, "pclk_pmu1_root", pmu_100m_50m_24m_src_p, CLK_IS_CRITICAL,
+ RK3588_PMU_CLKSEL_CON(1), 8, 2, MFLAGS,
+ RK3588_PMU_CLKGATE_CON(0), 7, GFLAGS),
+ GATE(PCLK_PMU0_ROOT, "pclk_pmu0_root", "pclk_pmu1_root", CLK_IS_CRITICAL,
+ RK3588_PMU_CLKGATE_CON(5), 0, GFLAGS),
+ COMPOSITE_NODIV(HCLK_PMU_CM0_ROOT, "hclk_pmu_cm0_root", hclk_pmu_cm0_root_p, CLK_IS_CRITICAL,
+ RK3588_PMU_CLKSEL_CON(1), 10, 2, MFLAGS,
+ RK3588_PMU_CLKGATE_CON(0), 8, GFLAGS),
+ GATE(CLK_PMU0, "clk_pmu0", "xin24m", CLK_IS_CRITICAL,
+ RK3588_PMU_CLKGATE_CON(5), 1, GFLAGS),
+ GATE(PCLK_PMU0, "pclk_pmu0", "pclk_pmu0_root", CLK_IS_CRITICAL,
+ RK3588_PMU_CLKGATE_CON(5), 2, GFLAGS),
+ GATE(PCLK_PMU0IOC, "pclk_pmu0ioc", "pclk_pmu0_root", CLK_IS_CRITICAL,
+ RK3588_PMU_CLKGATE_CON(5), 4, GFLAGS),
+ GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pmu0_root", 0,
+ RK3588_PMU_CLKGATE_CON(5), 5, GFLAGS),
+ COMPOSITE_NODIV(DBCLK_GPIO0, "dbclk_gpio0", mux_24m_32k_p, 0,
+ RK3588_PMU_CLKSEL_CON(17), 0, 1, MFLAGS,
+ RK3588_PMU_CLKGATE_CON(5), 6, GFLAGS),
+ GATE(PCLK_I2C0, "pclk_i2c0", "pclk_pmu0_root", 0,
+ RK3588_PMU_CLKGATE_CON(2), 1, GFLAGS),
+ COMPOSITE_NODIV(CLK_I2C0, "clk_i2c0", pmu_200m_100m_p, 0,
+ RK3588_PMU_CLKSEL_CON(3), 6, 1, MFLAGS,
+ RK3588_PMU_CLKGATE_CON(2), 2, GFLAGS),
+ GATE(HCLK_I2S1_8CH, "hclk_i2s1_8ch", "hclk_pmu1_root", 0,
+ RK3588_PMU_CLKGATE_CON(2), 7, GFLAGS),
+ COMPOSITE_NOMUX(CLK_I2S1_8CH_TX_SRC, "clk_i2s1_8ch_tx_src", "cpll", 0,
+ RK3588_PMU_CLKSEL_CON(5), 2, 5, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(2), 8, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S1_8CH_TX_FRAC, "clk_i2s1_8ch_tx_frac", "clk_i2s1_8ch_tx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_PMU_CLKSEL_CON(6), 0,
+ RK3588_PMU_CLKGATE_CON(2), 9, GFLAGS,
+ &rk3588_i2s1_8ch_tx_fracmux),
+ GATE(MCLK_I2S1_8CH_TX, "mclk_i2s1_8ch_tx", "clk_i2s1_8ch_tx", 0,
+ RK3588_PMU_CLKGATE_CON(2), 10, GFLAGS),
+ COMPOSITE_NOMUX(CLK_I2S1_8CH_RX_SRC, "clk_i2s1_8ch_rx_src", "cpll", 0,
+ RK3588_PMU_CLKSEL_CON(7), 2, 5, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(2), 11, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S1_8CH_RX_FRAC, "clk_i2s1_8ch_rx_frac", "clk_i2s1_8ch_rx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_PMU_CLKSEL_CON(8), 0,
+ RK3588_PMU_CLKGATE_CON(2), 12, GFLAGS,
+ &rk3588_i2s1_8ch_rx_fracmux),
+ GATE(MCLK_I2S1_8CH_RX, "mclk_i2s1_8ch_rx", "clk_i2s1_8ch_rx", 0,
+ RK3588_PMU_CLKGATE_CON(2), 13, GFLAGS),
+ MUX(I2S1_8CH_MCLKOUT, "i2s1_8ch_mclkout", i2s1_8ch_mclkout_p, CLK_SET_RATE_PARENT,
+ RK3588_PMU_CLKSEL_CON(9), 2, 2, MFLAGS),
+ GATE(PCLK_PMU1, "pclk_pmu1", "pclk_pmu0_root", CLK_IS_CRITICAL,
+ RK3588_PMU_CLKGATE_CON(1), 0, GFLAGS),
+ GATE(CLK_DDR_FAIL_SAFE, "clk_ddr_fail_safe", "clk_pmu0", CLK_IGNORE_UNUSED,
+ RK3588_PMU_CLKGATE_CON(1), 1, GFLAGS),
+ GATE(CLK_PMU1, "clk_pmu1", "clk_pmu0", CLK_IS_CRITICAL,
+ RK3588_PMU_CLKGATE_CON(1), 3, GFLAGS),
+ GATE(HCLK_PDM0, "hclk_pdm0", "hclk_pmu1_root", 0,
+ RK3588_PMU_CLKGATE_CON(2), 14, GFLAGS),
+ COMPOSITE_NODIV(MCLK_PDM0, "mclk_pdm0", mclk_pdm0_p, 0,
+ RK3588_PMU_CLKSEL_CON(9), 4, 1, MFLAGS,
+ RK3588_PMU_CLKGATE_CON(2), 15, GFLAGS),
+ GATE(HCLK_VAD, "hclk_vad", "hclk_pmu1_root", 0,
+ RK3588_PMU_CLKGATE_CON(3), 0, GFLAGS),
+ GATE(FCLK_PMU_CM0_CORE, "fclk_pmu_cm0_core", "hclk_pmu_cm0_root", CLK_IS_CRITICAL,
+ RK3588_PMU_CLKGATE_CON(0), 13, GFLAGS),
+ COMPOSITE(CLK_PMU_CM0_RTC, "clk_pmu_cm0_rtc", mux_24m_32k_p, CLK_IS_CRITICAL,
+ RK3588_PMU_CLKSEL_CON(2), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(0), 15, GFLAGS),
+ GATE(PCLK_PMU1_IOC, "pclk_pmu1_ioc", "pclk_pmu0_root", CLK_IGNORE_UNUSED,
+ RK3588_PMU_CLKGATE_CON(1), 5, GFLAGS),
+ GATE(PCLK_PMU1PWM, "pclk_pmu1pwm", "pclk_pmu0_root", 0,
+ RK3588_PMU_CLKGATE_CON(1), 12, GFLAGS),
+ COMPOSITE_NODIV(CLK_PMU1PWM, "clk_pmu1pwm", pmu_100m_50m_24m_src_p, 0,
+ RK3588_PMU_CLKSEL_CON(2), 9, 2, MFLAGS,
+ RK3588_PMU_CLKGATE_CON(1), 13, GFLAGS),
+ GATE(CLK_PMU1PWM_CAPTURE, "clk_pmu1pwm_capture", "xin24m", 0,
+ RK3588_PMU_CLKGATE_CON(1), 14, GFLAGS),
+ GATE(PCLK_PMU1TIMER, "pclk_pmu1timer", "pclk_pmu0_root", 0,
+ RK3588_PMU_CLKGATE_CON(1), 8, GFLAGS),
+ COMPOSITE_NODIV(CLK_PMU1TIMER_ROOT, "clk_pmu1timer_root", pmu_24m_32k_100m_src_p, 0,
+ RK3588_PMU_CLKSEL_CON(2), 7, 2, MFLAGS,
+ RK3588_PMU_CLKGATE_CON(1), 9, GFLAGS),
+ GATE(CLK_PMU1TIMER0, "clk_pmu1timer0", "clk_pmu1timer_root", 0,
+ RK3588_PMU_CLKGATE_CON(1), 10, GFLAGS),
+ GATE(CLK_PMU1TIMER1, "clk_pmu1timer1", "clk_pmu1timer_root", 0,
+ RK3588_PMU_CLKGATE_CON(1), 11, GFLAGS),
+ COMPOSITE_NOMUX(CLK_UART0_SRC, "clk_uart0_src", "cpll", 0,
+ RK3588_PMU_CLKSEL_CON(3), 7, 5, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(2), 3, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART0_FRAC, "clk_uart0_frac", "clk_uart0_src", CLK_SET_RATE_PARENT,
+ RK3588_PMU_CLKSEL_CON(4), 0,
+ RK3588_PMU_CLKGATE_CON(2), 4, GFLAGS,
+ &rk3588_uart0_fracmux),
+ GATE(SCLK_UART0, "sclk_uart0", "clk_uart0", 0,
+ RK3588_PMU_CLKGATE_CON(2), 5, GFLAGS),
+ GATE(PCLK_UART0, "pclk_uart0", "pclk_pmu0_root", 0,
+ RK3588_PMU_CLKGATE_CON(2), 6, GFLAGS),
+ GATE(PCLK_PMU1WDT, "pclk_pmu1wdt", "pclk_pmu0_root", 0,
+ RK3588_PMU_CLKGATE_CON(1), 6, GFLAGS),
+ COMPOSITE_NODIV(TCLK_PMU1WDT, "tclk_pmu1wdt", mux_24m_32k_p, 0,
+ RK3588_PMU_CLKSEL_CON(2), 6, 1, MFLAGS,
+ RK3588_PMU_CLKGATE_CON(1), 7, GFLAGS),
+ COMPOSITE(CLK_CR_PARA, "clk_cr_para", mux_24m_ppll_spll_p, 0,
+ RK3588_PMU_CLKSEL_CON(15), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(4), 11, GFLAGS),
+ COMPOSITE(CLK_USB2PHY_HDPTXRXPHY_REF, "clk_usb2phy_hdptxrxphy_ref", mux_24m_ppll_p,
+ CLK_IS_CRITICAL,
+ RK3588_PMU_CLKSEL_CON(14), 14, 1, MFLAGS, 9, 5, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(4), 7, GFLAGS),
+ COMPOSITE(CLK_USBDPPHY_MIPIDCPPHY_REF, "clk_usbdpphy_mipidcpphy_ref", mux_24m_ppll_spll_p,
+ CLK_IS_CRITICAL,
+ RK3588_PMU_CLKSEL_CON(14), 7, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(4), 3, GFLAGS),
+
+ GATE(CLK_PHY0_REF_ALT_P, "clk_phy0_ref_alt_p", "ppll", 0,
+ RK3588_PHYREF_ALT_GATE, 0, GFLAGS),
+ GATE(CLK_PHY0_REF_ALT_M, "clk_phy0_ref_alt_m", "ppll", 0,
+ RK3588_PHYREF_ALT_GATE, 1, GFLAGS),
+ GATE(CLK_PHY1_REF_ALT_P, "clk_phy1_ref_alt_p", "ppll", 0,
+ RK3588_PHYREF_ALT_GATE, 2, GFLAGS),
+ GATE(CLK_PHY1_REF_ALT_M, "clk_phy1_ref_alt_m", "ppll", 0,
+ RK3588_PHYREF_ALT_GATE, 3, GFLAGS),
+
+ GATE(HCLK_SPDIFRX0, "hclk_spdifrx0", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(63), 12, GFLAGS),
+ GATE(HCLK_SPDIFRX1, "hclk_spdifrx1", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(63), 14, GFLAGS),
+ GATE(HCLK_SPDIFRX2, "hclk_spdifrx2", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(64), 0, GFLAGS),
+ GATE(HCLK_SPDIF4, "hclk_spdif4", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(63), 8, GFLAGS),
+ GATE(HCLK_SPDIF3, "hclk_spdif3", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(63), 4, GFLAGS),
+ GATE(HCLK_I2S6_8CH, "hclk_i2s6_8ch", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(63), 3, GFLAGS),
+ GATE(HCLK_I2S5_8CH, "hclk_i2s5_8ch", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(62), 12, GFLAGS),
+ GATE(HCLK_I2S9_8CH, "hclk_i2s9_8ch", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(65), 0, GFLAGS),
+ GATE(HCLK_I2S7_8CH, "hclk_i2s7_8ch", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(60), 0, GFLAGS),
+ GATE(HCLK_I2S10_8CH, "hclk_i2s10_8ch", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(65), 4, GFLAGS),
+ GATE(ACLK_HDCP1, "aclk_hdcp1", "aclk_hdcp1_pre", 0,
+ RK3588_CLKGATE_CON(60), 5, GFLAGS),
+ GATE(HCLK_HDCP1, "hclk_hdcp1", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(60), 6, GFLAGS),
+ GATE(HCLK_SPDIF5_DP1, "hclk_spdif5_dp1", "hclk_vo0", 0,
+ RK3588_CLKGATE_CON(57), 7, GFLAGS),
+ GATE(HCLK_SPDIF2_DP0, "hclk_spdif2_dp0", "hclk_vo0", 0,
+ RK3588_CLKGATE_CON(57), 2, GFLAGS),
+ GATE(HCLK_I2S8_8CH, "hclk_i2s8_8ch", "hclk_vo0", 0,
+ RK3588_CLKGATE_CON(56), 14, GFLAGS),
+ GATE(HCLK_I2S4_8CH, "hclk_i2s4_8ch", "hclk_vo0", 0,
+ RK3588_CLKGATE_CON(56), 10, GFLAGS),
+ GATE(ACLK_HDCP0, "aclk_hdcp0", "aclk_hdcp0_pre", 0,
+ RK3588_CLKGATE_CON(55), 12, GFLAGS),
+ GATE(HCLK_HDCP0, "hclk_hdcp0", "hclk_vo0", 0,
+ RK3588_CLKGATE_CON(55), 13, GFLAGS),
+ GATE(HCLK_RKVENC1, "hclk_rkvenc1", "hclk_rkvenc1_pre", 0,
+ RK3588_CLKGATE_CON(48), 4, GFLAGS),
+ GATE(ACLK_RKVENC1, "aclk_rkvenc1", "aclk_rkvenc1_pre", 0,
+ RK3588_CLKGATE_CON(48), 5, GFLAGS),
+ GATE(ACLK_VPU, "aclk_vpu", "aclk_vdpu_low_pre", 0,
+ RK3588_CLKGATE_CON(44), 8, GFLAGS),
+ GATE(ACLK_IEP2P0, "aclk_iep2p0", "aclk_vdpu_low_pre", 0,
+ RK3588_CLKGATE_CON(45), 5, GFLAGS),
+ GATE(ACLK_JPEG_ENCODER0, "aclk_jpeg_encoder0", "aclk_vdpu_low_pre", 0,
+ RK3588_CLKGATE_CON(44), 10, GFLAGS),
+ GATE(ACLK_JPEG_ENCODER1, "aclk_jpeg_encoder1", "aclk_vdpu_low_pre", 0,
+ RK3588_CLKGATE_CON(44), 12, GFLAGS),
+ GATE(ACLK_JPEG_ENCODER2, "aclk_jpeg_encoder2", "aclk_vdpu_low_pre", 0,
+ RK3588_CLKGATE_CON(44), 14, GFLAGS),
+ GATE(ACLK_JPEG_ENCODER3, "aclk_jpeg_encoder3", "aclk_vdpu_low_pre", 0,
+ RK3588_CLKGATE_CON(45), 0, GFLAGS),
+ GATE(ACLK_JPEG_DECODER, "aclk_jpeg_decoder", "aclk_jpeg_decoder_pre", 0,
+ RK3588_CLKGATE_CON(45), 2, GFLAGS),
+ GATE(ACLK_USB3OTG1, "aclk_usb3otg1", "aclk_usb", 0,
+ RK3588_CLKGATE_CON(42), 7, GFLAGS),
+ GATE(HCLK_HOST0, "hclk_host0", "hclk_usb", 0,
+ RK3588_CLKGATE_CON(42), 10, GFLAGS),
+ GATE(HCLK_HOST_ARB0, "hclk_host_arb0", "hclk_usb", 0,
+ RK3588_CLKGATE_CON(42), 11, GFLAGS),
+ GATE(HCLK_HOST1, "hclk_host1", "hclk_usb", 0,
+ RK3588_CLKGATE_CON(42), 12, GFLAGS),
+ GATE(HCLK_HOST_ARB1, "hclk_host_arb1", "hclk_usb", 0,
+ RK3588_CLKGATE_CON(42), 13, GFLAGS),
+ GATE(ACLK_USB3OTG0, "aclk_usb3otg0", "aclk_usb", 0,
+ RK3588_CLKGATE_CON(42), 4, GFLAGS),
+ MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "scmi_cclk_sd", RK3588_SDMMC_CON0, 1),
+ MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "scmi_cclk_sd", RK3588_SDMMC_CON1, 1),
+ GATE(HCLK_SDIO, "hclk_sdio", "hclk_sdio_pre", 0,
+ RK3588_CLKGATE_CON(75), 2, GFLAGS),
+ GATE(HCLK_RKVDEC1, "hclk_rkvdec1", "hclk_rkvdec1_pre", 0,
+ RK3588_CLKGATE_CON(41), 2, GFLAGS),
+ GATE(ACLK_RKVDEC1, "aclk_rkvdec1", "aclk_rkvdec1_pre", 0,
+ RK3588_CLKGATE_CON(41), 3, GFLAGS),
+ GATE(HCLK_RKVDEC0, "hclk_rkvdec0", "hclk_rkvdec0_pre", 0,
+ RK3588_CLKGATE_CON(40), 3, GFLAGS),
+ GATE(ACLK_RKVDEC0, "aclk_rkvdec0", "aclk_rkvdec0_pre", 0,
+ RK3588_CLKGATE_CON(40), 4, GFLAGS),
+ GATE(CLK_PCIE4L_PIPE, "clk_pcie4l_pipe", "clk_pipe30phy_pipe0_i", 0,
+ RK3588_CLKGATE_CON(39), 0, GFLAGS),
+ GATE(CLK_PCIE2L_PIPE, "clk_pcie2l_pipe", "clk_pipe30phy_pipe2_i", 0,
+ RK3588_CLKGATE_CON(39), 1, GFLAGS),
+ GATE(CLK_PIPEPHY0_PIPE_G, "clk_pipephy0_pipe_g", "clk_pipephy0_pipe_i", 0,
+ RK3588_CLKGATE_CON(38), 3, GFLAGS),
+ GATE(CLK_PIPEPHY1_PIPE_G, "clk_pipephy1_pipe_g", "clk_pipephy1_pipe_i", 0,
+ RK3588_CLKGATE_CON(38), 4, GFLAGS),
+ GATE(CLK_PIPEPHY2_PIPE_G, "clk_pipephy2_pipe_g", "clk_pipephy2_pipe_i", 0,
+ RK3588_CLKGATE_CON(38), 5, GFLAGS),
+ GATE(CLK_PIPEPHY0_PIPE_ASIC_G, "clk_pipephy0_pipe_asic_g", "clk_pipephy0_pipe_i", 0,
+ RK3588_CLKGATE_CON(38), 6, GFLAGS),
+ GATE(CLK_PIPEPHY1_PIPE_ASIC_G, "clk_pipephy1_pipe_asic_g", "clk_pipephy1_pipe_i", 0,
+ RK3588_CLKGATE_CON(38), 7, GFLAGS),
+ GATE(CLK_PIPEPHY2_PIPE_ASIC_G, "clk_pipephy2_pipe_asic_g", "clk_pipephy2_pipe_i", 0,
+ RK3588_CLKGATE_CON(38), 8, GFLAGS),
+ GATE(CLK_PIPEPHY2_PIPE_U3_G, "clk_pipephy2_pipe_u3_g", "clk_pipephy2_pipe_i", 0,
+ RK3588_CLKGATE_CON(38), 9, GFLAGS),
+ GATE(CLK_PCIE1L2_PIPE, "clk_pcie1l2_pipe", "clk_pipephy0_pipe_g", 0,
+ RK3588_CLKGATE_CON(38), 13, GFLAGS),
+ GATE(CLK_PCIE1L0_PIPE, "clk_pcie1l0_pipe", "clk_pipephy1_pipe_g", 0,
+ RK3588_CLKGATE_CON(38), 14, GFLAGS),
+ GATE(CLK_PCIE1L1_PIPE, "clk_pcie1l1_pipe", "clk_pipephy2_pipe_g", 0,
+ RK3588_CLKGATE_CON(38), 15, GFLAGS),
+ GATE(HCLK_SFC, "hclk_sfc", "hclk_nvm", 0,
+ RK3588_CLKGATE_CON(31), 10, GFLAGS),
+ GATE(HCLK_SFC_XIP, "hclk_sfc_xip", "hclk_nvm", 0,
+ RK3588_CLKGATE_CON(31), 11, GFLAGS),
+ GATE(HCLK_EMMC, "hclk_emmc", "hclk_nvm", 0,
+ RK3588_CLKGATE_CON(31), 4, GFLAGS),
+ GATE(ACLK_ISP1, "aclk_isp1", "aclk_isp1_pre", 0,
+ RK3588_CLKGATE_CON(26), 5, GFLAGS),
+ GATE(HCLK_ISP1, "hclk_isp1", "hclk_isp1_pre", 0,
+ RK3588_CLKGATE_CON(26), 7, GFLAGS),
+ GATE(PCLK_AV1, "pclk_av1", "pclk_av1_pre", 0,
+ RK3588_CLKGATE_CON(68), 5, GFLAGS),
+ GATE(ACLK_AV1, "aclk_av1", "aclk_av1_pre", 0,
+ RK3588_CLKGATE_CON(68), 2, GFLAGS),
+
+ GATE_LINK(ACLK_ISP1_PRE, "aclk_isp1_pre", "aclk_isp1_root", "aclk_vi_root", 0, RK3588_CLKGATE_CON(26), 6, GFLAGS),
+ GATE_LINK(HCLK_ISP1_PRE, "hclk_isp1_pre", "hclk_isp1_root", "hclk_vi_root", 0, RK3588_CLKGATE_CON(26), 8, GFLAGS),
+ GATE_LINK(HCLK_NVM, "hclk_nvm", "hclk_nvm_root", "aclk_nvm_root", 0, RK3588_CLKGATE_CON(31), 2, GFLAGS),
+ GATE_LINK(ACLK_USB, "aclk_usb", "aclk_usb_root", "aclk_vo1usb_top_root", 0, RK3588_CLKGATE_CON(42), 2, GFLAGS),
+ GATE_LINK(HCLK_USB, "hclk_usb", "hclk_usb_root", "hclk_vo1usb_top_root", 0, RK3588_CLKGATE_CON(42), 3, GFLAGS),
+ GATE_LINK(ACLK_JPEG_DECODER_PRE, "aclk_jpeg_decoder_pre", "aclk_jpeg_decoder_root", "aclk_vdpu_root", 0, RK3588_CLKGATE_CON(44), 7, GFLAGS),
+ GATE_LINK(ACLK_VDPU_LOW_PRE, "aclk_vdpu_low_pre", "aclk_vdpu_low_root", "aclk_vdpu_root", 0, RK3588_CLKGATE_CON(44), 5, GFLAGS),
+ GATE_LINK(ACLK_RKVENC1_PRE, "aclk_rkvenc1_pre", "aclk_rkvenc1_root", "aclk_rkvenc0", 0, RK3588_CLKGATE_CON(48), 3, GFLAGS),
+ GATE_LINK(HCLK_RKVENC1_PRE, "hclk_rkvenc1_pre", "hclk_rkvenc1_root", "hclk_rkvenc0", 0, RK3588_CLKGATE_CON(48), 2, GFLAGS),
+ GATE_LINK(HCLK_RKVDEC0_PRE, "hclk_rkvdec0_pre", "hclk_rkvdec0_root", "hclk_vdpu_root", 0, RK3588_CLKGATE_CON(40), 5, GFLAGS),
+ GATE_LINK(ACLK_RKVDEC0_PRE, "aclk_rkvdec0_pre", "aclk_rkvdec0_root", "aclk_vdpu_root", 0, RK3588_CLKGATE_CON(40), 6, GFLAGS),
+ GATE_LINK(HCLK_RKVDEC1_PRE, "hclk_rkvdec1_pre", "hclk_rkvdec1_root", "hclk_vdpu_root", 0, RK3588_CLKGATE_CON(41), 4, GFLAGS),
+ GATE_LINK(ACLK_RKVDEC1_PRE, "aclk_rkvdec1_pre", "aclk_rkvdec1_root", "aclk_vdpu_root", 0, RK3588_CLKGATE_CON(41), 5, GFLAGS),
+ GATE_LINK(ACLK_HDCP0_PRE, "aclk_hdcp0_pre", "aclk_vo0_root", "aclk_vop_low_root", 0, RK3588_CLKGATE_CON(55), 9, GFLAGS),
+ GATE_LINK(HCLK_VO0, "hclk_vo0", "hclk_vo0_root", "hclk_vop_root", 0, RK3588_CLKGATE_CON(55), 5, GFLAGS),
+ GATE_LINK(ACLK_HDCP1_PRE, "aclk_hdcp1_pre", "aclk_hdcp1_root", "aclk_vo1usb_top_root", 0, RK3588_CLKGATE_CON(59), 6, GFLAGS),
+ GATE_LINK(HCLK_VO1, "hclk_vo1", "hclk_vo1_root", "hclk_vo1usb_top_root", 0, RK3588_CLKGATE_CON(59), 9, GFLAGS),
+ GATE_LINK(ACLK_AV1_PRE, "aclk_av1_pre", "aclk_av1_root", "aclk_vdpu_root", 0, RK3588_CLKGATE_CON(68), 1, GFLAGS),
+ GATE_LINK(PCLK_AV1_PRE, "pclk_av1_pre", "pclk_av1_root", "hclk_vdpu_root", 0, RK3588_CLKGATE_CON(68), 4, GFLAGS),
+ GATE_LINK(HCLK_SDIO_PRE, "hclk_sdio_pre", "hclk_sdio_root", "hclk_nvm", 0, RK3588_CLKGATE_CON(75), 1, GFLAGS),
+};
+
+static void __init rk3588_clk_init(struct device_node *np)
+{
+ struct rockchip_clk_provider *ctx;
+ void __iomem *reg_base;
+
+ reg_base = of_iomap(np, 0);
+ if (!reg_base) {
+ pr_err("%s: could not map cru region\n", __func__);
+ return;
+ }
+
+ ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+ if (IS_ERR(ctx)) {
+ pr_err("%s: rockchip clk init failed\n", __func__);
+ return;
+ }
+
+ rockchip_clk_register_plls(ctx, rk3588_pll_clks,
+ ARRAY_SIZE(rk3588_pll_clks),
+ RK3588_GRF_SOC_STATUS0);
+
+ rockchip_clk_register_armclk(ctx, ARMCLK_L, "armclk_l",
+ mux_armclkl_p, ARRAY_SIZE(mux_armclkl_p),
+ &rk3588_cpulclk_data, rk3588_cpulclk_rates,
+ ARRAY_SIZE(rk3588_cpulclk_rates));
+ rockchip_clk_register_armclk(ctx, ARMCLK_B01, "armclk_b01",
+ mux_armclkb01_p, ARRAY_SIZE(mux_armclkb01_p),
+ &rk3588_cpub0clk_data, rk3588_cpub0clk_rates,
+ ARRAY_SIZE(rk3588_cpub0clk_rates));
+ rockchip_clk_register_armclk(ctx, ARMCLK_B23, "armclk_b23",
+ mux_armclkb23_p, ARRAY_SIZE(mux_armclkb23_p),
+ &rk3588_cpub1clk_data, rk3588_cpub1clk_rates,
+ ARRAY_SIZE(rk3588_cpub1clk_rates));
+
+ rockchip_clk_register_branches(ctx, rk3588_clk_branches,
+ ARRAY_SIZE(rk3588_clk_branches));
+
+ rk3588_rst_init(np, reg_base);
+
+ rockchip_register_restart_notifier(ctx, RK3588_GLB_SRST_FST);
+
+ rockchip_clk_of_add_provider(np, ctx);
+}
+
+struct clk_rk3588_inits {
+ void (*inits)(struct device_node *np);
+};
+
+static const struct clk_rk3588_inits clk_3588_cru_init = {
+ .inits = rk3588_clk_init,
+};
+
+static const struct of_device_id clk_rk3588_match_table[] = {
+ {
+ .compatible = "rockchip,rk3588-cru",
+ .data = &clk_3588_cru_init,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, clk_rk3588_match_table);
+
+static int __init clk_rk3588_probe(struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ const struct clk_rk3588_inits *init_data;
+
+ init_data = of_device_get_match_data(dev);
+ if (init_data->inits)
+ init_data->inits(np);
+
+ return 0;
+}
+
+static struct driver clk_rk3588_driver = {
+ .probe = clk_rk3588_probe,
+ .name = "clk-rk3588",
+ .of_compatible = DRV_OF_COMPAT(clk_rk3588_match_table),
+};
+
+core_platform_driver(clk_rk3588_driver);
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index 833e9bed0e..aca107a45d 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -3,6 +3,9 @@
* Copyright (c) 2014 MundoReader S.L.
* Author: Heiko Stuebner <heiko@sntech.de>
*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Xing Zheng <zhengxing@rock-chips.com>
+ *
* based on
*
* samsung/clk.c
@@ -14,10 +17,14 @@
#include <common.h>
#include <malloc.h>
#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <mfd/syscon.h>
+#include <linux/spinlock.h>
+#include <linux/rational.h>
+#include <restart.h>
#include "clk.h"
-#include <init.h>
-/**
+/*
* Register a clock branch.
* Most clock branches have a form like
*
@@ -28,134 +35,369 @@
* sometimes without one of those components.
*/
static struct clk *rockchip_clk_register_branch(const char *name,
- const char **parent_names, u8 num_parents, void __iomem *base,
+ const char *const *parent_names, u8 num_parents,
+ void __iomem *base,
int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags,
- u8 div_shift, u8 div_width, u8 div_flags,
+ int div_offset, u8 div_shift, u8 div_width, u8 div_flags,
struct clk_div_table *div_table, int gate_offset,
- u8 gate_shift, u8 gate_flags, unsigned long flags
- )
+ u8 gate_shift, u8 gate_flags, unsigned long flags,
+ spinlock_t *lock)
{
struct clk *clk;
- struct clk *mux = NULL;
- struct clk *gate = NULL;
- struct clk *div = NULL;
+ struct clk_mux *mux = NULL;
+ struct clk_gate *gate = NULL;
+ struct clk_divider *div = NULL;
+ int ret;
if (num_parents > 1) {
- mux = clk_mux_alloc(name, 0, base + muxdiv_offset, mux_shift,
- mux_width, parent_names, num_parents, mux_flags);
+ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
if (!mux)
return ERR_PTR(-ENOMEM);
+
+ mux->reg = base + muxdiv_offset;
+ mux->shift = mux_shift;
+ mux->width = mux_width;
+ mux->flags = mux_flags;
+ mux->lock = lock;
+ mux->hw.clk.name = basprintf("%s.mux", name);
+ mux->hw.clk.ops = (mux_flags & CLK_MUX_READ_ONLY) ? &clk_mux_ro_ops
+ : &clk_mux_ops;
}
if (gate_offset >= 0) {
- gate = clk_gate_alloc(name, *parent_names, base + gate_offset,
- gate_shift, flags, gate_flags);
- if (!gate)
- return ERR_PTR(-ENOMEM);
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ ret = -ENOMEM;
+ goto err_gate;
+ }
+
+ gate->flags = gate_flags;
+ gate->reg = base + gate_offset;
+ gate->shift = gate_shift;
+ gate->lock = lock;
+ gate->hw.clk.name = basprintf("%s.gate", name);
+ gate->hw.clk.ops = &clk_gate_ops;
}
if (div_width > 0) {
- div = clk_divider_alloc(name, *parent_names, 0,
- base + muxdiv_offset, div_shift, div_width, div_flags);
- if (!div)
- return ERR_PTR(-ENOMEM);
+ div = kzalloc(sizeof(*div), GFP_KERNEL);
+ if (!div) {
+ ret = -ENOMEM;
+ goto err_div;
+ }
+
+ div->flags = div_flags;
+ if (div_offset)
+ div->reg = base + div_offset;
+ else
+ div->reg = base + muxdiv_offset;
+ div->shift = div_shift;
+ div->width = div_width;
+ div->lock = lock;
+ div->table = div_table;
+ div->hw.clk.name = basprintf("%s.div", name);
+ div->hw.clk.ops = (div_flags & CLK_DIVIDER_READ_ONLY)
+ ? &clk_divider_ro_ops
+ : &clk_divider_ops;
}
clk = clk_register_composite(name, parent_names, num_parents,
- mux,
- div,
- gate,
- flags);
+ mux ? &mux->hw.clk : NULL,
+ div ? &div->hw.clk : NULL,
+ gate ? &gate->hw.clk : NULL,
+ flags);
+ if (IS_ERR(clk)) {
+ kfree(div);
+ kfree(gate);
+ return ERR_CAST(clk);
+ }
return clk;
+err_div:
+ kfree(gate);
+err_gate:
+ kfree(mux);
+ return ERR_PTR(ret);
}
-static struct clk *rockchip_clk_register_frac_branch(const char *name,
- const char **parent_names, u8 num_parents, void __iomem *base,
- int muxdiv_offset, u8 div_flags,
+struct rockchip_clk_frac {
+ struct clk_fractional_divider div;
+ struct clk_gate gate;
+
+ struct clk_mux mux;
+ const struct clk_ops *mux_ops;
+ int mux_frac_idx;
+
+ bool rate_change_remuxed;
+ int rate_change_idx;
+};
+
+/*
+ * fractional divider must set that denominator is 20 times larger than
+ * numerator to generate precise clock frequency.
+ */
+static void rockchip_fractional_approximation(struct clk_hw *hw,
+ unsigned long rate, unsigned long *parent_rate,
+ unsigned long *m, unsigned long *n)
+{
+ struct clk_fractional_divider *fd = to_clk_fd(hw);
+ unsigned long p_rate, p_parent_rate;
+ struct clk_hw *p_parent;
+ unsigned long scale;
+
+ p_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
+ if ((rate * 20 > p_rate) && (p_rate % rate != 0)) {
+ p_parent = clk_hw_get_parent(clk_hw_get_parent(hw));
+ p_parent_rate = clk_hw_get_rate(p_parent);
+ *parent_rate = p_parent_rate;
+ }
+
+ /*
+ * Get rate closer to *parent_rate to guarantee there is no overflow
+ * for m and n. In the result it will be the nearest rate left shifted
+ * by (scale - fd->nwidth) bits.
+ */
+ scale = fls_long(*parent_rate / rate - 1);
+ if (scale > fd->nwidth)
+ rate <<= scale - fd->nwidth;
+
+ rational_best_approximation(rate, *parent_rate,
+ GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
+ m, n);
+}
+
+static struct clk *rockchip_clk_register_frac_branch(
+ struct rockchip_clk_provider *ctx, const char *name,
+ const char *const *parent_names, u8 num_parents,
+ void __iomem *base, int muxdiv_offset, u8 div_flags,
int gate_offset, u8 gate_shift, u8 gate_flags,
- unsigned long flags)
+ unsigned long flags, struct rockchip_clk_branch *child,
+ spinlock_t *lock)
{
struct clk *clk;
- struct clk *gate = NULL;
- struct clk *div = NULL;
-
- if (gate_offset >= 0) {
- gate = clk_gate_alloc(name, *parent_names, base + gate_offset,
- gate_shift, flags, gate_flags);
- if (!gate)
- return ERR_PTR(-ENOMEM);
- }
+ struct rockchip_clk_frac *frac;
+ struct clk_gate *gate = NULL;
+ struct clk_fractional_divider *div = NULL;
if (muxdiv_offset < 0)
return ERR_PTR(-EINVAL);
- div = clk_fractional_divider_alloc(name, *parent_names, flags,
- base + muxdiv_offset, 16, 16, 0, 16, div_flags);
- if (!div)
+ if (child && child->branch_type != branch_mux) {
+ pr_err("%s: fractional child clock for %s can only be a mux\n",
+ __func__, name);
+ return ERR_PTR(-EINVAL);
+ }
+
+ frac = kzalloc(sizeof(*frac), GFP_KERNEL);
+ if (!frac)
return ERR_PTR(-ENOMEM);
+ if (gate_offset >= 0) {
+ gate = &frac->gate;
+ gate->flags = gate_flags;
+ gate->reg = base + gate_offset;
+ gate->shift = gate_shift;
+ gate->lock = lock;
+ gate->hw.clk.ops = &clk_gate_ops;
+ }
+
+ div = &frac->div;
+ div->flags = div_flags;
+ div->reg = base + muxdiv_offset;
+ div->mshift = 16;
+ div->mwidth = 16;
+ div->mmask = GENMASK(div->mwidth - 1, 0) << div->mshift;
+ div->nshift = 0;
+ div->nwidth = 16;
+ div->nmask = GENMASK(div->nwidth - 1, 0) << div->nshift;
+ div->lock = lock;
+ div->approximation = rockchip_fractional_approximation;
+ div->hw.clk.ops = &clk_fractional_divider_ops;
+
clk = clk_register_composite(name, parent_names, num_parents,
- NULL,
- div,
- gate,
- flags);
+ NULL,
+ &div->hw.clk,
+ gate ? &gate->hw.clk : NULL,
+ flags | CLK_SET_RATE_UNGATE);
+ if (IS_ERR(clk)) {
+ kfree(frac);
+ return ERR_CAST(clk);
+ }
+
+ if (child) {
+ struct clk_mux *frac_mux = &frac->mux;
+ struct clk_init_data init;
+ struct clk *mux_clk;
+
+ frac->mux_frac_idx = match_string(child->parent_names,
+ child->num_parents, name);
+ frac->mux_ops = &clk_mux_ops;
+
+ frac_mux->reg = base + child->muxdiv_offset;
+ frac_mux->shift = child->mux_shift;
+ frac_mux->width = child->mux_width;
+ frac_mux->flags = child->mux_flags;
+ frac_mux->lock = lock;
+ frac_mux->hw.init = &init;
+
+ init.name = child->name;
+ init.flags = child->flags | CLK_SET_RATE_PARENT;
+ init.ops = frac->mux_ops;
+ init.parent_names = child->parent_names;
+ init.num_parents = child->num_parents;
+
+ mux_clk = clk_register(NULL, &frac_mux->hw);
+ if (IS_ERR(mux_clk)) {
+ kfree(frac);
+ return mux_clk;
+ }
+
+ rockchip_clk_add_lookup(ctx, mux_clk, child->id);
+
+ /* notifier on the fraction divider to catch rate changes */
+ if (frac->mux_frac_idx >= 0) {
+ pr_debug("%s: found fractional parent in mux at pos %d\n",
+ __func__, frac->mux_frac_idx);
+ } else {
+ pr_warn("%s: could not find %s as parent of %s, rate changes may not work\n",
+ __func__, name, child->name);
+ }
+ }
return clk;
}
-static struct clk **clk_table;
-static void __iomem *reg_base;
-static struct clk_onecell_data clk_data;
-static struct device_node *cru_node;
+static struct clk *rockchip_clk_register_factor_branch(const char *name,
+ const char *const *parent_names, u8 num_parents,
+ void __iomem *base, unsigned int mult, unsigned int div,
+ int gate_offset, u8 gate_shift, u8 gate_flags,
+ unsigned long flags, spinlock_t *lock)
+{
+ struct clk *clk;
+ struct clk_gate *gate = NULL;
+ struct clk_fixed_factor *fix = NULL;
+
+ /* without gate, register a simple factor clock */
+ if (gate_offset == 0) {
+ return clk_register_fixed_factor(NULL, name,
+ parent_names[0], flags, mult,
+ div);
+ }
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate)
+ return ERR_PTR(-ENOMEM);
+
+ gate->flags = gate_flags;
+ gate->reg = base + gate_offset;
+ gate->shift = gate_shift;
+ gate->lock = lock;
+ gate->hw.clk.ops = &clk_gate_ops;
+
+ fix = kzalloc(sizeof(*fix), GFP_KERNEL);
+ if (!fix) {
+ kfree(gate);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ fix->mult = mult;
+ fix->div = div;
+ fix->hw.clk.ops = &clk_fixed_factor_ops;
-void __init rockchip_clk_init(struct device_node *np, void __iomem *base,
- unsigned long nr_clks)
+ clk = clk_register_composite(name, parent_names, num_parents,
+ NULL,
+ &fix->hw.clk,
+ &gate->hw.clk, flags);
+ if (IS_ERR(clk)) {
+ kfree(fix);
+ kfree(gate);
+ return ERR_CAST(clk);
+ }
+
+ return clk;
+}
+
+struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,
+ void __iomem *base,
+ unsigned long nr_clks)
{
- reg_base = base;
- cru_node = np;
+ struct rockchip_clk_provider *ctx;
+ struct clk **clk_table;
+ int i;
+
+ ctx = kzalloc(sizeof(struct rockchip_clk_provider), GFP_KERNEL);
+ if (!ctx)
+ return ERR_PTR(-ENOMEM);
- clk_table = calloc(nr_clks, sizeof(struct clk *));
+ clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
if (!clk_table)
- pr_err("%s: could not allocate clock lookup table\n", __func__);
+ goto err_free;
+
+ for (i = 0; i < nr_clks; ++i)
+ clk_table[i] = ERR_PTR(-ENOENT);
+
+ ctx->reg_base = base;
+ ctx->clk_data.clks = clk_table;
+ ctx->clk_data.clk_num = nr_clks;
+ ctx->cru_node = np;
+ spin_lock_init(&ctx->lock);
- clk_data.clks = clk_table;
- clk_data.clk_num = nr_clks;
- of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+ ctx->grf = syscon_regmap_lookup_by_phandle(ctx->cru_node,
+ "rockchip,grf");
+
+ return ctx;
+
+err_free:
+ kfree(ctx);
+ return ERR_PTR(-ENOMEM);
+}
+EXPORT_SYMBOL_GPL(rockchip_clk_init);
+
+void rockchip_clk_of_add_provider(struct device_node *np,
+ struct rockchip_clk_provider *ctx)
+{
+ if (of_clk_add_provider(np, of_clk_src_onecell_get,
+ &ctx->clk_data))
+ pr_err("%s: could not register clk provider\n", __func__);
}
+EXPORT_SYMBOL_GPL(rockchip_clk_of_add_provider);
-void rockchip_clk_add_lookup(struct clk *clk, unsigned int id)
+void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx,
+ struct clk *clk, unsigned int id)
{
- if (clk_table && id)
- clk_table[id] = clk;
+ if (ctx->clk_data.clks && id)
+ ctx->clk_data.clks[id] = clk;
}
+EXPORT_SYMBOL_GPL(rockchip_clk_add_lookup);
-void __init rockchip_clk_register_plls(struct rockchip_pll_clock *list,
+void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx,
+ struct rockchip_pll_clock *list,
unsigned int nr_pll, int grf_lock_offset)
{
struct clk *clk;
int idx;
for (idx = 0; idx < nr_pll; idx++, list++) {
- clk = rockchip_clk_register_pll(list->type, list->name,
+ clk = rockchip_clk_register_pll(ctx, list->type, list->name,
list->parent_names, list->num_parents,
- reg_base, list->con_offset, grf_lock_offset,
+ list->con_offset, grf_lock_offset,
list->lock_shift, list->mode_offset,
list->mode_shift, list->rate_table,
- list->pll_flags);
+ list->flags, list->pll_flags);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
continue;
}
- rockchip_clk_add_lookup(clk, list->id);
+ rockchip_clk_add_lookup(ctx, clk, list->id);
}
}
+EXPORT_SYMBOL_GPL(rockchip_clk_register_plls);
-void __init rockchip_clk_register_branches(
- struct rockchip_clk_branch *list,
- unsigned int nr_clk)
+void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
+ struct rockchip_clk_branch *list,
+ unsigned int nr_clk)
{
struct clk *clk = NULL;
unsigned int idx;
@@ -167,50 +409,89 @@ void __init rockchip_clk_register_branches(
/* catch simple muxes */
switch (list->branch_type) {
case branch_mux:
- clk = clk_mux(list->name, flags,
- reg_base + list->muxdiv_offset, list->mux_shift,
- list->mux_width, list->parent_names,
- list->num_parents, list->mux_flags);
+ clk = clk_register_mux(NULL, list->name,
+ list->parent_names, list->num_parents,
+ flags, ctx->reg_base + list->muxdiv_offset,
+ list->mux_shift, list->mux_width,
+ list->mux_flags, &ctx->lock);
+ break;
+ case branch_muxgrf:
+ clk = rockchip_clk_register_muxgrf(list->name,
+ list->parent_names, list->num_parents,
+ flags, ctx->grf, list->muxdiv_offset,
+ list->mux_shift, list->mux_width,
+ list->mux_flags);
break;
case branch_divider:
if (list->div_table)
- clk = clk_divider_table(list->name,
- list->parent_names[0], flags,
- reg_base + list->muxdiv_offset,
- list->div_shift, list->div_width,
- list->div_table, list->div_flags);
+ clk = clk_register_divider_table(NULL,
+ list->name, list->parent_names[0],
+ flags,
+ ctx->reg_base + list->muxdiv_offset,
+ list->div_shift, list->div_width,
+ list->div_flags, list->div_table,
+ &ctx->lock);
else
- clk = clk_divider(list->name,
- list->parent_names[0], flags,
- reg_base + list->muxdiv_offset,
- list->div_shift, list->div_width,
- list->div_flags);
+ clk = clk_register_divider(NULL, list->name,
+ list->parent_names[0], flags,
+ ctx->reg_base + list->muxdiv_offset,
+ list->div_shift, list->div_width,
+ list->div_flags, &ctx->lock);
break;
case branch_fraction_divider:
- clk = rockchip_clk_register_frac_branch(list->name,
+ clk = rockchip_clk_register_frac_branch(ctx, list->name,
list->parent_names, list->num_parents,
- reg_base, list->muxdiv_offset, list->div_flags,
+ ctx->reg_base, list->muxdiv_offset,
+ list->div_flags,
list->gate_offset, list->gate_shift,
- list->gate_flags, flags);
+ list->gate_flags, flags, list->child,
+ &ctx->lock);
+ break;
+ case branch_half_divider:
break;
case branch_gate:
flags |= CLK_SET_RATE_PARENT;
- clk = clk_gate(list->name, list->parent_names[0],
- reg_base + list->gate_offset, list->gate_shift,
- flags, list->gate_flags);
+ clk = clk_register_gate(NULL, list->name,
+ list->parent_names[0], flags,
+ ctx->reg_base + list->gate_offset,
+ list->gate_shift, list->gate_flags, &ctx->lock);
break;
case branch_composite:
clk = rockchip_clk_register_branch(list->name,
list->parent_names, list->num_parents,
- reg_base, list->muxdiv_offset, list->mux_shift,
+ ctx->reg_base, list->muxdiv_offset,
+ list->mux_shift,
list->mux_width, list->mux_flags,
- list->div_shift, list->div_width,
+ list->div_offset, list->div_shift, list->div_width,
list->div_flags, list->div_table,
list->gate_offset, list->gate_shift,
- list->gate_flags, flags);
+ list->gate_flags, flags, &ctx->lock);
break;
case branch_mmc:
+ clk = rockchip_clk_register_mmc(
+ list->name,
+ list->parent_names, list->num_parents,
+ ctx->reg_base + list->muxdiv_offset,
+ list->div_shift
+ );
+ break;
+ case branch_inverter:
+ clk = rockchip_clk_register_inverter(
+ list->name, list->parent_names,
+ list->num_parents,
+ ctx->reg_base + list->muxdiv_offset,
+ list->div_shift, list->div_flags, &ctx->lock);
+ break;
+ case branch_factor:
+ clk = rockchip_clk_register_factor_branch(
+ list->name, list->parent_names,
+ list->num_parents, ctx->reg_base,
+ list->div_shift, list->div_width,
+ list->gate_offset, list->gate_shift,
+ list->gate_flags, flags, &ctx->lock);
+ break;
+ case branch_ddrclk:
break;
}
@@ -227,32 +508,36 @@ void __init rockchip_clk_register_branches(
continue;
}
- rockchip_clk_add_lookup(clk, list->id);
+ rockchip_clk_add_lookup(ctx, clk, list->id);
}
}
-
-void __init rockchip_clk_register_armclk(unsigned int lookup_id,
- const char *name, const char **parent_names,
- u8 num_parents,
- const struct rockchip_cpuclk_reg_data *reg_data,
- const struct rockchip_cpuclk_rate_table *rates,
- int nrates)
+EXPORT_SYMBOL_GPL(rockchip_clk_register_branches);
+
+void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx,
+ unsigned int lookup_id,
+ const char *name, const char *const *parent_names,
+ u8 num_parents,
+ const struct rockchip_cpuclk_reg_data *reg_data,
+ const struct rockchip_cpuclk_rate_table *rates,
+ int nrates)
{
struct clk *clk;
clk = rockchip_clk_register_cpuclk(name, parent_names, num_parents,
- reg_data, rates, nrates, reg_base
- );
+ reg_data, rates, nrates,
+ ctx->reg_base, &ctx->lock);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s: %ld\n",
__func__, name, PTR_ERR(clk));
return;
}
- rockchip_clk_add_lookup(clk, lookup_id);
+ rockchip_clk_add_lookup(ctx, clk, lookup_id);
}
+EXPORT_SYMBOL_GPL(rockchip_clk_register_armclk);
-void __init rockchip_clk_protect_critical(const char *clocks[], int nclocks)
+void rockchip_clk_protect_critical(const char *const clocks[],
+ int nclocks)
{
int i;
@@ -260,7 +545,34 @@ void __init rockchip_clk_protect_critical(const char *clocks[], int nclocks)
for (i = 0; i < nclocks; i++) {
struct clk *clk = __clk_lookup(clocks[i]);
- if (clk)
- clk_enable(clk);
+ clk_enable(clk);
}
}
+EXPORT_SYMBOL_GPL(rockchip_clk_protect_critical);
+
+static void rockchip_restart(struct restart_handler *this)
+{
+ struct rockchip_clk_provider *ctx =
+ container_of(this, struct rockchip_clk_provider, restart_handler);
+
+ writel(0xfdb9, ctx->reg_base + ctx->reg_restart);
+ mdelay(1000);
+}
+
+void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx,
+ unsigned int reg)
+{
+ int ret;
+
+ ctx->restart_handler.name = "rockchip-pmu",
+ ctx->restart_handler.restart = rockchip_restart,
+ ctx->restart_handler.priority = RESTART_DEFAULT_PRIORITY,
+
+ ctx->reg_restart = reg;
+
+ ret = restart_handler_register(&ctx->restart_handler);
+ if (ret)
+ pr_err("%s: cannot register restart handler, %d\n",
+ __func__, ret);
+}
+EXPORT_SYMBOL_GPL(rockchip_register_restart_notifier);
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 006225b7e8..df819c61f1 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -3,6 +3,9 @@
* Copyright (c) 2014 MundoReader S.L.
* Author: Heiko Stuebner <heiko@sntech.de>
*
+ * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
+ * Author: Xing Zheng <zhengxing@rock-chips.com>
+ *
* based on
*
* samsung/clk.h
@@ -16,31 +19,97 @@
#include <io.h>
#include <linux/clk.h>
-
-/* To keep changes from kernel smaller */
-#define CLK_GATE_SET_TO_DISABLE CLK_GATE_INVERTED
-#define CLK_GET_RATE_NOCACHE 0
+#include <restart.h>
#define HIWORD_UPDATE(val, mask, shift) \
((val) << (shift) | (mask) << ((shift) + 16))
-/* register positions shared by RK2928, RK3066 and RK3188 */
-#define RK2928_PLL_CON(x) (x * 0x4)
+/* register positions shared by PX30, RV1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */
+#define BOOST_PLL_H_CON(x) ((x) * 0x4)
+#define BOOST_CLK_CON 0x0008
+#define BOOST_BOOST_CON 0x000c
+#define BOOST_SWITCH_CNT 0x0010
+#define BOOST_HIGH_PERF_CNT0 0x0014
+#define BOOST_HIGH_PERF_CNT1 0x0018
+#define BOOST_STATIS_THRESHOLD 0x001c
+#define BOOST_SHORT_SWITCH_CNT 0x0020
+#define BOOST_SWITCH_THRESHOLD 0x0024
+#define BOOST_FSM_STATUS 0x0028
+#define BOOST_PLL_L_CON(x) ((x) * 0x4 + 0x2c)
+#define BOOST_RECOVERY_MASK 0x1
+#define BOOST_RECOVERY_SHIFT 1
+#define BOOST_SW_CTRL_MASK 0x1
+#define BOOST_SW_CTRL_SHIFT 2
+#define BOOST_LOW_FREQ_EN_MASK 0x1
+#define BOOST_LOW_FREQ_EN_SHIFT 3
+#define BOOST_BUSY_STATE BIT(8)
+
+#define PX30_PLL_CON(x) ((x) * 0x4)
+#define PX30_CLKSEL_CON(x) ((x) * 0x4 + 0x100)
+#define PX30_CLKGATE_CON(x) ((x) * 0x4 + 0x200)
+#define PX30_GLB_SRST_FST 0xb8
+#define PX30_GLB_SRST_SND 0xbc
+#define PX30_SOFTRST_CON(x) ((x) * 0x4 + 0x300)
+#define PX30_MODE_CON 0xa0
+#define PX30_MISC_CON 0xa4
+#define PX30_SDMMC_CON0 0x380
+#define PX30_SDMMC_CON1 0x384
+#define PX30_SDIO_CON0 0x388
+#define PX30_SDIO_CON1 0x38c
+#define PX30_EMMC_CON0 0x390
+#define PX30_EMMC_CON1 0x394
+
+#define PX30_PMU_PLL_CON(x) ((x) * 0x4)
+#define PX30_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x40)
+#define PX30_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x80)
+#define PX30_PMU_MODE 0x0020
+
+#define RV1108_PLL_CON(x) ((x) * 0x4)
+#define RV1108_CLKSEL_CON(x) ((x) * 0x4 + 0x60)
+#define RV1108_CLKGATE_CON(x) ((x) * 0x4 + 0x120)
+#define RV1108_SOFTRST_CON(x) ((x) * 0x4 + 0x180)
+#define RV1108_GLB_SRST_FST 0x1c0
+#define RV1108_GLB_SRST_SND 0x1c4
+#define RV1108_MISC_CON 0x1cc
+#define RV1108_SDMMC_CON0 0x1d8
+#define RV1108_SDMMC_CON1 0x1dc
+#define RV1108_SDIO_CON0 0x1e0
+#define RV1108_SDIO_CON1 0x1e4
+#define RV1108_EMMC_CON0 0x1e8
+#define RV1108_EMMC_CON1 0x1ec
+
+#define RK2928_PLL_CON(x) ((x) * 0x4)
#define RK2928_MODE_CON 0x40
-#define RK2928_CLKSEL_CON(x) (x * 0x4 + 0x44)
-#define RK2928_CLKGATE_CON(x) (x * 0x4 + 0xd0)
+#define RK2928_CLKSEL_CON(x) ((x) * 0x4 + 0x44)
+#define RK2928_CLKGATE_CON(x) ((x) * 0x4 + 0xd0)
#define RK2928_GLB_SRST_FST 0x100
#define RK2928_GLB_SRST_SND 0x104
-#define RK2928_SOFTRST_CON(x) (x * 0x4 + 0x110)
+#define RK2928_SOFTRST_CON(x) ((x) * 0x4 + 0x110)
#define RK2928_MISC_CON 0x134
+#define RK3036_SDMMC_CON0 0x144
+#define RK3036_SDMMC_CON1 0x148
+#define RK3036_SDIO_CON0 0x14c
+#define RK3036_SDIO_CON1 0x150
+#define RK3036_EMMC_CON0 0x154
+#define RK3036_EMMC_CON1 0x158
+
+#define RK3228_GLB_SRST_FST 0x1f0
+#define RK3228_GLB_SRST_SND 0x1f4
+#define RK3228_SDMMC_CON0 0x1c0
+#define RK3228_SDMMC_CON1 0x1c4
+#define RK3228_SDIO_CON0 0x1c8
+#define RK3228_SDIO_CON1 0x1cc
+#define RK3228_EMMC_CON0 0x1d8
+#define RK3228_EMMC_CON1 0x1dc
+
#define RK3288_PLL_CON(x) RK2928_PLL_CON(x)
#define RK3288_MODE_CON 0x50
-#define RK3288_CLKSEL_CON(x) (x * 0x4 + 0x60)
-#define RK3288_CLKGATE_CON(x) (x * 0x4 + 0x160)
+#define RK3288_CLKSEL_CON(x) ((x) * 0x4 + 0x60)
+#define RK3288_CLKGATE_CON(x) ((x) * 0x4 + 0x160)
#define RK3288_GLB_SRST_FST 0x1b0
#define RK3288_GLB_SRST_SND 0x1b4
-#define RK3288_SOFTRST_CON(x) (x * 0x4 + 0x1b8)
+#define RK3288_SOFTRST_CON(x) ((x) * 0x4 + 0x1b8)
#define RK3288_MISC_CON 0x1e8
#define RK3288_SDMMC_CON0 0x200
#define RK3288_SDMMC_CON1 0x204
@@ -51,41 +120,247 @@
#define RK3288_EMMC_CON0 0x218
#define RK3288_EMMC_CON1 0x21c
+#define RK3308_PLL_CON(x) RK2928_PLL_CON(x)
+#define RK3308_CLKSEL_CON(x) ((x) * 0x4 + 0x100)
+#define RK3308_CLKGATE_CON(x) ((x) * 0x4 + 0x300)
+#define RK3308_GLB_SRST_FST 0xb8
+#define RK3308_SOFTRST_CON(x) ((x) * 0x4 + 0x400)
+#define RK3308_MODE_CON 0xa0
+#define RK3308_SDMMC_CON0 0x480
+#define RK3308_SDMMC_CON1 0x484
+#define RK3308_SDIO_CON0 0x488
+#define RK3308_SDIO_CON1 0x48c
+#define RK3308_EMMC_CON0 0x490
+#define RK3308_EMMC_CON1 0x494
+
+#define RK3328_PLL_CON(x) RK2928_PLL_CON(x)
+#define RK3328_CLKSEL_CON(x) ((x) * 0x4 + 0x100)
+#define RK3328_CLKGATE_CON(x) ((x) * 0x4 + 0x200)
+#define RK3328_GRFCLKSEL_CON(x) ((x) * 0x4 + 0x100)
+#define RK3328_GLB_SRST_FST 0x9c
+#define RK3328_GLB_SRST_SND 0x98
+#define RK3328_SOFTRST_CON(x) ((x) * 0x4 + 0x300)
+#define RK3328_MODE_CON 0x80
+#define RK3328_MISC_CON 0x84
+#define RK3328_SDMMC_CON0 0x380
+#define RK3328_SDMMC_CON1 0x384
+#define RK3328_SDIO_CON0 0x388
+#define RK3328_SDIO_CON1 0x38c
+#define RK3328_EMMC_CON0 0x390
+#define RK3328_EMMC_CON1 0x394
+#define RK3328_SDMMC_EXT_CON0 0x398
+#define RK3328_SDMMC_EXT_CON1 0x39C
+
+#define RK3368_PLL_CON(x) RK2928_PLL_CON(x)
+#define RK3368_CLKSEL_CON(x) ((x) * 0x4 + 0x100)
+#define RK3368_CLKGATE_CON(x) ((x) * 0x4 + 0x200)
+#define RK3368_GLB_SRST_FST 0x280
+#define RK3368_GLB_SRST_SND 0x284
+#define RK3368_SOFTRST_CON(x) ((x) * 0x4 + 0x300)
+#define RK3368_MISC_CON 0x380
+#define RK3368_SDMMC_CON0 0x400
+#define RK3368_SDMMC_CON1 0x404
+#define RK3368_SDIO0_CON0 0x408
+#define RK3368_SDIO0_CON1 0x40c
+#define RK3368_SDIO1_CON0 0x410
+#define RK3368_SDIO1_CON1 0x414
+#define RK3368_EMMC_CON0 0x418
+#define RK3368_EMMC_CON1 0x41c
+
+#define RK3399_PLL_CON(x) RK2928_PLL_CON(x)
+#define RK3399_CLKSEL_CON(x) ((x) * 0x4 + 0x100)
+#define RK3399_CLKGATE_CON(x) ((x) * 0x4 + 0x300)
+#define RK3399_SOFTRST_CON(x) ((x) * 0x4 + 0x400)
+#define RK3399_GLB_SRST_FST 0x500
+#define RK3399_GLB_SRST_SND 0x504
+#define RK3399_GLB_CNT_TH 0x508
+#define RK3399_MISC_CON 0x50c
+#define RK3399_RST_CON 0x510
+#define RK3399_RST_ST 0x514
+#define RK3399_SDMMC_CON0 0x580
+#define RK3399_SDMMC_CON1 0x584
+#define RK3399_SDIO_CON0 0x588
+#define RK3399_SDIO_CON1 0x58c
+
+#define RK3399_PMU_PLL_CON(x) RK2928_PLL_CON(x)
+#define RK3399_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x80)
+#define RK3399_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x100)
+#define RK3399_PMU_SOFTRST_CON(x) ((x) * 0x4 + 0x110)
+
+#define RK3568_PLL_CON(x) RK2928_PLL_CON(x)
+#define RK3568_MODE_CON0 0xc0
+#define RK3568_MISC_CON0 0xc4
+#define RK3568_MISC_CON1 0xc8
+#define RK3568_MISC_CON2 0xcc
+#define RK3568_GLB_CNT_TH 0xd0
+#define RK3568_GLB_SRST_FST 0xd4
+#define RK3568_GLB_SRST_SND 0xd8
+#define RK3568_GLB_RST_CON 0xdc
+#define RK3568_GLB_RST_ST 0xe0
+#define RK3568_CLKSEL_CON(x) ((x) * 0x4 + 0x100)
+#define RK3568_CLKGATE_CON(x) ((x) * 0x4 + 0x300)
+#define RK3568_SOFTRST_CON(x) ((x) * 0x4 + 0x400)
+#define RK3568_SDMMC0_CON0 0x580
+#define RK3568_SDMMC0_CON1 0x584
+#define RK3568_SDMMC1_CON0 0x588
+#define RK3568_SDMMC1_CON1 0x58c
+#define RK3568_SDMMC2_CON0 0x590
+#define RK3568_SDMMC2_CON1 0x594
+#define RK3568_EMMC_CON0 0x598
+#define RK3568_EMMC_CON1 0x59c
+
+#define RK3568_PMU_PLL_CON(x) RK2928_PLL_CON(x)
+#define RK3568_PMU_MODE_CON0 0x80
+#define RK3568_PMU_CLKSEL_CON(x) ((x) * 0x4 + 0x100)
+#define RK3568_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x180)
+#define RK3568_PMU_SOFTRST_CON(x) ((x) * 0x4 + 0x200)
+
+#define RK3588_PHP_CRU_BASE 0x8000
+#define RK3588_PMU_CRU_BASE 0x30000
+#define RK3588_BIGCORE0_CRU_BASE 0x50000
+#define RK3588_BIGCORE1_CRU_BASE 0x52000
+#define RK3588_DSU_CRU_BASE 0x58000
+
+#define RK3588_PLL_CON(x) RK2928_PLL_CON(x)
+#define RK3588_MODE_CON0 0x280
+#define RK3588_B0_PLL_MODE_CON0 (RK3588_BIGCORE0_CRU_BASE + 0x280)
+#define RK3588_B1_PLL_MODE_CON0 (RK3588_BIGCORE1_CRU_BASE + 0x280)
+#define RK3588_LPLL_MODE_CON0 (RK3588_DSU_CRU_BASE + 0x280)
+#define RK3588_CLKSEL_CON(x) ((x) * 0x4 + 0x300)
+#define RK3588_CLKGATE_CON(x) ((x) * 0x4 + 0x800)
+#define RK3588_SOFTRST_CON(x) ((x) * 0x4 + 0xa00)
+#define RK3588_GLB_CNT_TH 0xc00
+#define RK3588_GLB_SRST_FST 0xc08
+#define RK3588_GLB_SRST_SND 0xc0c
+#define RK3588_GLB_RST_CON 0xc10
+#define RK3588_GLB_RST_ST 0xc04
+#define RK3588_SDIO_CON0 0xC24
+#define RK3588_SDIO_CON1 0xC28
+#define RK3588_SDMMC_CON0 0xC30
+#define RK3588_SDMMC_CON1 0xC34
+
+#define RK3588_PHP_CLKGATE_CON(x) ((x) * 0x4 + RK3588_PHP_CRU_BASE + 0x800)
+#define RK3588_PHP_SOFTRST_CON(x) ((x) * 0x4 + RK3588_PHP_CRU_BASE + 0xa00)
+
+#define RK3588_PMU_PLL_CON(x) ((x) * 0x4 + RK3588_PHP_CRU_BASE)
+#define RK3588_PMU_CLKSEL_CON(x) ((x) * 0x4 + RK3588_PMU_CRU_BASE + 0x300)
+#define RK3588_PMU_CLKGATE_CON(x) ((x) * 0x4 + RK3588_PMU_CRU_BASE + 0x800)
+#define RK3588_PMU_SOFTRST_CON(x) ((x) * 0x4 + RK3588_PMU_CRU_BASE + 0xa00)
+
+#define RK3588_B0_PLL_CON(x) ((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE)
+#define RK3588_BIGCORE0_CLKSEL_CON(x) ((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE + 0x300)
+#define RK3588_BIGCORE0_CLKGATE_CON(x) ((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE + 0x800)
+#define RK3588_BIGCORE0_SOFTRST_CON(x) ((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE + 0xa00)
+#define RK3588_B1_PLL_CON(x) ((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE)
+#define RK3588_BIGCORE1_CLKSEL_CON(x) ((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE + 0x300)
+#define RK3588_BIGCORE1_CLKGATE_CON(x) ((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE + 0x800)
+#define RK3588_BIGCORE1_SOFTRST_CON(x) ((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE + 0xa00)
+#define RK3588_LPLL_CON(x) ((x) * 0x4 + RK3588_DSU_CRU_BASE)
+#define RK3588_DSU_CLKSEL_CON(x) ((x) * 0x4 + RK3588_DSU_CRU_BASE + 0x300)
+#define RK3588_DSU_CLKGATE_CON(x) ((x) * 0x4 + RK3588_DSU_CRU_BASE + 0x800)
+#define RK3588_DSU_SOFTRST_CON(x) ((x) * 0x4 + RK3588_DSU_CRU_BASE + 0xa00)
+
enum rockchip_pll_type {
+ pll_rk3036,
pll_rk3066,
+ pll_rk3328,
+ pll_rk3399,
+ pll_rk3588,
+ pll_rk3588_core,
};
+#define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \
+ _postdiv2, _dsmpd, _frac) \
+{ \
+ .rate = _rate##U, \
+ .fbdiv = _fbdiv, \
+ .postdiv1 = _postdiv1, \
+ .refdiv = _refdiv, \
+ .postdiv2 = _postdiv2, \
+ .dsmpd = _dsmpd, \
+ .frac = _frac, \
+}
+
#define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \
{ \
.rate = _rate##U, \
.nr = _nr, \
.nf = _nf, \
.no = _no, \
- .bwadj = (_nf >> 1), \
+ .nb = ((_nf) < 2) ? 1 : (_nf) >> 1, \
}
-#define RK3066_PLL_RATE_BWADJ(_rate, _nr, _nf, _no, _bw) \
+#define RK3066_PLL_RATE_NB(_rate, _nr, _nf, _no, _nb) \
{ \
.rate = _rate##U, \
.nr = _nr, \
.nf = _nf, \
.no = _no, \
- .bwadj = _bw, \
+ .nb = _nb, \
+}
+
+#define RK3588_PLL_RATE(_rate, _p, _m, _s, _k) \
+{ \
+ .rate = _rate##U, \
+ .p = _p, \
+ .m = _m, \
+ .s = _s, \
+ .k = _k, \
}
+/**
+ * struct rockchip_clk_provider - information about clock provider
+ * @reg_base: virtual address for the register base.
+ * @clk_data: holds clock related data like clk* and number of clocks.
+ * @cru_node: device-node of the clock-provider
+ * @grf: regmap of the general-register-files syscon
+ * @lock: maintains exclusion between callbacks for a given clock-provider.
+ */
+struct rockchip_clk_provider {
+ void __iomem *reg_base;
+ struct clk_onecell_data clk_data;
+ struct device_node *cru_node;
+ struct regmap *grf;
+ struct restart_handler restart_handler;
+ unsigned int reg_restart;
+ spinlock_t lock;
+};
+
struct rockchip_pll_rate_table {
unsigned long rate;
- unsigned int nr;
- unsigned int nf;
- unsigned int no;
- unsigned int bwadj;
+ union {
+ struct {
+ /* for RK3066 */
+ unsigned int nr;
+ unsigned int nf;
+ unsigned int no;
+ unsigned int nb;
+ };
+ struct {
+ /* for RK3036/RK3399 */
+ unsigned int fbdiv;
+ unsigned int postdiv1;
+ unsigned int refdiv;
+ unsigned int postdiv2;
+ unsigned int dsmpd;
+ unsigned int frac;
+ };
+ struct {
+ /* for RK3588 */
+ unsigned int m;
+ unsigned int p;
+ unsigned int s;
+ unsigned int k;
+ };
+ };
};
/**
- * struct rockchip_pll_clock: information about pll clock
+ * struct rockchip_pll_clock - information about pll clock
* @id: platform specific id of the clock.
* @name: name of this pll clock.
- * @parent_name: name of the parent clock.
+ * @parent_names: name of the parent clock.
+ * @num_parents: number of parents
* @flags: optional flags for basic clock.
* @con_offset: offset of the register for configuring the PLL.
* @mode_offset: offset of the register for configuring the PLL-mode.
@@ -102,7 +377,7 @@ struct rockchip_pll_rate_table {
struct rockchip_pll_clock {
unsigned int id;
const char *name;
- const char **parent_names;
+ const char *const *parent_names;
u8 num_parents;
unsigned long flags;
int con_offset;
@@ -133,71 +408,116 @@ struct rockchip_pll_clock {
.rate_table = _rtable, \
}
-struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
- const char *name, const char **parent_names, u8 num_parents,
- void __iomem *base, int con_offset, int grf_lock_offset,
- int lock_shift, int reg_mode, int mode_shift,
+struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
+ enum rockchip_pll_type pll_type,
+ const char *name, const char *const *parent_names,
+ u8 num_parents, int con_offset, int grf_lock_offset,
+ int lock_shift, int mode_offset, int mode_shift,
struct rockchip_pll_rate_table *rate_table,
- u8 clk_pll_flags);
+ unsigned long flags, u8 clk_pll_flags);
struct rockchip_cpuclk_clksel {
int reg;
u32 val;
};
-#define ROCKCHIP_CPUCLK_NUM_DIVIDERS 2
+#define ROCKCHIP_CPUCLK_NUM_DIVIDERS 6
+#define ROCKCHIP_CPUCLK_MAX_CORES 4
struct rockchip_cpuclk_rate_table {
unsigned long prate;
struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
+ struct rockchip_cpuclk_clksel pre_muxs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
+ struct rockchip_cpuclk_clksel post_muxs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
};
/**
- * struct rockchip_cpuclk_reg_data: describes register offsets and masks of the cpuclock
- * @core_reg: register offset of the core settings register
- * @div_core_shift: core divider offset used to divide the pll value
- * @div_core_mask: core divider mask
+ * struct rockchip_cpuclk_reg_data - register offsets and masks of the cpuclock
+ * @core_reg[]: register offset of the cores setting register
+ * @div_core_shift[]: cores divider offset used to divide the pll value
+ * @div_core_mask[]: cores divider mask
+ * @num_cores: number of cpu cores
+ * @mux_core_reg: register offset of the cores select parent
+ * @mux_core_alt: mux value to select alternate parent
+ * @mux_core_main: mux value to select main parent of core
* @mux_core_shift: offset of the core multiplexer
+ * @mux_core_mask: core multiplexer mask
*/
struct rockchip_cpuclk_reg_data {
- int core_reg;
- u8 div_core_shift;
- u32 div_core_mask;
- int mux_core_reg;
- u8 mux_core_shift;
+ int core_reg[ROCKCHIP_CPUCLK_MAX_CORES];
+ u8 div_core_shift[ROCKCHIP_CPUCLK_MAX_CORES];
+ u32 div_core_mask[ROCKCHIP_CPUCLK_MAX_CORES];
+ int num_cores;
+ int mux_core_reg;
+ u8 mux_core_alt;
+ u8 mux_core_main;
+ u8 mux_core_shift;
+ u32 mux_core_mask;
};
struct clk *rockchip_clk_register_cpuclk(const char *name,
- const char **parent_names, u8 num_parents,
+ const char *const *parent_names, u8 num_parents,
const struct rockchip_cpuclk_reg_data *reg_data,
const struct rockchip_cpuclk_rate_table *rates,
- int nrates, void __iomem *reg_base);
+ int nrates, void __iomem *reg_base, spinlock_t *lock);
struct clk *rockchip_clk_register_mmc(const char *name,
- const char **parent_names, u8 num_parents,
+ const char *const *parent_names, u8 num_parents,
void __iomem *reg, int shift);
-#define PNAME(x) static const char *x[] __initconst
+/*
+ * DDRCLK flags, including method of setting the rate
+ * ROCKCHIP_DDRCLK_SIP: use SIP call to bl31 to change ddrclk rate.
+ */
+#define ROCKCHIP_DDRCLK_SIP BIT(0)
+
+struct clk *rockchip_clk_register_ddrclk(const char *name, int flags,
+ const char *const *parent_names,
+ u8 num_parents, int mux_offset,
+ int mux_shift, int mux_width,
+ int div_shift, int div_width,
+ int ddr_flags, void __iomem *reg_base,
+ spinlock_t *lock);
+
+#define ROCKCHIP_INVERTER_HIWORD_MASK BIT(0)
+
+struct clk *rockchip_clk_register_inverter(const char *name,
+ const char *const *parent_names, u8 num_parents,
+ void __iomem *reg, int shift, int flags,
+ spinlock_t *lock);
+
+struct clk *rockchip_clk_register_muxgrf(const char *name,
+ const char *const *parent_names, u8 num_parents,
+ int flags, struct regmap *grf, int reg,
+ int shift, int width, int mux_flags);
+
+#define PNAME(x) static const char *const x[] __initconst
enum rockchip_clk_branch_type {
branch_composite,
branch_mux,
+ branch_muxgrf,
branch_divider,
branch_fraction_divider,
branch_gate,
branch_mmc,
+ branch_inverter,
+ branch_factor,
+ branch_ddrclk,
+ branch_half_divider,
};
struct rockchip_clk_branch {
unsigned int id;
enum rockchip_clk_branch_type branch_type;
const char *name;
- const char **parent_names;
+ const char *const *parent_names;
u8 num_parents;
unsigned long flags;
int muxdiv_offset;
u8 mux_shift;
u8 mux_width;
u8 mux_flags;
+ int div_offset;
u8 div_shift;
u8 div_width;
u8 div_flags;
@@ -205,6 +525,7 @@ struct rockchip_clk_branch {
int gate_offset;
u8 gate_shift;
u8 gate_flags;
+ struct rockchip_clk_branch *child;
};
#define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
@@ -228,6 +549,28 @@ struct rockchip_clk_branch {
.gate_flags = gf, \
}
+#define COMPOSITE_DIV_OFFSET(_id, cname, pnames, f, mo, ms, mw, \
+ mf, do, ds, dw, df, go, gs, gf) \
+ { \
+ .id = _id, \
+ .branch_type = branch_composite, \
+ .name = cname, \
+ .parent_names = pnames, \
+ .num_parents = ARRAY_SIZE(pnames), \
+ .flags = f, \
+ .muxdiv_offset = mo, \
+ .mux_shift = ms, \
+ .mux_width = mw, \
+ .mux_flags = mf, \
+ .div_offset = do, \
+ .div_shift = ds, \
+ .div_width = dw, \
+ .div_flags = df, \
+ .gate_offset = go, \
+ .gate_shift = gs, \
+ .gate_flags = gf, \
+ }
+
#define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \
go, gs, gf) \
{ \
@@ -302,6 +645,26 @@ struct rockchip_clk_branch {
.gate_offset = -1, \
}
+#define COMPOSITE_NOGATE_DIVTBL(_id, cname, pnames, f, mo, ms, \
+ mw, mf, ds, dw, df, dt) \
+ { \
+ .id = _id, \
+ .branch_type = branch_composite, \
+ .name = cname, \
+ .parent_names = pnames, \
+ .num_parents = ARRAY_SIZE(pnames), \
+ .flags = f, \
+ .muxdiv_offset = mo, \
+ .mux_shift = ms, \
+ .mux_width = mw, \
+ .mux_flags = mf, \
+ .div_shift = ds, \
+ .div_width = dw, \
+ .div_flags = df, \
+ .div_table = dt, \
+ .gate_offset = -1, \
+ }
+
#define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\
{ \
.id = _id, \
@@ -319,6 +682,58 @@ struct rockchip_clk_branch {
.gate_flags = gf, \
}
+#define COMPOSITE_FRACMUX(_id, cname, pname, f, mo, df, go, gs, gf, ch) \
+ { \
+ .id = _id, \
+ .branch_type = branch_fraction_divider, \
+ .name = cname, \
+ .parent_names = (const char *[]){ pname }, \
+ .num_parents = 1, \
+ .flags = f, \
+ .muxdiv_offset = mo, \
+ .div_shift = 16, \
+ .div_width = 16, \
+ .div_flags = df, \
+ .gate_offset = go, \
+ .gate_shift = gs, \
+ .gate_flags = gf, \
+ .child = ch, \
+ }
+
+#define COMPOSITE_FRACMUX_NOGATE(_id, cname, pname, f, mo, df, ch) \
+ { \
+ .id = _id, \
+ .branch_type = branch_fraction_divider, \
+ .name = cname, \
+ .parent_names = (const char *[]){ pname }, \
+ .num_parents = 1, \
+ .flags = f, \
+ .muxdiv_offset = mo, \
+ .div_shift = 16, \
+ .div_width = 16, \
+ .div_flags = df, \
+ .gate_offset = -1, \
+ .child = ch, \
+ }
+
+#define COMPOSITE_DDRCLK(_id, cname, pnames, f, mo, ms, mw, \
+ ds, dw, df) \
+ { \
+ .id = _id, \
+ .branch_type = branch_ddrclk, \
+ .name = cname, \
+ .parent_names = pnames, \
+ .num_parents = ARRAY_SIZE(pnames), \
+ .flags = f, \
+ .muxdiv_offset = mo, \
+ .mux_shift = ms, \
+ .mux_width = mw, \
+ .div_shift = ds, \
+ .div_width = dw, \
+ .div_flags = df, \
+ .gate_offset = -1, \
+ }
+
#define MUX(_id, cname, pnames, f, o, s, w, mf) \
{ \
.id = _id, \
@@ -334,6 +749,21 @@ struct rockchip_clk_branch {
.gate_offset = -1, \
}
+#define MUXGRF(_id, cname, pnames, f, o, s, w, mf) \
+ { \
+ .id = _id, \
+ .branch_type = branch_muxgrf, \
+ .name = cname, \
+ .parent_names = pnames, \
+ .num_parents = ARRAY_SIZE(pnames), \
+ .flags = f, \
+ .muxdiv_offset = o, \
+ .mux_shift = s, \
+ .mux_width = w, \
+ .mux_flags = mf, \
+ .gate_offset = -1, \
+ }
+
#define DIV(_id, cname, pname, f, o, s, w, df) \
{ \
.id = _id, \
@@ -388,19 +818,115 @@ struct rockchip_clk_branch {
.div_shift = shift, \
}
-void rockchip_clk_init(struct device_node *np, void __iomem *base,
- unsigned long nr_clks);
-struct regmap *rockchip_clk_get_grf(void);
-void rockchip_clk_add_lookup(struct clk *clk, unsigned int id);
-void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list,
+#define INVERTER(_id, cname, pname, io, is, if) \
+ { \
+ .id = _id, \
+ .branch_type = branch_inverter, \
+ .name = cname, \
+ .parent_names = (const char *[]){ pname }, \
+ .num_parents = 1, \
+ .muxdiv_offset = io, \
+ .div_shift = is, \
+ .div_flags = if, \
+ }
+
+#define FACTOR(_id, cname, pname, f, fm, fd) \
+ { \
+ .id = _id, \
+ .branch_type = branch_factor, \
+ .name = cname, \
+ .parent_names = (const char *[]){ pname }, \
+ .num_parents = 1, \
+ .flags = f, \
+ .div_shift = fm, \
+ .div_width = fd, \
+ }
+
+#define FACTOR_GATE(_id, cname, pname, f, fm, fd, go, gb, gf) \
+ { \
+ .id = _id, \
+ .branch_type = branch_factor, \
+ .name = cname, \
+ .parent_names = (const char *[]){ pname }, \
+ .num_parents = 1, \
+ .flags = f, \
+ .div_shift = fm, \
+ .div_width = fd, \
+ .gate_offset = go, \
+ .gate_shift = gb, \
+ .gate_flags = gf, \
+ }
+
+#define COMPOSITE_HALFDIV(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
+ df, go, gs, gf) \
+ { \
+ .id = _id, \
+ .branch_type = branch_half_divider, \
+ .name = cname, \
+ .parent_names = pnames, \
+ .num_parents = ARRAY_SIZE(pnames), \
+ .flags = f, \
+ .muxdiv_offset = mo, \
+ .mux_shift = ms, \
+ .mux_width = mw, \
+ .mux_flags = mf, \
+ .div_shift = ds, \
+ .div_width = dw, \
+ .div_flags = df, \
+ .gate_offset = go, \
+ .gate_shift = gs, \
+ .gate_flags = gf, \
+ }
+
+/* SGRF clocks are only accessible from secure mode, so not controllable */
+#define SGRF_GATE(_id, cname, pname) \
+ FACTOR(_id, cname, pname, 0, 1, 1)
+
+struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,
+ void __iomem *base, unsigned long nr_clks);
+void rockchip_clk_of_add_provider(struct device_node *np,
+ struct rockchip_clk_provider *ctx);
+void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx,
+ struct clk *clk, unsigned int id);
+void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
+ struct rockchip_clk_branch *list,
unsigned int nr_clk);
-void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list,
+void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx,
+ struct rockchip_pll_clock *pll_list,
unsigned int nr_pll, int grf_lock_offset);
-void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name,
- const char **parent_names, u8 num_parents,
+void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx,
+ unsigned int lookup_id, const char *name,
+ const char *const *parent_names, u8 num_parents,
const struct rockchip_cpuclk_reg_data *reg_data,
const struct rockchip_cpuclk_rate_table *rates,
int nrates);
-void rockchip_clk_protect_critical(const char *clocks[], int nclocks);
+void rockchip_clk_protect_critical(const char *const clocks[], int nclocks);
+void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx,
+ unsigned int reg);
+
+#define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0)
+
+#ifdef CONFIG_RESET_CONTROLLER
+void rockchip_register_softrst_lut(struct device_node *np,
+ const int *lookup_table,
+ unsigned int num_regs,
+ void __iomem *base, u8 flags);
+#else
+static inline void rockchip_register_softrst_lut(struct device_node *np,
+ const int *lookup_table,
+ unsigned int num_regs,
+ void __iomem *base, u8 flags)
+{
+}
+#endif
+
+static inline void rockchip_register_softrst(struct device_node *np,
+ unsigned int num_regs,
+ void __iomem *base, u8 flags)
+{
+ return rockchip_register_softrst_lut(np, NULL, num_regs, base, flags);
+}
+
+void rk3588_rst_init(struct device_node *np, void __iomem *reg_base);
#endif
diff --git a/drivers/clk/rockchip/rst-rk3588.c b/drivers/clk/rockchip/rst-rk3588.c
new file mode 100644
index 0000000000..7501b92b45
--- /dev/null
+++ b/drivers/clk/rockchip/rst-rk3588.c
@@ -0,0 +1,855 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2022 Collabora Ltd.
+ * Author: Sebastian Reichel <sebastian.reichel@collabora.com>
+ */
+
+#include <dt-bindings/reset/rockchip,rk3588-cru.h>
+#include "clk.h"
+
+/* 0xFD7C0000 + 0x0A00 */
+#define RK3588_CRU_RESET_OFFSET(id, reg, bit) [id] = (0 + reg * 16 + bit)
+
+/* 0xFD7C8000 + 0x0A00 */
+#define RK3588_PHPTOPCRU_RESET_OFFSET(id, reg, bit) [id] = (0x8000*4 + reg * 16 + bit)
+
+/* 0xFD7D0000 + 0x0A00 */
+#define RK3588_SECURECRU_RESET_OFFSET(id, reg, bit) [id] = (0x10000*4 + reg * 16 + bit)
+
+/* 0xFD7F0000 + 0x0A00 */
+#define RK3588_PMU1CRU_RESET_OFFSET(id, reg, bit) [id] = (0x30000*4 + reg * 16 + bit)
+
+/* mapping table for reset ID to register offset */
+static const int rk3588_register_offset[] = {
+ /* SOFTRST_CON01 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_TOP_BIU, 1, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_TOP_BIU, 1, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CSIPHY0, 1, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_CSIPHY0, 1, 7), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_P_CSIPHY1, 1, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_CSIPHY1, 1, 9), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_A_TOP_M500_BIU, 1, 15),
+
+ /* SOFTRST_CON02 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_TOP_M400_BIU, 2, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_A_TOP_S200_BIU, 2, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_A_TOP_S400_BIU, 2, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_A_TOP_M300_BIU, 2, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_INIT, 2, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_CMN, 2, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_LANE, 2, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_PCS, 2, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_INIT, 2, 15),
+
+ /* SOFTRST_CON03 */
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_CMN, 3, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_LANE, 3, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_PCS, 3, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_DCPHY0, 3, 11), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_P_MIPI_DCPHY0, 3, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_P_MIPI_DCPHY0_GRF, 3, 15),
+
+ /* SOFTRST_CON04 */
+ RK3588_CRU_RESET_OFFSET(SRST_DCPHY1, 4, 0), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_P_MIPI_DCPHY1, 4, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_MIPI_DCPHY1_GRF, 4, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_CDPHY, 4, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_CSIPHY, 4, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_VCCIO3_5, 4, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_VCCIO6, 4, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_EMMCIO, 4, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_IOC_TOP, 4, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_IOC_RIGHT, 4, 11),
+
+ /* SOFTRST_CON05 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_CRU, 5, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_A_CHANNEL_SECURE2VO1USB, 5, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_A_CHANNEL_SECURE2CENTER, 5, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_H_CHANNEL_SECURE2VO1USB, 5, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_H_CHANNEL_SECURE2CENTER, 5, 15),
+
+ /* SOFTRST_CON06 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_CHANNEL_SECURE2VO1USB, 6, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CHANNEL_SECURE2CENTER, 6, 1),
+
+ /* SOFTRST_CON07 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_AUDIO_BIU, 7, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_AUDIO_BIU, 7, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S0_8CH, 7, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S0_8CH_TX, 7, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S0_8CH_RX, 7, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_P_ACDCDIG, 7, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S2_2CH, 7, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S3_2CH, 7, 13),
+
+ /* SOFTRST_CON08 */
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S2_2CH, 8, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S3_2CH, 8, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_DAC_ACDCDIG, 8, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SPDIF0, 8, 14),
+
+ /* SOFTRST_CON09 */
+ RK3588_CRU_RESET_OFFSET(SRST_M_SPDIF0, 9, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SPDIF1, 9, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_M_SPDIF1, 9, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_H_PDM1, 9, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_PDM1, 9, 7),
+
+ /* SOFTRST_CON10 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_BUS_BIU, 10, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_BUS_BIU, 10, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_A_GIC, 10, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_A_GIC_DBG, 10, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DMAC0, 10, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DMAC1, 10, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DMAC2, 10, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_I2C1, 10, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_I2C2, 10, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_I2C3, 10, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_P_I2C4, 10, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_P_I2C5, 10, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_I2C6, 10, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_P_I2C7, 10, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_P_I2C8, 10, 15),
+
+ /* SOFTRST_CON11 */
+ RK3588_CRU_RESET_OFFSET(SRST_I2C1, 11, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_I2C2, 11, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_I2C3, 11, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_I2C4, 11, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_I2C5, 11, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_I2C6, 11, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_I2C7, 11, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_I2C8, 11, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CAN0, 11, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_CAN0, 11, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CAN1, 11, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_CAN1, 11, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CAN2, 11, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_CAN2, 11, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_P_SARADC, 11, 14),
+
+ /* SOFTRST_CON12 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_TSADC, 12, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_TSADC, 12, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_UART1, 12, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_UART2, 12, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_UART3, 12, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_UART4, 12, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_P_UART5, 12, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_UART6, 12, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_UART7, 12, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_UART8, 12, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_UART9, 12, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_S_UART1, 12, 13),
+
+ /* SOFTRST_CON13 */
+ RK3588_CRU_RESET_OFFSET(SRST_S_UART2, 13, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_S_UART3, 13, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_S_UART4, 13, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_S_UART5, 13, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_S_UART6, 13, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_S_UART7, 13, 15),
+
+ /* SOFTRST_CON14 */
+ RK3588_CRU_RESET_OFFSET(SRST_S_UART8, 14, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_S_UART9, 14, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_P_SPI0, 14, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_SPI1, 14, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_SPI2, 14, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_SPI3, 14, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_SPI4, 14, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_SPI0, 14, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_SPI1, 14, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_SPI2, 14, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_SPI3, 14, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_SPI4, 14, 15),
+
+ /* SOFTRST_CON15 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_WDT0, 15, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_T_WDT0, 15, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_SYS_GRF, 15, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_PWM1, 15, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_PWM1, 15, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_PWM2, 15, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_PWM2, 15, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_PWM3, 15, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_PWM3, 15, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_P_BUSTIMER0, 15, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_BUSTIMER1, 15, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER0, 15, 15),
+
+ /* SOFTRST_CON16 */
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER1, 16, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER2, 16, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER3, 16, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER4, 16, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER5, 16, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER6, 16, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER7, 16, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER8, 16, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER9, 16, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER10, 16, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER11, 16, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_P_MAILBOX0, 16, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_P_MAILBOX1, 16, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_MAILBOX2, 16, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_P_GPIO1, 16, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_GPIO1, 16, 15),
+
+ /* SOFTRST_CON17 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_GPIO2, 17, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_GPIO2, 17, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_GPIO3, 17, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_GPIO3, 17, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_GPIO4, 17, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_GPIO4, 17, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DECOM, 17, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DECOM, 17, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_D_DECOM, 17, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_TOP, 17, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_A_GICADB_GIC2CORE_BUS, 17, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DFT2APB, 17, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_TOP, 17, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_CDPHY, 17, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_BOT_RIGHT, 17, 15),
+
+ /* SOFTRST_CON18 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_IOC_TOP, 18, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_IOC_RIGHT, 18, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_CSIPHY, 18, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_VCCIO3_5, 18, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_VCCIO6, 18, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_EMMCIO, 18, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_A_SPINLOCK, 18, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_OTPC_NS, 18, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_OTPC_NS, 18, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_OTPC_ARB, 18, 11),
+
+ /* SOFTRST_CON19 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_BUSIOC, 19, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_P_PMUCM0_INTMUX, 19, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDRCM0_INTMUX, 19, 5),
+
+ /* SOFTRST_CON20 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_DFICTL_CH0, 20, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_MON_CH0, 20, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_STANDBY_CH0, 20, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_UPCTL_CH0, 20, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_TM_DDR_MON_CH0, 20, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_GRF_CH01, 20, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_DFI_CH0, 20, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_SBR_CH0, 20, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_UPCTL_CH0, 20, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_DFICTL_CH0, 20, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_MON_CH0, 20, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_STANDBY_CH0, 20, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_CH0, 20, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_DFICTL_CH1, 20, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_MON_CH1, 20, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_STANDBY_CH1, 20, 15),
+
+ /* SOFTRST_CON21 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_UPCTL_CH1, 21, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_TM_DDR_MON_CH1, 21, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_DFI_CH1, 21, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_SBR_CH1, 21, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_UPCTL_CH1, 21, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_DFICTL_CH1, 21, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_MON_CH1, 21, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_STANDBY_CH1, 21, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_CH1, 21, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_MSCH0, 21, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_RS_MSCH0, 21, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_FRS_MSCH0, 21, 15),
+
+ /* SOFTRST_CON22 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_SCRAMBLE0, 22, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_FRS_SCRAMBLE0, 22, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_MSCH1, 22, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_RS_MSCH1, 22, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_FRS_MSCH1, 22, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_SCRAMBLE1, 22, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_FRS_SCRAMBLE1, 22, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR01_MSCH0, 22, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR01_MSCH1, 22, 8),
+
+ /* SOFTRST_CON23 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_DFICTL_CH2, 23, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_MON_CH2, 23, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_STANDBY_CH2, 23, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_UPCTL_CH2, 23, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_TM_DDR_MON_CH2, 23, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_GRF_CH23, 23, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_DFI_CH2, 23, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_SBR_CH2, 23, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_UPCTL_CH2, 23, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_DFICTL_CH2, 23, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_MON_CH2, 23, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_STANDBY_CH2, 23, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_CH2, 23, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_DFICTL_CH3, 23, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_MON_CH3, 23, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_STANDBY_CH3, 23, 15),
+
+ /* SOFTRST_CON24 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_UPCTL_CH3, 24, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_TM_DDR_MON_CH3, 24, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_DFI_CH3, 24, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_SBR_CH3, 24, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_UPCTL_CH3, 24, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_DFICTL_CH3, 24, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_MON_CH3, 24, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_STANDBY_CH3, 24, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_CH3, 24, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_MSCH2, 24, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_RS_MSCH2, 24, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_FRS_MSCH2, 24, 15),
+
+ /* SOFTRST_CON25 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_SCRAMBLE2, 25, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_FRS_SCRAMBLE2, 25, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_MSCH3, 25, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_RS_MSCH3, 25, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_FRS_MSCH3, 25, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_SCRAMBLE3, 25, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_FRS_SCRAMBLE3, 25, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR23_MSCH2, 25, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR23_MSCH3, 25, 8),
+
+ /* SOFTRST_CON26 */
+ RK3588_CRU_RESET_OFFSET(SRST_ISP1, 26, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_ISP1_VICAP, 26, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_ISP1_BIU, 26, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_H_ISP1_BIU, 26, 8),
+
+ /* SOFTRST_CON27 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKNN1, 27, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKNN1_BIU, 27, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKNN1, 27, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKNN1_BIU, 27, 3),
+
+ /* SOFTRST_CON28 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKNN2, 28, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKNN2_BIU, 28, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKNN2, 28, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKNN2_BIU, 28, 3),
+
+ /* SOFTRST_CON29 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKNN_DSU0, 29, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_NPUTOP_BIU, 29, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_P_NPU_TIMER, 29, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_NPUTIMER0, 29, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_NPUTIMER1, 29, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_NPU_WDT, 29, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_T_NPU_WDT, 29, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_P_NPU_PVTM, 29, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_NPU_GRF, 29, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_NPU_PVTM, 29, 14),
+
+ /* SOFTRST_CON30 */
+ RK3588_CRU_RESET_OFFSET(SRST_NPU_PVTPLL, 30, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_H_NPU_CM0_BIU, 30, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_F_NPU_CM0_CORE, 30, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_T_NPU_CM0_JTAG, 30, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKNN0, 30, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKNN0_BIU, 30, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKNN0, 30, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKNN0_BIU, 30, 9),
+
+ /* SOFTRST_CON31 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_NVM_BIU, 31, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_A_NVM_BIU, 31, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_EMMC, 31, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_EMMC, 31, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_C_EMMC, 31, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_B_EMMC, 31, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_T_EMMC, 31, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_S_SFC, 31, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SFC, 31, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SFC_XIP, 31, 11),
+
+ /* SOFTRST_CON32 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_GRF, 32, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DEC_BIU, 32, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_PHP_BIU, 32, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_A_PCIE_GRIDGE, 32, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_A_PHP_BIU, 32, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_A_GMAC0, 32, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_A_GMAC1, 32, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_A_PCIE_BIU, 32, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_PCIE0_POWER_UP, 32, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_PCIE1_POWER_UP, 32, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_PCIE2_POWER_UP, 32, 15),
+
+ /* SOFTRST_CON33 */
+ RK3588_CRU_RESET_OFFSET(SRST_PCIE3_POWER_UP, 33, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_PCIE4_POWER_UP, 33, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_PCIE0, 33, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_PCIE1, 33, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_P_PCIE2, 33, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_P_PCIE3, 33, 15),
+
+ /* SOFTRST_CON34 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_PCIE4, 34, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_A_PHP_GIC_ITS, 34, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_A_MMU_PCIE, 34, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_A_MMU_PHP, 34, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_A_MMU_BIU, 34, 9),
+
+ /* SOFTRST_CON35 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_USB3OTG2, 35, 7),
+
+ /* SOFTRST_CON37 */
+ RK3588_CRU_RESET_OFFSET(SRST_PMALIVE0, 37, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_PMALIVE1, 37, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_PMALIVE2, 37, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_A_SATA0, 37, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_A_SATA1, 37, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_A_SATA2, 37, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_RXOOB0, 37, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_RXOOB1, 37, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_RXOOB2, 37, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_ASIC0, 37, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_ASIC1, 37, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_ASIC2, 37, 15),
+
+ /* SOFTRST_CON40 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKVDEC_CCU, 40, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKVDEC0, 40, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKVDEC0, 40, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKVDEC0_BIU, 40, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKVDEC0_BIU, 40, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_RKVDEC0_CA, 40, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_RKVDEC0_HEVC_CA, 40, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_RKVDEC0_CORE, 40, 9),
+
+ /* SOFTRST_CON41 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKVDEC1, 41, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKVDEC1, 41, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKVDEC1_BIU, 41, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKVDEC1_BIU, 41, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_RKVDEC1_CA, 41, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_RKVDEC1_HEVC_CA, 41, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_RKVDEC1_CORE, 41, 8),
+
+ /* SOFTRST_CON42 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_USB_BIU, 42, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_H_USB_BIU, 42, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_A_USB3OTG0, 42, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_USB3OTG1, 42, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_H_HOST0, 42, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_H_HOST_ARB0, 42, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_H_HOST1, 42, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_H_HOST_ARB1, 42, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_A_USB_GRF, 42, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_C_USB2P0_HOST0, 42, 15),
+
+ /* SOFTRST_CON43 */
+ RK3588_CRU_RESET_OFFSET(SRST_C_USB2P0_HOST1, 43, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_HOST_UTMI0, 43, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_HOST_UTMI1, 43, 2),
+
+ /* SOFTRST_CON44 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_VDPU_BIU, 44, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_VDPU_LOW_BIU, 44, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VDPU_BIU, 44, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_A_JPEG_DECODER_BIU, 44, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_A_VPU, 44, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VPU, 44, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_A_JPEG_ENCODER0, 44, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_H_JPEG_ENCODER0, 44, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_A_JPEG_ENCODER1, 44, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_H_JPEG_ENCODER1, 44, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_A_JPEG_ENCODER2, 44, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_H_JPEG_ENCODER2, 44, 15),
+
+ /* SOFTRST_CON45 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_JPEG_ENCODER3, 45, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_H_JPEG_ENCODER3, 45, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_A_JPEG_DECODER, 45, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_H_JPEG_DECODER, 45, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_IEP2P0, 45, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_IEP2P0, 45, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_IEP2P0_CORE, 45, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RGA2, 45, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RGA2, 45, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_RGA2_CORE, 45, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RGA3_0, 45, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RGA3_0, 45, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_RGA3_0_CORE, 45, 12),
+
+ /* SOFTRST_CON47 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKVENC0_BIU, 47, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKVENC0_BIU, 47, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKVENC0, 47, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKVENC0, 47, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_RKVENC0_CORE, 47, 6),
+
+ /* SOFTRST_CON48 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKVENC1_BIU, 48, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKVENC1_BIU, 48, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKVENC1, 48, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKVENC1, 48, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_RKVENC1_CORE, 48, 6),
+
+ /* SOFTRST_CON49 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_VI_BIU, 49, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VI_BIU, 49, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VI_BIU, 49, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_D_VICAP, 49, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_A_VICAP, 49, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VICAP, 49, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_ISP0, 49, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_ISP0_VICAP, 49, 11),
+
+ /* SOFTRST_CON50 */
+ RK3588_CRU_RESET_OFFSET(SRST_FISHEYE0, 50, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_FISHEYE1, 50, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CSI_HOST_0, 50, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CSI_HOST_1, 50, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CSI_HOST_2, 50, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CSI_HOST_3, 50, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CSI_HOST_4, 50, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CSI_HOST_5, 50, 9),
+
+ /* SOFTRST_CON51 */
+ RK3588_CRU_RESET_OFFSET(SRST_CSIHOST0_VICAP, 51, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_CSIHOST1_VICAP, 51, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_CSIHOST2_VICAP, 51, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_CSIHOST3_VICAP, 51, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_CSIHOST4_VICAP, 51, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_CSIHOST5_VICAP, 51, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_CIFIN, 51, 13),
+
+ /* SOFTRST_CON52 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_VOP_BIU, 52, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_VOP_LOW_BIU, 52, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VOP_BIU, 52, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VOP_BIU, 52, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VOP, 52, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_A_VOP, 52, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_D_VOP0, 52, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_D_VOP2HDMI_BRIDGE0, 52, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_D_VOP2HDMI_BRIDGE1, 52, 15),
+
+ /* SOFTRST_CON53 */
+ RK3588_CRU_RESET_OFFSET(SRST_D_VOP1, 53, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_D_VOP2, 53, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_D_VOP3, 53, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VOPGRF, 53, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DSIHOST0, 53, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DSIHOST1, 53, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_DSIHOST0, 53, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_DSIHOST1, 53, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_VOP_PMU, 53, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VOP_CHANNEL_BIU, 53, 9),
+
+ /* SOFTRST_CON55 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_VO0_BIU, 55, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VO0_S_BIU, 55, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VO0_BIU, 55, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VO0_S_BIU, 55, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_A_HDCP0_BIU, 55, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VO0GRF, 55, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_H_HDCP_KEY0, 55, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_A_HDCP0, 55, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_H_HDCP0, 55, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_HDCP0, 55, 15),
+
+ /* SOFTRST_CON56 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_TRNG0, 56, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_DP0, 56, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_DP1, 56, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S4_8CH, 56, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S4_8CH_TX, 56, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S8_8CH, 56, 14),
+
+ /* SOFTRST_CON57 */
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S8_8CH_TX, 57, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SPDIF2_DP0, 57, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_M_SPDIF2_DP0, 57, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SPDIF5_DP1, 57, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_M_SPDIF5_DP1, 57, 11),
+
+ /* SOFTRST_CON59 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_HDCP1_BIU, 59, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_A_VO1_BIU, 59, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VOP1_BIU, 59, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VOP1_S_BIU, 59, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VOP1_BIU, 59, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VO1GRF, 59, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VO1_S_BIU, 59, 13),
+
+ /* SOFTRST_CON60 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S7_8CH, 60, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S7_8CH_RX, 60, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_HDCP_KEY1, 60, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_HDCP1, 60, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_H_HDCP1, 60, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_HDCP1, 60, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_TRNG1, 60, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_P_HDMITX0, 60, 11),
+
+ /* SOFTRST_CON61 */
+ RK3588_CRU_RESET_OFFSET(SRST_HDMITX0_REF, 61, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_P_HDMITX1, 61, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_HDMITX1_REF, 61, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_A_HDMIRX, 61, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_HDMIRX, 61, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_HDMIRX_REF, 61, 11),
+
+ /* SOFTRST_CON62 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_EDP0, 62, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_EDP0_24M, 62, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_EDP1, 62, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_EDP1_24M, 62, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S5_8CH_TX, 62, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S5_8CH, 62, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S6_8CH_TX, 62, 15),
+
+ /* SOFTRST_CON63 */
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S6_8CH_RX, 63, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S6_8CH, 63, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SPDIF3, 63, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_M_SPDIF3, 63, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SPDIF4, 63, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_M_SPDIF4, 63, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SPDIFRX0, 63, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_M_SPDIFRX0, 63, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SPDIFRX1, 63, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_M_SPDIFRX1, 63, 15),
+
+ /* SOFTRST_CON64 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_SPDIFRX2, 64, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_M_SPDIFRX2, 64, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_LINKSYM_HDMITXPHY0, 64, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_LINKSYM_HDMITXPHY1, 64, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_VO1_BRIDGE0, 64, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_VO1_BRIDGE1, 64, 15),
+
+ /* SOFTRST_CON65 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S9_8CH, 65, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S9_8CH_RX, 65, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S10_8CH, 65, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S10_8CH_RX, 65, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_S_HDMIRX, 65, 8),
+
+ /* SOFTRST_CON66 */
+ RK3588_CRU_RESET_OFFSET(SRST_GPU, 66, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_SYS_GPU, 66, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_A_S_GPU_BIU, 66, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_A_M0_GPU_BIU, 66, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_A_M1_GPU_BIU, 66, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_A_M2_GPU_BIU, 66, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_A_M3_GPU_BIU, 66, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_GPU_BIU, 66, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_P_GPU_PVTM, 66, 15),
+
+ /* SOFTRST_CON67 */
+ RK3588_CRU_RESET_OFFSET(SRST_GPU_PVTM, 67, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_P_GPU_GRF, 67, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_GPU_PVTPLL, 67, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_GPU_JTAG, 67, 4),
+
+ /* SOFTRST_CON68 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_AV1_BIU, 68, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_A_AV1, 68, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_AV1_BIU, 68, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_AV1, 68, 5),
+
+ /* SOFTRST_CON69 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR_BIU, 69, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DMA2DDR, 69, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR_SHAREMEM, 69, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR_SHAREMEM_BIU, 69, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_A_CENTER_S200_BIU, 69, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_A_CENTER_S400_BIU, 69, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_H_AHB2APB, 69, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_H_CENTER_BIU, 69, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_F_DDR_CM0_CORE, 69, 14),
+
+ /* SOFTRST_CON70 */
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_TIMER0, 70, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_TIMER1, 70, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_T_WDT_DDR, 70, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_T_DDR_CM0_JTAG, 70, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CENTER_GRF, 70, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_P_AHB2APB, 70, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_WDT, 70, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_TIMER, 70, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DMA2DDR, 70, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_SHAREMEM, 70, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CENTER_BIU, 70, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CENTER_CHANNEL_BIU, 70, 12),
+
+ /* SOFTRST_CON72 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_USBDPGRF0, 72, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_USBDPPHY0, 72, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_USBDPGRF1, 72, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_USBDPPHY1, 72, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_HDPTX0, 72, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_P_HDPTX1, 72, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_BOT_RIGHT, 72, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_USB2PHY_U3_0_GRF0, 72, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_USB2PHY_U3_1_GRF0, 72, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_USB2PHY_U2_0_GRF0, 72, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_P_USB2PHY_U2_1_GRF0, 72, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_HDPTX0_ROPLL, 72, 12), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_HDPTX0_LCPLL, 72, 13), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_HDPTX0, 72, 14), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_HDPTX1_ROPLL, 72, 15), // missing in TRM
+
+ /* SOFTRST_CON73 */
+ RK3588_CRU_RESET_OFFSET(SRST_HDPTX1_LCPLL, 73, 0), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_HDPTX1, 73, 1), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_HDPTX0_HDMIRXPHY_SET, 73, 2), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0, 73, 3), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_LCPLL, 73, 4), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_ROPLL, 73, 5), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_PCS_HS, 73, 6), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1, 73, 7), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_LCPLL, 73, 8), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_ROPLL, 73, 9), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_PCS_HS, 73, 10), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_HDMIHDP0, 73, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_HDMIHDP1, 73, 13),
+
+ /* SOFTRST_CON74 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_VO1USB_TOP_BIU, 74, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VO1USB_TOP_BIU, 74, 3),
+
+ /* SOFTRST_CON75 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_SDIO_BIU, 75, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SDIO, 75, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_SDIO, 75, 3),
+
+ /* SOFTRST_CON76 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_RGA3_BIU, 76, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RGA3_BIU, 76, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RGA3_1, 76, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RGA3_1, 76, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_RGA3_1_CORE, 76, 6),
+
+ /* SOFTRST_CON77 */
+ RK3588_CRU_RESET_OFFSET(SRST_REF_PIPE_PHY0, 77, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_REF_PIPE_PHY1, 77, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_REF_PIPE_PHY2, 77, 8),
+
+ /* PHPTOPCRU_SOFTRST_CON00 */
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PHPTOP_CRU, 0, 1),
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE2_GRF0, 0, 2),
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE2_GRF1, 0, 3),
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE2_GRF2, 0, 4),
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE2_PHY0, 0, 5),
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE2_PHY1, 0, 6),
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE2_PHY2, 0, 7),
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE3_PHY, 0, 8),
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_CHIP_TOP, 0, 9),
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_PCIE30_PHY, 0, 10),
+
+ /* PMU1CRU_SOFTRST_CON00 */
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_H_PMU1_BIU, 0, 10),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU1_BIU, 0, 11),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_H_PMU_CM0_BIU, 0, 12),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_F_PMU_CM0_CORE, 0, 13),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_T_PMU1_CM0_JTAG, 0, 14),
+
+ /* PMU1CRU_SOFTRST_CON01 */
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_DDR_FAIL_SAFE, 1, 1),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_CRU_PMU1, 1, 2),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU1_GRF, 1, 4),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU1_IOC, 1, 5),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU1WDT, 1, 6),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_T_PMU1WDT, 1, 7),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU1TIMER, 1, 8),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_PMU1TIMER0, 1, 10),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_PMU1TIMER1, 1, 11),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU1PWM, 1, 12),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_PMU1PWM, 1, 13),
+
+ /* PMU1CRU_SOFTRST_CON02 */
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_I2C0, 2, 1),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_I2C0, 2, 2),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_S_UART0, 2, 5),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_UART0, 2, 6),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_H_I2S1_8CH, 2, 7),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_M_I2S1_8CH_TX, 2, 10),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_M_I2S1_8CH_RX, 2, 13),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_H_PDM0, 2, 14),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_PDM0, 2, 15),
+
+ /* PMU1CRU_SOFTRST_CON03 */
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_H_VAD, 3, 0),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_HDPTX0_INIT, 3, 11),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_HDPTX0_CMN, 3, 12),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_HDPTX0_LANE, 3, 13),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_HDPTX1_INIT, 3, 15),
+
+ /* PMU1CRU_SOFTRST_CON04 */
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_HDPTX1_CMN, 4, 0),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_HDPTX1_LANE, 4, 1),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_M_MIPI_DCPHY0, 4, 3),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_S_MIPI_DCPHY0, 4, 4),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_M_MIPI_DCPHY1, 4, 5),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_S_MIPI_DCPHY1, 4, 6),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_OTGPHY_U3_0, 4, 7),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_OTGPHY_U3_1, 4, 8),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_OTGPHY_U2_0, 4, 9),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_OTGPHY_U2_1, 4, 10),
+
+ /* PMU1CRU_SOFTRST_CON05 */
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU0GRF, 5, 3),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU0IOC, 5, 4),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_GPIO0, 5, 5),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_GPIO0, 5, 6),
+
+ /* SECURECRU_SOFTRST_CON00 */
+ RK3588_SECURECRU_RESET_OFFSET(SRST_A_SECURE_NS_BIU, 0, 10),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_SECURE_NS_BIU, 0, 11),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_A_SECURE_S_BIU, 0, 12),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_SECURE_S_BIU, 0, 13),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_P_SECURE_S_BIU, 0, 14),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_CRYPTO_CORE, 0, 15),
+
+ /* SECURECRU_SOFTRST_CON01 */
+ RK3588_SECURECRU_RESET_OFFSET(SRST_CRYPTO_PKA, 1, 0),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_CRYPTO_RNG, 1, 1),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_A_CRYPTO, 1, 2),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_CRYPTO, 1, 3),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_KEYLADDER_CORE, 1, 9),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_KEYLADDER_RNG, 1, 10),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_A_KEYLADDER, 1, 11),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_KEYLADDER, 1, 12),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_P_OTPC_S, 1, 13),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_OTPC_S, 1, 14),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_WDT_S, 1, 15),
+
+ /* SECURECRU_SOFTRST_CON02 */
+ RK3588_SECURECRU_RESET_OFFSET(SRST_T_WDT_S, 2, 0),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_BOOTROM, 2, 1),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_A_DCF, 2, 2),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_P_DCF, 2, 3),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_BOOTROM_NS, 2, 5),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_P_KEYLADDER, 2, 14),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_TRNG_S, 2, 15),
+
+ /* SECURECRU_SOFTRST_CON03 */
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_TRNG_NS, 3, 0),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_D_SDMMC_BUFFER, 3, 1),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_SDMMC, 3, 2),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_SDMMC_BUFFER, 3, 3),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_SDMMC, 3, 4),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_P_TRNG_CHK, 3, 5),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_TRNG_S, 3, 6),
+};
+
+void rk3588_rst_init(struct device_node *np, void __iomem *reg_base)
+{
+ rockchip_register_softrst_lut(np,
+ rk3588_register_offset,
+ ARRAY_SIZE(rk3588_register_offset),
+ reg_base + RK3588_SOFTRST_CON(0),
+ ROCKCHIP_SOFTRST_HIWORD_MASK);
+}
diff --git a/drivers/clk/rockchip/softrst.c b/drivers/clk/rockchip/softrst.c
new file mode 100644
index 0000000000..929b227154
--- /dev/null
+++ b/drivers/clk/rockchip/softrst.c
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ */
+
+#include <common.h>
+#include <io.h>
+#include <linux/bitops.h>
+#include <linux/reset-controller.h>
+#include <linux/spinlock.h>
+#include "clk.h"
+
+struct rockchip_softrst {
+ struct reset_controller_dev rcdev;
+ const int *lut;
+ void __iomem *reg_base;
+ int num_regs;
+ int num_per_reg;
+ u8 flags;
+ spinlock_t lock;
+};
+
+static int rockchip_softrst_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct rockchip_softrst *softrst = container_of(rcdev,
+ struct rockchip_softrst,
+ rcdev);
+ int bank, offset;
+
+ if (softrst->lut)
+ id = softrst->lut[id];
+
+ bank = id / softrst->num_per_reg;
+ offset = id % softrst->num_per_reg;
+
+ if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {
+ writel(BIT(offset) | (BIT(offset) << 16),
+ softrst->reg_base + (bank * 4));
+ } else {
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&softrst->lock, flags);
+
+ reg = readl(softrst->reg_base + (bank * 4));
+ writel(reg | BIT(offset), softrst->reg_base + (bank * 4));
+
+ spin_unlock_irqrestore(&softrst->lock, flags);
+ }
+
+ return 0;
+}
+
+static int rockchip_softrst_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct rockchip_softrst *softrst = container_of(rcdev,
+ struct rockchip_softrst,
+ rcdev);
+ int bank, offset;
+
+ if (softrst->lut)
+ id = softrst->lut[id];
+
+ bank = id / softrst->num_per_reg;
+ offset = id % softrst->num_per_reg;
+
+ if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {
+ writel((BIT(offset) << 16), softrst->reg_base + (bank * 4));
+ } else {
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&softrst->lock, flags);
+
+ reg = readl(softrst->reg_base + (bank * 4));
+ writel(reg & ~BIT(offset), softrst->reg_base + (bank * 4));
+
+ spin_unlock_irqrestore(&softrst->lock, flags);
+ }
+
+ return 0;
+}
+
+static const struct reset_control_ops rockchip_softrst_ops = {
+ .assert = rockchip_softrst_assert,
+ .deassert = rockchip_softrst_deassert,
+};
+
+void rockchip_register_softrst_lut(struct device_node *np,
+ const int *lookup_table,
+ unsigned int num_regs,
+ void __iomem *base, u8 flags)
+{
+ struct rockchip_softrst *softrst;
+ int ret;
+
+ softrst = kzalloc(sizeof(*softrst), GFP_KERNEL);
+ if (!softrst)
+ return;
+
+ spin_lock_init(&softrst->lock);
+
+ softrst->reg_base = base;
+ softrst->lut = lookup_table;
+ softrst->flags = flags;
+ softrst->num_regs = num_regs;
+ softrst->num_per_reg = (flags & ROCKCHIP_SOFTRST_HIWORD_MASK) ? 16
+ : 32;
+
+ if (lookup_table)
+ softrst->rcdev.nr_resets = num_regs;
+ else
+ softrst->rcdev.nr_resets = num_regs * softrst->num_per_reg;
+ softrst->rcdev.ops = &rockchip_softrst_ops;
+ softrst->rcdev.of_node = np;
+ ret = reset_controller_register(&softrst->rcdev);
+ if (ret) {
+ pr_err("%s: could not register reset controller, %d\n",
+ __func__, ret);
+ kfree(softrst);
+ }
+};
+EXPORT_SYMBOL_GPL(rockchip_register_softrst_lut);
diff --git a/drivers/clk/sifive/Kconfig b/drivers/clk/sifive/Kconfig
new file mode 100644
index 0000000000..01343b305b
--- /dev/null
+++ b/drivers/clk/sifive/Kconfig
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+menuconfig CLK_SIFIVE
+ bool "SiFive SoC driver support"
+ depends on RISCV || COMPILE_TEST
+ help
+ SoC drivers for SiFive Linux-capable SoCs.
+
+if CLK_SIFIVE
+
+config CLK_SIFIVE_PRCI
+ bool "PRCI driver for SiFive SoCs"
+ help
+ Supports the Power Reset Clock interface (PRCI) IP block found in
+ FU540/FU740 SoCs. If this kernel is meant to run on a SiFive FU540/
+ FU740 SoCs, enable this driver.
+
+endif
diff --git a/drivers/clk/sifive/Makefile b/drivers/clk/sifive/Makefile
new file mode 100644
index 0000000000..7b06fc04e6
--- /dev/null
+++ b/drivers/clk/sifive/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_CLK_SIFIVE_PRCI) += sifive-prci.o fu540-prci.o fu740-prci.o
diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c
new file mode 100644
index 0000000000..312a583b1d
--- /dev/null
+++ b/drivers/clk/sifive/fu540-prci.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2018-2019 SiFive, Inc.
+ * Copyright (C) 2018-2019 Wesley Terpstra
+ * Copyright (C) 2018-2019 Paul Walmsley
+ * Copyright (C) 2020 Zong Li
+ *
+ * The FU540 PRCI implements clock and reset control for the SiFive
+ * FU540-C000 chip. This driver assumes that it has sole control
+ * over all PRCI resources.
+ *
+ * This driver is based on the PRCI driver written by Wesley Terpstra:
+ * https://github.com/riscv/riscv-linux/commit/999529edf517ed75b56659d456d221b2ee56bb60
+ *
+ * References:
+ * - SiFive FU540-C000 manual v1p0, Chapter 7 "Clocking and Reset"
+ */
+
+#include <dt-bindings/clock/sifive-fu540-prci.h>
+
+#include "fu540-prci.h"
+#include "sifive-prci.h"
+
+/* PRCI integration data for each WRPLL instance */
+
+static struct __prci_wrpll_data __prci_corepll_data = {
+ .cfg0_offs = PRCI_COREPLLCFG0_OFFSET,
+ .cfg1_offs = PRCI_COREPLLCFG1_OFFSET,
+ .enable_bypass = sifive_prci_coreclksel_use_hfclk,
+ .disable_bypass = sifive_prci_coreclksel_use_corepll,
+};
+
+static struct __prci_wrpll_data __prci_ddrpll_data = {
+ .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
+ .cfg1_offs = PRCI_DDRPLLCFG1_OFFSET,
+};
+
+static struct __prci_wrpll_data __prci_gemgxlpll_data = {
+ .cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET,
+ .cfg1_offs = PRCI_GEMGXLPLLCFG1_OFFSET,
+};
+
+/* Linux clock framework integration */
+
+static const struct clk_ops sifive_fu540_prci_wrpll_clk_ops = {
+ .set_rate = sifive_prci_wrpll_set_rate,
+ .round_rate = sifive_prci_wrpll_round_rate,
+ .recalc_rate = sifive_prci_wrpll_recalc_rate,
+ .enable = sifive_prci_clock_enable,
+ .disable = sifive_prci_clock_disable,
+ .is_enabled = sifive_clk_is_enabled,
+};
+
+static const struct clk_ops sifive_fu540_prci_wrpll_ro_clk_ops = {
+ .recalc_rate = sifive_prci_wrpll_recalc_rate,
+};
+
+static const struct clk_ops sifive_fu540_prci_tlclksel_clk_ops = {
+ .recalc_rate = sifive_prci_tlclksel_recalc_rate,
+};
+
+/* List of clock controls provided by the PRCI */
+struct __prci_clock __prci_init_clocks_fu540[] = {
+ [FU540_PRCI_CLK_COREPLL] = {
+ .name = "corepll",
+ .parent_name = "hfclk",
+ .ops = &sifive_fu540_prci_wrpll_clk_ops,
+ .pwd = &__prci_corepll_data,
+ },
+ [FU540_PRCI_CLK_DDRPLL] = {
+ .name = "ddrpll",
+ .parent_name = "hfclk",
+ .ops = &sifive_fu540_prci_wrpll_ro_clk_ops,
+ .pwd = &__prci_ddrpll_data,
+ },
+ [FU540_PRCI_CLK_GEMGXLPLL] = {
+ .name = "gemgxlpll",
+ .parent_name = "hfclk",
+ .ops = &sifive_fu540_prci_wrpll_clk_ops,
+ .pwd = &__prci_gemgxlpll_data,
+ },
+ [FU540_PRCI_CLK_TLCLK] = {
+ .name = "tlclk",
+ .parent_name = "corepll",
+ .ops = &sifive_fu540_prci_tlclksel_clk_ops,
+ },
+};
diff --git a/drivers/clk/sifive/fu540-prci.h b/drivers/clk/sifive/fu540-prci.h
new file mode 100644
index 0000000000..b15ff494fd
--- /dev/null
+++ b/drivers/clk/sifive/fu540-prci.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2020 SiFive, Inc.
+ * Zong Li
+ */
+
+#ifndef __SIFIVE_CLK_FU540_PRCI_H
+#define __SIFIVE_CLK_FU540_PRCI_H
+
+#include "sifive-prci.h"
+
+#define NUM_CLOCK_FU540 4
+
+extern struct __prci_clock __prci_init_clocks_fu540[NUM_CLOCK_FU540];
+
+#endif /* __SIFIVE_CLK_FU540_PRCI_H */
diff --git a/drivers/clk/sifive/fu740-prci.c b/drivers/clk/sifive/fu740-prci.c
new file mode 100644
index 0000000000..30bb53accf
--- /dev/null
+++ b/drivers/clk/sifive/fu740-prci.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2020 SiFive, Inc.
+ * Copyright (C) 2020 Zong Li
+ */
+
+#include <dt-bindings/clock/sifive-fu740-prci.h>
+
+#include "fu540-prci.h"
+#include "sifive-prci.h"
+
+/* PRCI integration data for each WRPLL instance */
+
+static struct __prci_wrpll_data __prci_corepll_data = {
+ .cfg0_offs = PRCI_COREPLLCFG0_OFFSET,
+ .cfg1_offs = PRCI_COREPLLCFG1_OFFSET,
+ .enable_bypass = sifive_prci_coreclksel_use_hfclk,
+ .disable_bypass = sifive_prci_coreclksel_use_final_corepll,
+};
+
+static struct __prci_wrpll_data __prci_ddrpll_data = {
+ .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
+ .cfg1_offs = PRCI_DDRPLLCFG1_OFFSET,
+};
+
+static struct __prci_wrpll_data __prci_gemgxlpll_data = {
+ .cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET,
+ .cfg1_offs = PRCI_GEMGXLPLLCFG1_OFFSET,
+};
+
+static struct __prci_wrpll_data __prci_dvfscorepll_data = {
+ .cfg0_offs = PRCI_DVFSCOREPLLCFG0_OFFSET,
+ .cfg1_offs = PRCI_DVFSCOREPLLCFG1_OFFSET,
+ .enable_bypass = sifive_prci_corepllsel_use_corepll,
+ .disable_bypass = sifive_prci_corepllsel_use_dvfscorepll,
+};
+
+static struct __prci_wrpll_data __prci_hfpclkpll_data = {
+ .cfg0_offs = PRCI_HFPCLKPLLCFG0_OFFSET,
+ .cfg1_offs = PRCI_HFPCLKPLLCFG1_OFFSET,
+ .enable_bypass = sifive_prci_hfpclkpllsel_use_hfclk,
+ .disable_bypass = sifive_prci_hfpclkpllsel_use_hfpclkpll,
+};
+
+static struct __prci_wrpll_data __prci_cltxpll_data = {
+ .cfg0_offs = PRCI_CLTXPLLCFG0_OFFSET,
+ .cfg1_offs = PRCI_CLTXPLLCFG1_OFFSET,
+};
+
+/* Linux clock framework integration */
+
+static const struct clk_ops sifive_fu740_prci_wrpll_clk_ops = {
+ .set_rate = sifive_prci_wrpll_set_rate,
+ .round_rate = sifive_prci_wrpll_round_rate,
+ .recalc_rate = sifive_prci_wrpll_recalc_rate,
+ .enable = sifive_prci_clock_enable,
+ .disable = sifive_prci_clock_disable,
+ .is_enabled = sifive_clk_is_enabled,
+};
+
+static const struct clk_ops sifive_fu740_prci_wrpll_ro_clk_ops = {
+ .recalc_rate = sifive_prci_wrpll_recalc_rate,
+};
+
+static const struct clk_ops sifive_fu740_prci_tlclksel_clk_ops = {
+ .recalc_rate = sifive_prci_tlclksel_recalc_rate,
+};
+
+static const struct clk_ops sifive_fu740_prci_hfpclkplldiv_clk_ops = {
+ .recalc_rate = sifive_prci_hfpclkplldiv_recalc_rate,
+};
+
+/* List of clock controls provided by the PRCI */
+struct __prci_clock __prci_init_clocks_fu740[] = {
+ [FU740_PRCI_CLK_COREPLL] = {
+ .name = "corepll",
+ .parent_name = "hfclk",
+ .ops = &sifive_fu740_prci_wrpll_clk_ops,
+ .pwd = &__prci_corepll_data,
+ },
+ [FU740_PRCI_CLK_DDRPLL] = {
+ .name = "ddrpll",
+ .parent_name = "hfclk",
+ .ops = &sifive_fu740_prci_wrpll_ro_clk_ops,
+ .pwd = &__prci_ddrpll_data,
+ },
+ [FU740_PRCI_CLK_GEMGXLPLL] = {
+ .name = "gemgxlpll",
+ .parent_name = "hfclk",
+ .ops = &sifive_fu740_prci_wrpll_clk_ops,
+ .pwd = &__prci_gemgxlpll_data,
+ },
+ [FU740_PRCI_CLK_DVFSCOREPLL] = {
+ .name = "dvfscorepll",
+ .parent_name = "hfclk",
+ .ops = &sifive_fu740_prci_wrpll_clk_ops,
+ .pwd = &__prci_dvfscorepll_data,
+ },
+ [FU740_PRCI_CLK_HFPCLKPLL] = {
+ .name = "hfpclkpll",
+ .parent_name = "hfclk",
+ .ops = &sifive_fu740_prci_wrpll_clk_ops,
+ .pwd = &__prci_hfpclkpll_data,
+ },
+ [FU740_PRCI_CLK_CLTXPLL] = {
+ .name = "cltxpll",
+ .parent_name = "hfclk",
+ .ops = &sifive_fu740_prci_wrpll_clk_ops,
+ .pwd = &__prci_cltxpll_data,
+ },
+ [FU740_PRCI_CLK_TLCLK] = {
+ .name = "tlclk",
+ .parent_name = "corepll",
+ .ops = &sifive_fu740_prci_tlclksel_clk_ops,
+ },
+ [FU740_PRCI_CLK_PCLK] = {
+ .name = "pclk",
+ .parent_name = "hfpclkpll",
+ .ops = &sifive_fu740_prci_hfpclkplldiv_clk_ops,
+ },
+};
diff --git a/drivers/clk/sifive/fu740-prci.h b/drivers/clk/sifive/fu740-prci.h
new file mode 100644
index 0000000000..a459cca2da
--- /dev/null
+++ b/drivers/clk/sifive/fu740-prci.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2020 SiFive, Inc.
+ * Zong Li
+ */
+
+#ifndef __SIFIVE_CLK_FU740_PRCI_H
+#define __SIFIVE_CLK_FU740_PRCI_H
+
+#include "sifive-prci.h"
+
+#define NUM_CLOCK_FU740 8
+
+extern struct __prci_clock __prci_init_clocks_fu740[NUM_CLOCK_FU740];
+
+static const struct prci_clk_desc prci_clk_fu740 = {
+ .clks = __prci_init_clocks_fu740,
+ .num_clks = ARRAY_SIZE(__prci_init_clocks_fu740),
+};
+
+#endif /* __SIFIVE_CLK_FU740_PRCI_H */
diff --git a/drivers/clk/sifive/sifive-prci.c b/drivers/clk/sifive/sifive-prci.c
new file mode 100644
index 0000000000..349629d82a
--- /dev/null
+++ b/drivers/clk/sifive/sifive-prci.c
@@ -0,0 +1,586 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2020 SiFive, Inc.
+ * Copyright (C) 2020 Zong Li
+ */
+
+#include <common.h>
+#include <linux/list.h>
+#include <linux/clkdev.h>
+#include <linux/overflow.h>
+#include <linux/printk.h>
+#include <clock.h>
+#include <io.h>
+#include <of.h>
+#include <driver.h>
+#include <init.h>
+#include "sifive-prci.h"
+#include "fu540-prci.h"
+#include "fu740-prci.h"
+
+static const struct prci_clk_desc prci_clk_fu540 = {
+ .clks = __prci_init_clocks_fu540,
+ .num_clks = ARRAY_SIZE(__prci_init_clocks_fu540),
+};
+
+/*
+ * Private functions
+ */
+
+/**
+ * __prci_readl() - read from a PRCI register
+ * @pd: PRCI context
+ * @offs: register offset to read from (in bytes, from PRCI base address)
+ *
+ * Read the register located at offset @offs from the base virtual
+ * address of the PRCI register target described by @pd, and return
+ * the value to the caller.
+ *
+ * Context: Any context.
+ *
+ * Return: the contents of the register described by @pd and @offs.
+ */
+static u32 __prci_readl(struct __prci_data *pd, u32 offs)
+{
+ return readl(pd->va + offs);
+}
+
+static void __prci_writel(u32 v, u32 offs, struct __prci_data *pd)
+{
+ writel(v, pd->va + offs);
+}
+
+/* WRPLL-related private functions */
+
+/**
+ * __prci_wrpll_unpack() - unpack WRPLL configuration registers into parameters
+ * @c: ptr to a struct wrpll_cfg record to write config into
+ * @r: value read from the PRCI PLL configuration register
+ *
+ * Given a value @r read from an FU740 PRCI PLL configuration register,
+ * split it into fields and populate it into the WRPLL configuration record
+ * pointed to by @c.
+ *
+ * The COREPLLCFG0 macros are used below, but the other *PLLCFG0 macros
+ * have the same register layout.
+ *
+ * Context: Any context.
+ */
+static void __prci_wrpll_unpack(struct wrpll_cfg *c, u32 r)
+{
+ u32 v;
+
+ v = r & PRCI_COREPLLCFG0_DIVR_MASK;
+ v >>= PRCI_COREPLLCFG0_DIVR_SHIFT;
+ c->divr = v;
+
+ v = r & PRCI_COREPLLCFG0_DIVF_MASK;
+ v >>= PRCI_COREPLLCFG0_DIVF_SHIFT;
+ c->divf = v;
+
+ v = r & PRCI_COREPLLCFG0_DIVQ_MASK;
+ v >>= PRCI_COREPLLCFG0_DIVQ_SHIFT;
+ c->divq = v;
+
+ v = r & PRCI_COREPLLCFG0_RANGE_MASK;
+ v >>= PRCI_COREPLLCFG0_RANGE_SHIFT;
+ c->range = v;
+
+ c->flags &=
+ (WRPLL_FLAGS_INT_FEEDBACK_MASK | WRPLL_FLAGS_EXT_FEEDBACK_MASK);
+
+ /* external feedback mode not supported */
+ c->flags |= WRPLL_FLAGS_INT_FEEDBACK_MASK;
+}
+
+/**
+ * __prci_wrpll_pack() - pack PLL configuration parameters into a register value
+ * @c: pointer to a struct wrpll_cfg record containing the PLL's cfg
+ *
+ * Using a set of WRPLL configuration values pointed to by @c,
+ * assemble a PRCI PLL configuration register value, and return it to
+ * the caller.
+ *
+ * Context: Any context. Caller must ensure that the contents of the
+ * record pointed to by @c do not change during the execution
+ * of this function.
+ *
+ * Returns: a value suitable for writing into a PRCI PLL configuration
+ * register
+ */
+static u32 __prci_wrpll_pack(const struct wrpll_cfg *c)
+{
+ u32 r = 0;
+
+ r |= c->divr << PRCI_COREPLLCFG0_DIVR_SHIFT;
+ r |= c->divf << PRCI_COREPLLCFG0_DIVF_SHIFT;
+ r |= c->divq << PRCI_COREPLLCFG0_DIVQ_SHIFT;
+ r |= c->range << PRCI_COREPLLCFG0_RANGE_SHIFT;
+
+ /* external feedback mode not supported */
+ r |= PRCI_COREPLLCFG0_FSE_MASK;
+
+ return r;
+}
+
+/**
+ * __prci_wrpll_read_cfg0() - read the WRPLL configuration from the PRCI
+ * @pd: PRCI context
+ * @pwd: PRCI WRPLL metadata
+ *
+ * Read the current configuration of the PLL identified by @pwd from
+ * the PRCI identified by @pd, and store it into the local configuration
+ * cache in @pwd.
+ *
+ * Context: Any context. Caller must prevent the records pointed to by
+ * @pd and @pwd from changing during execution.
+ */
+static void __prci_wrpll_read_cfg0(struct __prci_data *pd,
+ struct __prci_wrpll_data *pwd)
+{
+ __prci_wrpll_unpack(&pwd->c, __prci_readl(pd, pwd->cfg0_offs));
+}
+
+/**
+ * __prci_wrpll_write_cfg0() - write WRPLL configuration into the PRCI
+ * @pd: PRCI context
+ * @pwd: PRCI WRPLL metadata
+ * @c: WRPLL configuration record to write
+ *
+ * Write the WRPLL configuration described by @c into the WRPLL
+ * configuration register identified by @pwd in the PRCI instance
+ * described by @c. Make a cached copy of the WRPLL's current
+ * configuration so it can be used by other code.
+ *
+ * Context: Any context. Caller must prevent the records pointed to by
+ * @pd and @pwd from changing during execution.
+ */
+static void __prci_wrpll_write_cfg0(struct __prci_data *pd,
+ struct __prci_wrpll_data *pwd,
+ struct wrpll_cfg *c)
+{
+ __prci_writel(__prci_wrpll_pack(c), pwd->cfg0_offs, pd);
+
+ memcpy(&pwd->c, c, sizeof(*c));
+}
+
+/**
+ * __prci_wrpll_write_cfg1() - write Clock enable/disable configuration
+ * into the PRCI
+ * @pd: PRCI context
+ * @pwd: PRCI WRPLL metadata
+ * @enable: Clock enable or disable value
+ */
+static void __prci_wrpll_write_cfg1(struct __prci_data *pd,
+ struct __prci_wrpll_data *pwd,
+ u32 enable)
+{
+ __prci_writel(enable, pwd->cfg1_offs, pd);
+}
+
+/*
+ * Linux clock framework integration
+ *
+ * See the Linux clock framework documentation for more information on
+ * these functions.
+ */
+
+unsigned long sifive_prci_wrpll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+ struct __prci_wrpll_data *pwd = pc->pwd;
+
+ return wrpll_calc_output_rate(&pwd->c, parent_rate);
+}
+
+long sifive_prci_wrpll_round_rate(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+ struct __prci_wrpll_data *pwd = pc->pwd;
+ struct wrpll_cfg c;
+
+ memcpy(&c, &pwd->c, sizeof(c));
+
+ wrpll_configure_for_rate(&c, rate, *parent_rate);
+
+ return wrpll_calc_output_rate(&c, *parent_rate);
+}
+
+int sifive_prci_wrpll_set_rate(struct clk_hw *hw,
+ unsigned long rate, unsigned long parent_rate)
+{
+ struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+ struct __prci_wrpll_data *pwd = pc->pwd;
+ struct __prci_data *pd = pc->pd;
+ int r;
+
+ r = wrpll_configure_for_rate(&pwd->c, rate, parent_rate);
+ if (r)
+ return r;
+
+ if (pwd->enable_bypass)
+ pwd->enable_bypass(pd);
+
+ __prci_wrpll_write_cfg0(pd, pwd, &pwd->c);
+
+ udelay(wrpll_calc_max_lock_us(&pwd->c));
+
+ return 0;
+}
+
+int sifive_clk_is_enabled(struct clk_hw *hw)
+{
+ struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+ struct __prci_wrpll_data *pwd = pc->pwd;
+ struct __prci_data *pd = pc->pd;
+ u32 r;
+
+ r = __prci_readl(pd, pwd->cfg1_offs);
+
+ if (r & PRCI_COREPLLCFG1_CKE_MASK)
+ return 1;
+ else
+ return 0;
+}
+
+int sifive_prci_clock_enable(struct clk_hw *hw)
+{
+ struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+ struct __prci_wrpll_data *pwd = pc->pwd;
+ struct __prci_data *pd = pc->pd;
+
+ if (sifive_clk_is_enabled(hw))
+ return 0;
+
+ __prci_wrpll_write_cfg1(pd, pwd, PRCI_COREPLLCFG1_CKE_MASK);
+
+ if (pwd->disable_bypass)
+ pwd->disable_bypass(pd);
+
+ return 0;
+}
+
+void sifive_prci_clock_disable(struct clk_hw *hw)
+{
+ struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+ struct __prci_wrpll_data *pwd = pc->pwd;
+ struct __prci_data *pd = pc->pd;
+ u32 r;
+
+ if (pwd->enable_bypass)
+ pwd->enable_bypass(pd);
+
+ r = __prci_readl(pd, pwd->cfg1_offs);
+ r &= ~PRCI_COREPLLCFG1_CKE_MASK;
+
+ __prci_wrpll_write_cfg1(pd, pwd, r);
+}
+
+/* TLCLKSEL clock integration */
+
+unsigned long sifive_prci_tlclksel_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+ struct __prci_data *pd = pc->pd;
+ u32 v;
+ u8 div;
+
+ v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
+ v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
+ div = v ? 1 : 2;
+
+ return div_u64(parent_rate, div);
+}
+
+/* HFPCLK clock integration */
+
+unsigned long sifive_prci_hfpclkplldiv_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+ struct __prci_data *pd = pc->pd;
+ u32 div = __prci_readl(pd, PRCI_HFPCLKPLLDIV_OFFSET);
+
+ return div_u64(parent_rate, div + 2);
+}
+
+/*
+ * Core clock mux control
+ */
+
+/**
+ * sifive_prci_coreclksel_use_hfclk() - switch the CORECLK mux to output HFCLK
+ * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
+ *
+ * Switch the CORECLK mux to the HFCLK input source; return once complete.
+ *
+ * Context: Any context. Caller must prevent concurrent changes to the
+ * PRCI_CORECLKSEL_OFFSET register.
+ */
+void sifive_prci_coreclksel_use_hfclk(struct __prci_data *pd)
+{
+ u32 r;
+
+ r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
+ r |= PRCI_CORECLKSEL_CORECLKSEL_MASK;
+ __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
+
+ r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); /* barrier */
+}
+
+/**
+ * sifive_prci_coreclksel_use_corepll() - switch the CORECLK mux to output
+ * COREPLL
+ * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
+ *
+ * Switch the CORECLK mux to the COREPLL output clock; return once complete.
+ *
+ * Context: Any context. Caller must prevent concurrent changes to the
+ * PRCI_CORECLKSEL_OFFSET register.
+ */
+void sifive_prci_coreclksel_use_corepll(struct __prci_data *pd)
+{
+ u32 r;
+
+ r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
+ r &= ~PRCI_CORECLKSEL_CORECLKSEL_MASK;
+ __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
+
+ r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); /* barrier */
+}
+
+/**
+ * sifive_prci_coreclksel_use_final_corepll() - switch the CORECLK mux to output
+ * FINAL_COREPLL
+ * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
+ *
+ * Switch the CORECLK mux to the final COREPLL output clock; return once
+ * complete.
+ *
+ * Context: Any context. Caller must prevent concurrent changes to the
+ * PRCI_CORECLKSEL_OFFSET register.
+ */
+void sifive_prci_coreclksel_use_final_corepll(struct __prci_data *pd)
+{
+ u32 r;
+
+ r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
+ r &= ~PRCI_CORECLKSEL_CORECLKSEL_MASK;
+ __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
+
+ r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); /* barrier */
+}
+
+/**
+ * sifive_prci_corepllsel_use_dvfscorepll() - switch the COREPLL mux to
+ * output DVFS_COREPLL
+ * @pd: struct __prci_data * for the PRCI containing the COREPLL mux reg
+ *
+ * Switch the COREPLL mux to the DVFSCOREPLL output clock; return once complete.
+ *
+ * Context: Any context. Caller must prevent concurrent changes to the
+ * PRCI_COREPLLSEL_OFFSET register.
+ */
+void sifive_prci_corepllsel_use_dvfscorepll(struct __prci_data *pd)
+{
+ u32 r;
+
+ r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET);
+ r |= PRCI_COREPLLSEL_COREPLLSEL_MASK;
+ __prci_writel(r, PRCI_COREPLLSEL_OFFSET, pd);
+
+ r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET); /* barrier */
+}
+
+/**
+ * sifive_prci_corepllsel_use_corepll() - switch the COREPLL mux to
+ * output COREPLL
+ * @pd: struct __prci_data * for the PRCI containing the COREPLL mux reg
+ *
+ * Switch the COREPLL mux to the COREPLL output clock; return once complete.
+ *
+ * Context: Any context. Caller must prevent concurrent changes to the
+ * PRCI_COREPLLSEL_OFFSET register.
+ */
+void sifive_prci_corepllsel_use_corepll(struct __prci_data *pd)
+{
+ u32 r;
+
+ r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET);
+ r &= ~PRCI_COREPLLSEL_COREPLLSEL_MASK;
+ __prci_writel(r, PRCI_COREPLLSEL_OFFSET, pd);
+
+ r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET); /* barrier */
+}
+
+/**
+ * sifive_prci_hfpclkpllsel_use_hfclk() - switch the HFPCLKPLL mux to
+ * output HFCLK
+ * @pd: struct __prci_data * for the PRCI containing the HFPCLKPLL mux reg
+ *
+ * Switch the HFPCLKPLL mux to the HFCLK input source; return once complete.
+ *
+ * Context: Any context. Caller must prevent concurrent changes to the
+ * PRCI_HFPCLKPLLSEL_OFFSET register.
+ */
+void sifive_prci_hfpclkpllsel_use_hfclk(struct __prci_data *pd)
+{
+ u32 r;
+
+ r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET);
+ r |= PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_MASK;
+ __prci_writel(r, PRCI_HFPCLKPLLSEL_OFFSET, pd);
+
+ r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET); /* barrier */
+}
+
+/**
+ * sifive_prci_hfpclkpllsel_use_hfpclkpll() - switch the HFPCLKPLL mux to
+ * output HFPCLKPLL
+ * @pd: struct __prci_data * for the PRCI containing the HFPCLKPLL mux reg
+ *
+ * Switch the HFPCLKPLL mux to the HFPCLKPLL output clock; return once complete.
+ *
+ * Context: Any context. Caller must prevent concurrent changes to the
+ * PRCI_HFPCLKPLLSEL_OFFSET register.
+ */
+void sifive_prci_hfpclkpllsel_use_hfpclkpll(struct __prci_data *pd)
+{
+ u32 r;
+
+ r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET);
+ r &= ~PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_MASK;
+ __prci_writel(r, PRCI_HFPCLKPLLSEL_OFFSET, pd);
+
+ r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET); /* barrier */
+}
+
+/**
+ * __prci_register_clocks() - register clock controls in the PRCI
+ * @dev: Linux struct device
+ * @pd: The pointer for PRCI per-device instance data
+ * @desc: The pointer for the information of clocks of each SoCs
+ *
+ * Register the list of clock controls described in __prci_init_clocks[] with
+ * the Linux clock framework.
+ *
+ * Return: 0 upon success or a negative error code upon failure.
+ */
+static int __prci_register_clocks(struct device *dev, struct __prci_data *pd,
+ const struct prci_clk_desc *desc)
+{
+ struct clk_init_data init = { };
+ struct __prci_clock *pic;
+ int parent_count, i, r;
+
+ parent_count = of_clk_get_parent_count(dev->of_node);
+ if (parent_count != EXPECTED_CLK_PARENT_COUNT) {
+ dev_err(dev, "expected only two parent clocks, found %d\n",
+ parent_count);
+ return -EINVAL;
+ }
+
+ /* Register PLLs */
+ for (i = 0; i < desc->num_clks; ++i) {
+ struct clk *clk;
+
+ pic = &(desc->clks[i]);
+
+ init.name = pic->name;
+ init.parent_names = &pic->parent_name;
+ init.num_parents = 1;
+ init.ops = pic->ops;
+ pic->hw.init = &init;
+
+ pic->pd = pd;
+
+ if (pic->pwd)
+ __prci_wrpll_read_cfg0(pd, pic->pwd);
+
+ clk = clk_register(dev, &pic->hw);
+ if (IS_ERR(clk)) {
+ dev_warn(dev, "Failed to register clock %s: %d\n",
+ clk_hw_get_name(&pic->hw), r);
+ return PTR_ERR(clk);
+ }
+
+ r = clk_register_clkdev(clk, pic->name, dev_name(dev));
+ if (r) {
+ dev_warn(dev, "Failed to register clkdev for %s: %d\n",
+ clk_hw_get_name(&pic->hw), r);
+ return r;
+ }
+
+ pd->hw_clks.clks[i] = clk;
+ }
+
+ pd->hw_clks.clk_num = i;
+
+ r = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
+ &pd->hw_clks);
+ if (r) {
+ dev_err(dev, "could not add hw_provider: %d\n", r);
+ return r;
+ }
+
+ return 0;
+}
+
+/**
+ * sifive_prci_init() - initialize prci data and check parent count
+ * @dev: platform device pointer for the prci
+ *
+ * Return: 0 upon success or a negative error code upon failure.
+ */
+static int sifive_prci_probe(struct device *dev)
+{
+ struct resource *res;
+ struct __prci_data *pd;
+ const struct prci_clk_desc *desc;
+ int r;
+
+ desc = device_get_match_data(dev);
+
+ pd = malloc(sizeof(*pd));
+ if (!pd)
+ return -ENOMEM;
+
+ pd->hw_clks.clk_num = desc->num_clks;
+ pd->hw_clks.clks = calloc(pd->hw_clks.clk_num, sizeof(*pd->hw_clks.clks));
+ if (!pd->hw_clks.clks)
+ return -ENOMEM;
+
+ res = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(res))
+ return PTR_ERR(res);
+
+ pd->va = IOMEM(res->start);
+
+ r = __prci_register_clocks(dev, pd, desc);
+ if (r) {
+ dev_err(dev, "could not register clocks: %d\n", r);
+ return r;
+ }
+
+ dev_dbg(dev, "SiFive PRCI probed\n");
+
+ return 0;
+}
+
+static const struct of_device_id sifive_prci_of_match[] = {
+ {.compatible = "sifive,fu540-c000-prci", .data = &prci_clk_fu540},
+ {.compatible = "sifive,fu740-c000-prci", .data = &prci_clk_fu740},
+ {}
+};
+MODULE_DEVICE_TABLE(of, sifive_prci_of_match);
+
+static struct driver sifive_prci_driver = {
+ .name = "sifive-clk-prci",
+ .of_compatible = sifive_prci_of_match,
+ .probe = sifive_prci_probe,
+};
+core_platform_driver(sifive_prci_driver);
diff --git a/drivers/clk/sifive/sifive-prci.h b/drivers/clk/sifive/sifive-prci.h
new file mode 100644
index 0000000000..5ed6c0884b
--- /dev/null
+++ b/drivers/clk/sifive/sifive-prci.h
@@ -0,0 +1,298 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2018-2019 SiFive, Inc.
+ * Wesley Terpstra
+ * Paul Walmsley
+ * Zong Li
+ */
+
+#ifndef __SIFIVE_CLK_SIFIVE_PRCI_H
+#define __SIFIVE_CLK_SIFIVE_PRCI_H
+
+#include <linux/clk/analogbits-wrpll-cln28hpc.h>
+#include <linux/clk.h>
+
+/*
+ * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver expects:
+ * hfclk and rtcclk
+ */
+#define EXPECTED_CLK_PARENT_COUNT 2
+
+/*
+ * Register offsets and bitmasks
+ */
+
+/* COREPLLCFG0 */
+#define PRCI_COREPLLCFG0_OFFSET 0x4
+#define PRCI_COREPLLCFG0_DIVR_SHIFT 0
+#define PRCI_COREPLLCFG0_DIVR_MASK (0x3f << PRCI_COREPLLCFG0_DIVR_SHIFT)
+#define PRCI_COREPLLCFG0_DIVF_SHIFT 6
+#define PRCI_COREPLLCFG0_DIVF_MASK (0x1ff << PRCI_COREPLLCFG0_DIVF_SHIFT)
+#define PRCI_COREPLLCFG0_DIVQ_SHIFT 15
+#define PRCI_COREPLLCFG0_DIVQ_MASK (0x7 << PRCI_COREPLLCFG0_DIVQ_SHIFT)
+#define PRCI_COREPLLCFG0_RANGE_SHIFT 18
+#define PRCI_COREPLLCFG0_RANGE_MASK (0x7 << PRCI_COREPLLCFG0_RANGE_SHIFT)
+#define PRCI_COREPLLCFG0_BYPASS_SHIFT 24
+#define PRCI_COREPLLCFG0_BYPASS_MASK (0x1 << PRCI_COREPLLCFG0_BYPASS_SHIFT)
+#define PRCI_COREPLLCFG0_FSE_SHIFT 25
+#define PRCI_COREPLLCFG0_FSE_MASK (0x1 << PRCI_COREPLLCFG0_FSE_SHIFT)
+#define PRCI_COREPLLCFG0_LOCK_SHIFT 31
+#define PRCI_COREPLLCFG0_LOCK_MASK (0x1 << PRCI_COREPLLCFG0_LOCK_SHIFT)
+
+/* COREPLLCFG1 */
+#define PRCI_COREPLLCFG1_OFFSET 0x8
+#define PRCI_COREPLLCFG1_CKE_SHIFT 31
+#define PRCI_COREPLLCFG1_CKE_MASK (0x1 << PRCI_COREPLLCFG1_CKE_SHIFT)
+
+/* DDRPLLCFG0 */
+#define PRCI_DDRPLLCFG0_OFFSET 0xc
+#define PRCI_DDRPLLCFG0_DIVR_SHIFT 0
+#define PRCI_DDRPLLCFG0_DIVR_MASK (0x3f << PRCI_DDRPLLCFG0_DIVR_SHIFT)
+#define PRCI_DDRPLLCFG0_DIVF_SHIFT 6
+#define PRCI_DDRPLLCFG0_DIVF_MASK (0x1ff << PRCI_DDRPLLCFG0_DIVF_SHIFT)
+#define PRCI_DDRPLLCFG0_DIVQ_SHIFT 15
+#define PRCI_DDRPLLCFG0_DIVQ_MASK (0x7 << PRCI_DDRPLLCFG0_DIVQ_SHIFT)
+#define PRCI_DDRPLLCFG0_RANGE_SHIFT 18
+#define PRCI_DDRPLLCFG0_RANGE_MASK (0x7 << PRCI_DDRPLLCFG0_RANGE_SHIFT)
+#define PRCI_DDRPLLCFG0_BYPASS_SHIFT 24
+#define PRCI_DDRPLLCFG0_BYPASS_MASK (0x1 << PRCI_DDRPLLCFG0_BYPASS_SHIFT)
+#define PRCI_DDRPLLCFG0_FSE_SHIFT 25
+#define PRCI_DDRPLLCFG0_FSE_MASK (0x1 << PRCI_DDRPLLCFG0_FSE_SHIFT)
+#define PRCI_DDRPLLCFG0_LOCK_SHIFT 31
+#define PRCI_DDRPLLCFG0_LOCK_MASK (0x1 << PRCI_DDRPLLCFG0_LOCK_SHIFT)
+
+/* DDRPLLCFG1 */
+#define PRCI_DDRPLLCFG1_OFFSET 0x10
+#define PRCI_DDRPLLCFG1_CKE_SHIFT 31
+#define PRCI_DDRPLLCFG1_CKE_MASK (0x1 << PRCI_DDRPLLCFG1_CKE_SHIFT)
+
+/* GEMGXLPLLCFG0 */
+#define PRCI_GEMGXLPLLCFG0_OFFSET 0x1c
+#define PRCI_GEMGXLPLLCFG0_DIVR_SHIFT 0
+#define PRCI_GEMGXLPLLCFG0_DIVR_MASK (0x3f << PRCI_GEMGXLPLLCFG0_DIVR_SHIFT)
+#define PRCI_GEMGXLPLLCFG0_DIVF_SHIFT 6
+#define PRCI_GEMGXLPLLCFG0_DIVF_MASK (0x1ff << PRCI_GEMGXLPLLCFG0_DIVF_SHIFT)
+#define PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT 15
+#define PRCI_GEMGXLPLLCFG0_DIVQ_MASK (0x7 << PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT)
+#define PRCI_GEMGXLPLLCFG0_RANGE_SHIFT 18
+#define PRCI_GEMGXLPLLCFG0_RANGE_MASK (0x7 << PRCI_GEMGXLPLLCFG0_RANGE_SHIFT)
+#define PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT 24
+#define PRCI_GEMGXLPLLCFG0_BYPASS_MASK (0x1 << PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT)
+#define PRCI_GEMGXLPLLCFG0_FSE_SHIFT 25
+#define PRCI_GEMGXLPLLCFG0_FSE_MASK (0x1 << PRCI_GEMGXLPLLCFG0_FSE_SHIFT)
+#define PRCI_GEMGXLPLLCFG0_LOCK_SHIFT 31
+#define PRCI_GEMGXLPLLCFG0_LOCK_MASK (0x1 << PRCI_GEMGXLPLLCFG0_LOCK_SHIFT)
+
+/* GEMGXLPLLCFG1 */
+#define PRCI_GEMGXLPLLCFG1_OFFSET 0x20
+#define PRCI_GEMGXLPLLCFG1_CKE_SHIFT 31
+#define PRCI_GEMGXLPLLCFG1_CKE_MASK (0x1 << PRCI_GEMGXLPLLCFG1_CKE_SHIFT)
+
+/* CORECLKSEL */
+#define PRCI_CORECLKSEL_OFFSET 0x24
+#define PRCI_CORECLKSEL_CORECLKSEL_SHIFT 0
+#define PRCI_CORECLKSEL_CORECLKSEL_MASK \
+ (0x1 << PRCI_CORECLKSEL_CORECLKSEL_SHIFT)
+
+/* DEVICESRESETREG */
+#define PRCI_DEVICESRESETREG_OFFSET 0x28
+#define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT 0
+#define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK \
+ (0x1 << PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT)
+#define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT 1
+#define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK \
+ (0x1 << PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT)
+#define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT 2
+#define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK \
+ (0x1 << PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT)
+#define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT 3
+#define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK \
+ (0x1 << PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT)
+#define PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT 5
+#define PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK \
+ (0x1 << PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT)
+#define PRCI_DEVICESRESETREG_CHIPLINK_RST_N_SHIFT 6
+#define PRCI_DEVICESRESETREG_CHIPLINK_RST_N_MASK \
+ (0x1 << PRCI_DEVICESRESETREG_CHIPLINK_RST_N_SHIFT)
+
+/* CLKMUXSTATUSREG */
+#define PRCI_CLKMUXSTATUSREG_OFFSET 0x2c
+#define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT 1
+#define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \
+ (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
+
+/* CLTXPLLCFG0 */
+#define PRCI_CLTXPLLCFG0_OFFSET 0x30
+#define PRCI_CLTXPLLCFG0_DIVR_SHIFT 0
+#define PRCI_CLTXPLLCFG0_DIVR_MASK (0x3f << PRCI_CLTXPLLCFG0_DIVR_SHIFT)
+#define PRCI_CLTXPLLCFG0_DIVF_SHIFT 6
+#define PRCI_CLTXPLLCFG0_DIVF_MASK (0x1ff << PRCI_CLTXPLLCFG0_DIVF_SHIFT)
+#define PRCI_CLTXPLLCFG0_DIVQ_SHIFT 15
+#define PRCI_CLTXPLLCFG0_DIVQ_MASK (0x7 << PRCI_CLTXPLLCFG0_DIVQ_SHIFT)
+#define PRCI_CLTXPLLCFG0_RANGE_SHIFT 18
+#define PRCI_CLTXPLLCFG0_RANGE_MASK (0x7 << PRCI_CLTXPLLCFG0_RANGE_SHIFT)
+#define PRCI_CLTXPLLCFG0_BYPASS_SHIFT 24
+#define PRCI_CLTXPLLCFG0_BYPASS_MASK (0x1 << PRCI_CLTXPLLCFG0_BYPASS_SHIFT)
+#define PRCI_CLTXPLLCFG0_FSE_SHIFT 25
+#define PRCI_CLTXPLLCFG0_FSE_MASK (0x1 << PRCI_CLTXPLLCFG0_FSE_SHIFT)
+#define PRCI_CLTXPLLCFG0_LOCK_SHIFT 31
+#define PRCI_CLTXPLLCFG0_LOCK_MASK (0x1 << PRCI_CLTXPLLCFG0_LOCK_SHIFT)
+
+/* CLTXPLLCFG1 */
+#define PRCI_CLTXPLLCFG1_OFFSET 0x34
+#define PRCI_CLTXPLLCFG1_CKE_SHIFT 31
+#define PRCI_CLTXPLLCFG1_CKE_MASK (0x1 << PRCI_CLTXPLLCFG1_CKE_SHIFT)
+
+/* DVFSCOREPLLCFG0 */
+#define PRCI_DVFSCOREPLLCFG0_OFFSET 0x38
+
+/* DVFSCOREPLLCFG1 */
+#define PRCI_DVFSCOREPLLCFG1_OFFSET 0x3c
+#define PRCI_DVFSCOREPLLCFG1_CKE_SHIFT 31
+#define PRCI_DVFSCOREPLLCFG1_CKE_MASK (0x1 << PRCI_DVFSCOREPLLCFG1_CKE_SHIFT)
+
+/* COREPLLSEL */
+#define PRCI_COREPLLSEL_OFFSET 0x40
+#define PRCI_COREPLLSEL_COREPLLSEL_SHIFT 0
+#define PRCI_COREPLLSEL_COREPLLSEL_MASK \
+ (0x1 << PRCI_COREPLLSEL_COREPLLSEL_SHIFT)
+
+/* HFPCLKPLLCFG0 */
+#define PRCI_HFPCLKPLLCFG0_OFFSET 0x50
+#define PRCI_HFPCLKPLL_CFG0_DIVR_SHIFT 0
+#define PRCI_HFPCLKPLL_CFG0_DIVR_MASK \
+ (0x3f << PRCI_HFPCLKPLLCFG0_DIVR_SHIFT)
+#define PRCI_HFPCLKPLL_CFG0_DIVF_SHIFT 6
+#define PRCI_HFPCLKPLL_CFG0_DIVF_MASK \
+ (0x1ff << PRCI_HFPCLKPLLCFG0_DIVF_SHIFT)
+#define PRCI_HFPCLKPLL_CFG0_DIVQ_SHIFT 15
+#define PRCI_HFPCLKPLL_CFG0_DIVQ_MASK \
+ (0x7 << PRCI_HFPCLKPLLCFG0_DIVQ_SHIFT)
+#define PRCI_HFPCLKPLL_CFG0_RANGE_SHIFT 18
+#define PRCI_HFPCLKPLL_CFG0_RANGE_MASK \
+ (0x7 << PRCI_HFPCLKPLLCFG0_RANGE_SHIFT)
+#define PRCI_HFPCLKPLL_CFG0_BYPASS_SHIFT 24
+#define PRCI_HFPCLKPLL_CFG0_BYPASS_MASK \
+ (0x1 << PRCI_HFPCLKPLLCFG0_BYPASS_SHIFT)
+#define PRCI_HFPCLKPLL_CFG0_FSE_SHIFT 25
+#define PRCI_HFPCLKPLL_CFG0_FSE_MASK \
+ (0x1 << PRCI_HFPCLKPLLCFG0_FSE_SHIFT)
+#define PRCI_HFPCLKPLL_CFG0_LOCK_SHIFT 31
+#define PRCI_HFPCLKPLL_CFG0_LOCK_MASK \
+ (0x1 << PRCI_HFPCLKPLLCFG0_LOCK_SHIFT)
+
+/* HFPCLKPLLCFG1 */
+#define PRCI_HFPCLKPLLCFG1_OFFSET 0x54
+#define PRCI_HFPCLKPLLCFG1_CKE_SHIFT 31
+#define PRCI_HFPCLKPLLCFG1_CKE_MASK \
+ (0x1 << PRCI_HFPCLKPLLCFG1_CKE_SHIFT)
+
+/* HFPCLKPLLSEL */
+#define PRCI_HFPCLKPLLSEL_OFFSET 0x58
+#define PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_SHIFT 0
+#define PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_MASK \
+ (0x1 << PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_SHIFT)
+
+/* HFPCLKPLLDIV */
+#define PRCI_HFPCLKPLLDIV_OFFSET 0x5c
+
+/* PRCIPLL */
+#define PRCI_PRCIPLL_OFFSET 0xe0
+
+/* PROCMONCFG */
+#define PRCI_PROCMONCFG_OFFSET 0xf0
+
+/*
+ * Private structures
+ */
+
+/**
+ * struct __prci_data - per-device-instance data
+ * @va: base virtual address of the PRCI IP block
+ * @hw_clks: encapsulates struct clk_hw records
+ *
+ * PRCI per-device instance data
+ */
+struct __prci_data {
+ void __iomem *va;
+ struct clk_onecell_data hw_clks;
+};
+
+/**
+ * struct __prci_wrpll_data - WRPLL configuration and integration data
+ * @c: WRPLL current configuration record
+ * @enable_bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL)
+ * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL)
+ * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address
+ * @cfg1_offs: WRPLL CFG1 register offset (in bytes) from the PRCI base address
+ *
+ * @enable_bypass and @disable_bypass are used for WRPLL instances
+ * that contain a separate external glitchless clock mux downstream
+ * from the PLL. The WRPLL internal bypass mux is not glitchless.
+ */
+struct __prci_wrpll_data {
+ struct wrpll_cfg c;
+ void (*enable_bypass)(struct __prci_data *pd);
+ void (*disable_bypass)(struct __prci_data *pd);
+ u8 cfg0_offs;
+ u8 cfg1_offs;
+};
+
+/**
+ * struct __prci_clock - describes a clock device managed by PRCI
+ * @name: user-readable clock name string - should match the manual
+ * @parent_name: parent name for this clock
+ * @ops: struct clk_ops for the Linux clock framework to use for control
+ * @hw: Linux-private clock data
+ * @pwd: WRPLL-specific data, associated with this clock (if not NULL)
+ * @pd: PRCI-specific data associated with this clock (if not NULL)
+ *
+ * PRCI clock data. Used by the PRCI driver to register PRCI-provided
+ * clocks to the Linux clock infrastructure.
+ */
+struct __prci_clock {
+ const char *name;
+ const char *parent_name;
+ const struct clk_ops *ops;
+ struct clk_hw hw;
+ struct __prci_wrpll_data *pwd;
+ struct __prci_data *pd;
+};
+
+#define clk_hw_to_prci_clock(pwd) container_of(pwd, struct __prci_clock, hw)
+
+/*
+ * struct prci_clk_desc - describes the information of clocks of each SoCs
+ * @clks: point to a array of __prci_clock
+ * @num_clks: the number of element of clks
+ */
+struct prci_clk_desc {
+ struct __prci_clock *clks;
+ size_t num_clks;
+};
+
+/* Core clock mux control */
+void sifive_prci_coreclksel_use_hfclk(struct __prci_data *pd);
+void sifive_prci_coreclksel_use_corepll(struct __prci_data *pd);
+void sifive_prci_coreclksel_use_final_corepll(struct __prci_data *pd);
+void sifive_prci_corepllsel_use_dvfscorepll(struct __prci_data *pd);
+void sifive_prci_corepllsel_use_corepll(struct __prci_data *pd);
+void sifive_prci_hfpclkpllsel_use_hfclk(struct __prci_data *pd);
+void sifive_prci_hfpclkpllsel_use_hfpclkpll(struct __prci_data *pd);
+
+/* Linux clock framework integration */
+long sifive_prci_wrpll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate);
+int sifive_prci_wrpll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate);
+int sifive_clk_is_enabled(struct clk_hw *hw);
+int sifive_prci_clock_enable(struct clk_hw *hw);
+void sifive_prci_clock_disable(struct clk_hw *hw);
+unsigned long sifive_prci_wrpll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate);
+unsigned long sifive_prci_tlclksel_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate);
+unsigned long sifive_prci_hfpclkplldiv_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate);
+
+#endif /* __SIFIVE_CLK_SIFIVE_PRCI_H */
diff --git a/drivers/clk/socfpga/clk-gate-a10.c b/drivers/clk/socfpga/clk-gate-a10.c
index 401eb20d24..b66fbcdb8c 100644
--- a/drivers/clk/socfpga/clk-gate-a10.c
+++ b/drivers/clk/socfpga/clk-gate-a10.c
@@ -6,23 +6,23 @@
#include <common.h>
#include <io.h>
#include <malloc.h>
-#include <regmap.h>
+#include <linux/regmap.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
-#include <mach/arria10-regs.h>
-#include <mach/arria10-system-manager.h>
+#include <mach/socfpga/arria10-regs.h>
+#include <mach/socfpga/arria10-system-manager.h>
#include "clk.h"
-#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, clk)
+#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw)
/* SDMMC Group for System Manager defines */
#define SYSMGR_SDMMCGRP_CTRL_OFFSET 0x28
-static unsigned long socfpga_gate_clk_recalc_rate(struct clk *clk,
+static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(clk);
+ struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hw);
u32 div = 1, val;
if (socfpgaclk->fixed_div)
@@ -36,9 +36,9 @@ static unsigned long socfpga_gate_clk_recalc_rate(struct clk *clk,
return parent_rate / div;
}
-static int socfpga_clk_prepare(struct clk *clk)
+static int socfpga_clk_prepare(struct clk_hw *hw)
{
- struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(clk);
+ struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hw);
int i;
u32 hs_timing;
u32 clk_phase[2];
@@ -82,12 +82,12 @@ static int socfpga_clk_prepare(struct clk *clk)
return 0;
}
-static int clk_socfpga_enable(struct clk *clk)
+static int clk_socfpga_enable(struct clk_hw *hw)
{
- struct socfpga_gate_clk *socfpga_clk = to_socfpga_gate_clk(clk);
+ struct socfpga_gate_clk *socfpga_clk = to_socfpga_gate_clk(hw);
u32 val;
- socfpga_clk_prepare(clk);
+ socfpga_clk_prepare(hw);
val = readl(socfpga_clk->reg);
val |= 1 << socfpga_clk->bit_idx;
@@ -96,9 +96,9 @@ static int clk_socfpga_enable(struct clk *clk)
return 0;
}
-static void clk_socfpga_disable(struct clk *clk)
+static void clk_socfpga_disable(struct clk_hw *hw)
{
- struct socfpga_gate_clk *socfpga_clk = to_socfpga_gate_clk(clk);
+ struct socfpga_gate_clk *socfpga_clk = to_socfpga_gate_clk(hw);
u32 val;
val = readl(socfpga_clk->reg);
@@ -159,8 +159,8 @@ static struct clk *__socfpga_gate_init(struct device_node *node,
of_property_read_string(node, "clock-output-names", &clk_name);
- socfpga_clk->clk.name = xstrdup(clk_name);
- socfpga_clk->clk.ops = ops;
+ socfpga_clk->hw.clk.name = xstrdup(clk_name);
+ socfpga_clk->hw.clk.ops = ops;
for (i = 0; i < SOCFPGA_MAX_PARENTS; i++) {
socfpga_clk->parent_names[i] = of_clk_get_parent_name(node, i);
@@ -168,16 +168,16 @@ static struct clk *__socfpga_gate_init(struct device_node *node,
break;
}
- socfpga_clk->clk.num_parents = i;
- socfpga_clk->clk.parent_names = socfpga_clk->parent_names;
+ socfpga_clk->hw.clk.num_parents = i;
+ socfpga_clk->hw.clk.parent_names = socfpga_clk->parent_names;
- rc = clk_register(&socfpga_clk->clk);
+ rc = bclk_register(&socfpga_clk->hw.clk);
if (rc) {
free(socfpga_clk);
return ERR_PTR(rc);
}
- return &socfpga_clk->clk;
+ return &socfpga_clk->hw.clk;
}
struct clk *socfpga_a10_gate_init(struct device_node *node)
diff --git a/drivers/clk/socfpga/clk-periph-a10.c b/drivers/clk/socfpga/clk-periph-a10.c
index 4ef00052e4..f9cf40b0aa 100644
--- a/drivers/clk/socfpga/clk-periph-a10.c
+++ b/drivers/clk/socfpga/clk-periph-a10.c
@@ -17,12 +17,12 @@
#define SOCFPGA_MPU_FREE_CLK "mpu_free_clk"
#define SOCFPGA_NOC_FREE_CLK "noc_free_clk"
#define SOCFPGA_SDMMC_FREE_CLK "sdmmc_free_clk"
-#define to_socfpga_periph_clk(p) container_of(p, struct socfpga_periph_clk, clk)
+#define to_socfpga_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw)
-static unsigned long clk_periclk_recalc_rate(struct clk *clk,
+static unsigned long clk_periclk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(clk);
+ struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hw);
u32 div;
if (socfpgaclk->fixed_div) {
@@ -38,15 +38,15 @@ static unsigned long clk_periclk_recalc_rate(struct clk *clk,
return parent_rate / div;
}
-static int clk_periclk_get_parent(struct clk *clk)
+static int clk_periclk_get_parent(struct clk_hw *hw)
{
- struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(clk);
+ struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hw);
u32 clk_src;
clk_src = readl(socfpgaclk->reg);
- if (streq(clk->name, SOCFPGA_MPU_FREE_CLK) ||
- streq(clk->name, SOCFPGA_NOC_FREE_CLK) ||
- streq(clk->name, SOCFPGA_SDMMC_FREE_CLK))
+ if (streq(clk_hw_get_name(hw), SOCFPGA_MPU_FREE_CLK) ||
+ streq(clk_hw_get_name(hw), SOCFPGA_NOC_FREE_CLK) ||
+ streq(clk_hw_get_name(hw), SOCFPGA_SDMMC_FREE_CLK))
return (clk_src >> CLK_MGR_FREE_SHIFT) &
CLK_MGR_FREE_MASK;
else
@@ -98,19 +98,19 @@ static struct clk *__socfpga_periph_init(struct device_node *node,
break;
}
- periph_clk->clk.num_parents = i;
- periph_clk->clk.parent_names = periph_clk->parent_names;
+ periph_clk->hw.clk.num_parents = i;
+ periph_clk->hw.clk.parent_names = periph_clk->parent_names;
- periph_clk->clk.name = xstrdup(clk_name);
- periph_clk->clk.ops = ops;
+ periph_clk->hw.clk.name = xstrdup(clk_name);
+ periph_clk->hw.clk.ops = ops;
- rc = clk_register(&periph_clk->clk);
+ rc = bclk_register(&periph_clk->hw.clk);
if (rc) {
free(periph_clk);
return ERR_PTR(rc);
}
- return &periph_clk->clk;
+ return &periph_clk->hw.clk;
}
struct clk *socfpga_a10_periph_init(struct device_node *node)
diff --git a/drivers/clk/socfpga/clk-pll-a10.c b/drivers/clk/socfpga/clk-pll-a10.c
index 12d6ef6fc3..2e58a2eb5d 100644
--- a/drivers/clk/socfpga/clk-pll-a10.c
+++ b/drivers/clk/socfpga/clk-pll-a10.c
@@ -7,7 +7,7 @@
#include <malloc.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include "clk.h"
@@ -28,12 +28,12 @@
#define SOCFPGA_MAIN_PLL_CLK "main_pll"
#define SOCFPGA_PERIP_PLL_CLK "periph_pll"
-#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, clk)
+#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw)
-static unsigned long clk_pll_recalc_rate(struct clk *clk,
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct socfpga_pll *socfpgaclk = to_socfpga_clk(clk);
+ struct socfpga_pll *socfpgaclk = to_socfpga_clk(hw);
unsigned long divf, divq, reg;
unsigned long long vco_freq;
@@ -46,9 +46,9 @@ static unsigned long clk_pll_recalc_rate(struct clk *clk,
return (unsigned long)vco_freq;
}
-static int clk_pll_get_parent(struct clk *clk)
+static int clk_pll_get_parent(struct clk_hw *hw)
{
- struct socfpga_pll *socfpgaclk = to_socfpga_clk(clk);
+ struct socfpga_pll *socfpgaclk = to_socfpga_clk(hw);
u32 pll_src;
pll_src = readl(socfpgaclk->reg);
@@ -57,9 +57,9 @@ static int clk_pll_get_parent(struct clk *clk)
CLK_MGR_PLL_CLK_SRC_MASK;
}
-static int clk_socfpga_enable(struct clk *clk)
+static int clk_socfpga_enable(struct clk_hw *hw)
{
- struct socfpga_pll *socfpga_clk = to_socfpga_clk(clk);
+ struct socfpga_pll *socfpga_clk = to_socfpga_clk(hw);
u32 val;
val = readl(socfpga_clk->reg);
@@ -69,9 +69,9 @@ static int clk_socfpga_enable(struct clk *clk)
return 0;
}
-static void clk_socfpga_disable(struct clk *clk)
+static void clk_socfpga_disable(struct clk_hw *hw)
{
- struct socfpga_pll *socfpga_clk = to_socfpga_clk(clk);
+ struct socfpga_pll *socfpga_clk = to_socfpga_clk(hw);
u32 val;
val = readl(socfpga_clk->reg);
@@ -101,8 +101,8 @@ static struct clk *__socfpga_pll_init(struct device_node *node,
of_property_read_string(node, "clock-output-names", &clk_name);
- pll_clk->clk.name = xstrdup(clk_name);
- pll_clk->clk.ops = ops;
+ pll_clk->hw.clk.name = xstrdup(clk_name);
+ pll_clk->hw.clk.ops = ops;
for (i = 0; i < SOCFPGA_MAX_PARENTS; i++) {
pll_clk->parent_names[i] = of_clk_get_parent_name(node, i);
@@ -111,19 +111,19 @@ static struct clk *__socfpga_pll_init(struct device_node *node,
}
pll_clk->bit_idx = SOCFPGA_PLL_EXT_ENA;
- pll_clk->clk.num_parents = i;
- pll_clk->clk.parent_names = pll_clk->parent_names;
+ pll_clk->hw.clk.num_parents = i;
+ pll_clk->hw.clk.parent_names = pll_clk->parent_names;
clk_pll_ops.enable = clk_socfpga_enable;
clk_pll_ops.disable = clk_socfpga_disable;
- rc = clk_register(&pll_clk->clk);
+ rc = bclk_register(&pll_clk->hw.clk);
if (rc) {
free(pll_clk);
return NULL;
}
- return &pll_clk->clk;
+ return &pll_clk->hw.clk;
}
struct clk *socfpga_a10_pll_init(struct device_node *node)
diff --git a/drivers/clk/socfpga/clk.c b/drivers/clk/socfpga/clk.c
index 1d34b15caf..35de843291 100644
--- a/drivers/clk/socfpga/clk.c
+++ b/drivers/clk/socfpga/clk.c
@@ -50,15 +50,15 @@
void __iomem *clk_mgr_base_addr;
struct clk_pll {
- struct clk clk;
+ struct clk_hw hw;
const char *parent;
unsigned regofs;
};
-static unsigned long clk_pll_recalc_rate(struct clk *clk,
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_pll *pll = container_of(clk, struct clk_pll, clk);
+ struct clk_pll *pll = container_of(hw, struct clk_pll, hw);
unsigned long divf, divq, vco_freq, reg;
unsigned long bypass;
@@ -90,24 +90,24 @@ static struct clk *socfpga_pll_clk(struct device_node *node)
if (!pll->parent)
return ERR_PTR(-EINVAL);
- pll->clk.parent_names = &pll->parent;
- pll->clk.num_parents = 1;
- pll->clk.name = xstrdup(node->name);
- pll->clk.ops = &clk_pll_ops;
+ pll->hw.clk.parent_names = &pll->parent;
+ pll->hw.clk.num_parents = 1;
+ pll->hw.clk.name = xstrdup(node->name);
+ pll->hw.clk.ops = &clk_pll_ops;
of_property_read_u32(node, "reg", &pll->regofs);
- ret = clk_register(&pll->clk);
+ ret = bclk_register(&pll->hw.clk);
if (ret) {
free(pll);
return ERR_PTR(ret);
}
- return &pll->clk;
+ return &pll->hw.clk;
}
struct clk_periph {
- struct clk clk;
+ struct clk_hw hw;
const char *parent;
unsigned regofs;
unsigned int fixed_div;
@@ -116,10 +116,10 @@ struct clk_periph {
unsigned int shift;
};
-static unsigned long clk_periph_recalc_rate(struct clk *clk,
+static unsigned long clk_periph_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_periph *periph = container_of(clk, struct clk_periph, clk);
+ struct clk_periph *periph = container_of(hw, struct clk_periph, hw);
u32 div, val;
if (periph->fixed_div) {
@@ -152,10 +152,10 @@ static struct clk *socfpga_periph_clk(struct device_node *node)
if (!periph->parent)
return ERR_PTR(-EINVAL);
- periph->clk.parent_names = &periph->parent;
- periph->clk.num_parents = 1;
- periph->clk.name = xstrdup(node->name);
- periph->clk.ops = &clk_periph_ops;
+ periph->hw.clk.parent_names = &periph->parent;
+ periph->hw.clk.num_parents = 1;
+ periph->hw.clk.name = xstrdup(node->name);
+ periph->hw.clk.ops = &clk_periph_ops;
ret = of_property_read_u32_array(node, "div-reg", div_reg, 3);
if (!ret) {
@@ -169,17 +169,17 @@ static struct clk *socfpga_periph_clk(struct device_node *node)
of_property_read_u32(node, "reg", &periph->regofs);
of_property_read_u32(node, "fixed-divider", &periph->fixed_div);
- ret = clk_register(&periph->clk);
+ ret = bclk_register(&periph->hw.clk);
if (ret) {
free(periph);
return ERR_PTR(ret);
}
- return &periph->clk;
+ return &periph->hw.clk;
}
struct clk_socfpga {
- struct clk clk;
+ struct clk_hw hw;
const char *parent;
void __iomem *reg;
void __iomem *div_reg;
@@ -190,9 +190,9 @@ struct clk_socfpga {
const char *parent_names[SOCFGPA_MAX_PARENTS];
};
-static int clk_socfpga_enable(struct clk *clk)
+static int clk_socfpga_enable(struct clk_hw *hw)
{
- struct clk_socfpga *cs = container_of(clk, struct clk_socfpga, clk);
+ struct clk_socfpga *cs = container_of(hw, struct clk_socfpga, hw);
u32 val;
val = readl(cs->reg);
@@ -202,9 +202,9 @@ static int clk_socfpga_enable(struct clk *clk)
return 0;
}
-static void clk_socfpga_disable(struct clk *clk)
+static void clk_socfpga_disable(struct clk_hw *hw)
{
- struct clk_socfpga *cs = container_of(clk, struct clk_socfpga, clk);
+ struct clk_socfpga *cs = container_of(hw, struct clk_socfpga, hw);
u32 val;
val = readl(cs->reg);
@@ -212,9 +212,9 @@ static void clk_socfpga_disable(struct clk *clk)
writel(val, cs->reg);
}
-static int clk_socfpga_is_enabled(struct clk *clk)
+static int clk_socfpga_is_enabled(struct clk_hw *hw)
{
- struct clk_socfpga *cs = container_of(clk, struct clk_socfpga, clk);
+ struct clk_socfpga *cs = container_of(hw, struct clk_socfpga, hw);
u32 val;
val = readl(cs->reg);
@@ -225,10 +225,10 @@ static int clk_socfpga_is_enabled(struct clk *clk)
return 0;
}
-static unsigned long clk_socfpga_recalc_rate(struct clk *clk,
+static unsigned long clk_socfpga_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct clk_socfpga *cs = container_of(clk, struct clk_socfpga, clk);
+ struct clk_socfpga *cs = container_of(hw, struct clk_socfpga, hw);
u32 div = 1, val;
if (cs->fixed_div) {
@@ -236,7 +236,7 @@ static unsigned long clk_socfpga_recalc_rate(struct clk *clk,
} else if (cs->div_reg) {
val = readl(cs->div_reg) >> cs->shift;
val &= div_mask(cs->width);
- if (streq(clk->name, SOCFPGA_DB_CLK))
+ if (streq(clk_hw_get_name(hw), SOCFPGA_DB_CLK))
div = val + 1;
else
div = (1 << val);
@@ -245,8 +245,9 @@ static unsigned long clk_socfpga_recalc_rate(struct clk *clk,
return parent_rate / div;
}
-static int clk_socfpga_get_parent(struct clk *clk)
+static int clk_socfpga_get_parent(struct clk_hw *hw)
{
+ struct clk *clk = clk_hw_to_clk(hw);
u32 perpll_src;
u32 l4_src;
@@ -270,8 +271,9 @@ static int clk_socfpga_get_parent(struct clk *clk)
return (perpll_src >> 4) & 3;
}
-static int clk_socfpga_set_parent(struct clk *clk, u8 parent)
+static int clk_socfpga_set_parent(struct clk_hw *hw, u8 parent)
{
+ struct clk *clk = clk_hw_to_clk(hw);
u32 src_reg;
if (streq(clk->name, SOCFPGA_L4_MP_CLK)) {
@@ -351,21 +353,22 @@ static struct clk *socfpga_gate_clk(struct device_node *node)
break;
}
- cs->clk.parent_names = cs->parent_names;
- cs->clk.num_parents = i;
- cs->clk.name = xstrdup(node->name);
- cs->clk.ops = &clk_socfpga_ops;
+ cs->hw.clk.parent_names = cs->parent_names;
+ cs->hw.clk.num_parents = i;
+ cs->hw.clk.name = xstrdup(node->name);
+ cs->hw.clk.ops = &clk_socfpga_ops;
- ret = clk_register(&cs->clk);
+ ret = bclk_register(&cs->hw.clk);
if (ret) {
free(cs);
return ERR_PTR(ret);
}
- return &cs->clk;
+ return &cs->hw.clk;
}
-static void socfpga_register_clocks(struct device_d *dev, struct device_node *node)
+static void socfpga_register_clocks(struct device *dev,
+ struct device_node *node)
{
struct device_node *child;
struct clk *clk;
@@ -392,7 +395,7 @@ static void socfpga_register_clocks(struct device_d *dev, struct device_node *no
of_clk_add_provider(node, of_clk_src_simple_get, clk);
}
-static int socfpga_ccm_probe(struct device_d *dev)
+static int socfpga_ccm_probe(struct device *dev)
{
struct resource *iores;
void __iomem *regs;
@@ -405,7 +408,7 @@ static int socfpga_ccm_probe(struct device_d *dev)
clk_mgr_base_addr = regs;
- clknode = of_get_child_by_name(dev->device_node, "clocks");
+ clknode = of_get_child_by_name(dev->of_node, "clocks");
if (!clknode)
return -EINVAL;
@@ -421,15 +424,12 @@ static __maybe_unused struct of_device_id socfpga_ccm_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, socfpga_ccm_dt_ids);
-static struct driver_d socfpga_ccm_driver = {
+static struct driver socfpga_ccm_driver = {
.probe = socfpga_ccm_probe,
.name = "socfpga-ccm",
.of_compatible = DRV_OF_COMPAT(socfpga_ccm_dt_ids),
};
-static int socfpga_ccm_init(void)
-{
- return platform_driver_register(&socfpga_ccm_driver);
-}
-core_initcall(socfpga_ccm_init);
+core_platform_driver(socfpga_ccm_driver);
diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h
index 9d291f7243..402f714436 100644
--- a/drivers/clk/socfpga/clk.h
+++ b/drivers/clk/socfpga/clk.h
@@ -47,14 +47,14 @@ static inline struct clk *socfpga_a10_gate_init(struct device_node *node)
#endif
struct socfpga_pll {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *reg;
u32 bit_idx;
const char *parent_names[SOCFPGA_MAX_PARENTS];
};
struct socfpga_gate_clk {
- struct clk clk;
+ struct clk_hw hw;
char *parent_name;
u32 fixed_div;
void __iomem *div_reg;
@@ -68,7 +68,7 @@ struct socfpga_gate_clk {
};
struct socfpga_periph_clk {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *reg;
char *parent_name;
u32 fixed_div;
diff --git a/drivers/clk/starfive/Makefile b/drivers/clk/starfive/Makefile
new file mode 100644
index 0000000000..84abc31ca3
--- /dev/null
+++ b/drivers/clk/starfive/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_SOC_STARFIVE_JH71XX) += jh7100-clkgen.o
diff --git a/drivers/clk/starfive/clk.h b/drivers/clk/starfive/clk.h
new file mode 100644
index 0000000000..6a9993ee95
--- /dev/null
+++ b/drivers/clk/starfive/clk.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright 2021 Ahmad Fatoum, Pengutronix
+ */
+
+#ifndef STARFIVE_CLK_H_
+#define STARFIVE_CLK_H_
+
+#include <linux/clk.h>
+
+#define STARFIVE_CLK_ENABLE_SHIFT 31
+#define STARFIVE_CLK_INVERT_SHIFT 30
+#define STARFIVE_CLK_MUX_SHIFT 24
+
+static inline struct clk *starfive_clk_underspecifid(const char *name, const char *parent)
+{
+ /*
+ * TODO With documentation available, all users of this functions can be
+ * migrated to one of the above or to a clk_fixed_factor with
+ * appropriate factor
+ */
+ return clk_fixed_factor(name, parent, 1, 1, 0);
+}
+
+static inline struct clk *starfive_clk_divider(const char *name, const char *parent,
+ void __iomem *reg, u8 width)
+{
+ return starfive_clk_underspecifid(name, parent);
+}
+
+static inline struct clk *starfive_clk_gate(const char *name, const char *parent,
+ void __iomem *reg)
+{
+ return clk_gate(name, parent, reg, STARFIVE_CLK_ENABLE_SHIFT, CLK_SET_RATE_PARENT, 0);
+}
+
+static inline struct clk *starfive_clk_divider_table(const char *name,
+ const char *parent, void __iomem *reg, u8 width,
+ const struct clk_div_table *table)
+{
+ return clk_divider_table(name, parent, CLK_SET_RATE_PARENT, reg, 0,
+ width, table, 0);
+}
+
+static inline struct clk *starfive_clk_gated_divider(const char *name,
+ const char *parent, void __iomem *reg, u8 width)
+{
+ /* TODO divider part */
+ return clk_gate(name, parent, reg, STARFIVE_CLK_ENABLE_SHIFT, CLK_SET_RATE_PARENT, 0);
+}
+
+static inline struct clk *starfive_clk_gate_dis(const char *name, const char *parent,
+ void __iomem *reg)
+{
+ return clk_gate_inverted(name, parent, reg, STARFIVE_CLK_INVERT_SHIFT, CLK_SET_RATE_PARENT);
+}
+
+static inline struct clk *starfive_clk_mux(const char *name, void __iomem *reg,
+ u8 width, const char * const *parents, u8 num_parents)
+{
+ return clk_mux(name, 0, reg, STARFIVE_CLK_MUX_SHIFT, width, parents, num_parents, 0);
+}
+
+#endif
diff --git a/drivers/clk/starfive/jh7100-clkgen.c b/drivers/clk/starfive/jh7100-clkgen.c
new file mode 100644
index 0000000000..c93b23d448
--- /dev/null
+++ b/drivers/clk/starfive/jh7100-clkgen.c
@@ -0,0 +1,364 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2021 Ahmad Fatoum, Pengutronix
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <linux/clk.h>
+#include <io.h>
+#include <of.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <dt-bindings/clock/starfive-jh7100.h>
+
+#include "clk.h"
+
+
+static const char *cpundbus_root_sels[4] = {
+ [0] = "osc_sys",
+ [1] = "pll0_out",
+ [2] = "pll1_out",
+ [3] = "pll2_out",
+};
+
+static const char *dla_root_sels[4] = {
+ [0] = "osc_sys",
+ [1] = "pll1_out",
+ [2] = "pll2_out",
+ [3] = "dummy",
+};
+
+static const char *dsp_root_sels[4] = {
+ [0] = "osc_sys",
+ [1] = "pll0_out",
+ [2] = "pll1_out",
+ [3] = "pll2_out",
+};
+
+static const char *gmacusb_root_sels[4] = {
+ [0] = "osc_sys",
+ [1] = "pll0_out",
+ [2] = "pll2_out",
+ [3] = "dummy",
+};
+
+static const char *perh0_root_sels[2] = {
+ [0] = "osc_sys",
+ [1] = "pll0_out",
+};
+
+static const char *perh1_root_sels[2] = {
+ [0] = "osc_sys",
+ [1] = "pll2_out",
+};
+
+static const char *vin_root_sels[4] = {
+ [0] = "osc_sys",
+ [1] = "pll1_out",
+ [2] = "pll2_out",
+ [3] = "dummy",
+};
+
+static const char *vout_root_sels[4] = {
+ [0] = "osc_aud",
+ [1] = "pll0_out",
+ [2] = "pll2_out",
+ [3] = "dummy",
+};
+
+static const char *cdechifi4_root_sels[4] = {
+ [0] = "osc_sys",
+ [1] = "pll1_out",
+ [2] = "pll2_out",
+ [3] = "dummy",
+};
+
+static const char *cdec_root_sels[4] = {
+ [0] = "osc_sys",
+ [1] = "pll0_out",
+ [2] = "pll1_out",
+ [3] = "dummy",
+};
+
+static const char *voutbus_root_sels[4] = {
+ [0] = "osc_aud",
+ [1] = "pll0_out",
+ [2] = "pll2_out",
+ [3] = "dummy",
+};
+
+static const char *pll2_refclk_sels[2] = {
+ [0] = "osc_sys",
+ [1] = "osc_aud",
+};
+
+static const char *ddrc0_sels[4] = {
+ [0] = "ddrosc_div2",
+ [1] = "ddrpll_div2",
+ [2] = "ddrpll_div4",
+ [3] = "ddrpll_div8",
+};
+
+static const char *ddrc1_sels[4] = {
+ [0] = "ddrosc_div2",
+ [1] = "ddrpll_div2",
+ [2] = "ddrpll_div4",
+ [3] = "ddrpll_div8",
+};
+
+static const char *nne_bus_sels[2] = {
+ [0] = "cpu_axi",
+ [1] = "nnebus_src1",
+};
+
+static const char *usbphy_25m_sels[2] = {
+ [0] = "osc_sys",
+ [1] = "usbphy_plldiv25m",
+};
+
+static const char *gmac_tx_sels[4] = {
+ [0] = "gmac_gtxclk",
+ [1] = "gmac_mii_txclk",
+ [2] = "gmac_rmii_txclk",
+ [3] = "dummy",
+};
+
+static const char *gmac_rx_pre_sels[2] = {
+ [0] = "gmac_gr_mii_rxclk",
+ [1] = "gmac_rmii_rxclk",
+};
+
+static struct clk *clks[CLK_END];
+
+/* assume osc_sys as direct parent for clocks of yet unknown lineage */
+#define UNKNOWN "osc_sys"
+
+static void starfive_clkgen_init(struct device_node *np, void __iomem *base)
+{
+ clks[CLK_OSC_SYS] = of_clk_get_by_name(np, "osc_sys");
+ clks[CLK_OSC_AUD] = of_clk_get_by_name(np, "osc_aud");
+ clks[CLK_PLL0_OUT] = starfive_clk_underspecifid("pll0_out", "osc_sys");
+ clks[CLK_PLL1_OUT] = starfive_clk_underspecifid("pll1_out", "osc_sys");
+ clks[CLK_PLL2_OUT] = starfive_clk_underspecifid("pll2_out", "pll2_refclk");
+ clks[CLK_CPUNDBUS_ROOT] = starfive_clk_mux("cpundbus_root", base + 0x0, 2, cpundbus_root_sels, ARRAY_SIZE(cpundbus_root_sels));
+ clks[CLK_DLA_ROOT] = starfive_clk_mux("dla_root", base + 0x4, 2, dla_root_sels, ARRAY_SIZE(dla_root_sels));
+ clks[CLK_DSP_ROOT] = starfive_clk_mux("dsp_root", base + 0x8, 2, dsp_root_sels, ARRAY_SIZE(dsp_root_sels));
+ clks[CLK_GMACUSB_ROOT] = starfive_clk_mux("gmacusb_root", base + 0xC, 2, gmacusb_root_sels, ARRAY_SIZE(gmacusb_root_sels));
+ clks[CLK_PERH0_ROOT] = starfive_clk_mux("perh0_root", base + 0x10, 1, perh0_root_sels, ARRAY_SIZE(perh0_root_sels));
+ clks[CLK_PERH1_ROOT] = starfive_clk_mux("perh1_root", base + 0x14, 1, perh1_root_sels, ARRAY_SIZE(perh1_root_sels));
+ clks[CLK_VIN_ROOT] = starfive_clk_mux("vin_root", base + 0x18, 2, vin_root_sels, ARRAY_SIZE(vin_root_sels));
+ clks[CLK_VOUT_ROOT] = starfive_clk_mux("vout_root", base + 0x1C, 2, vout_root_sels, ARRAY_SIZE(vout_root_sels));
+ clks[CLK_AUDIO_ROOT] = starfive_clk_gated_divider("audio_root", UNKNOWN, base + 0x20, 4);
+ clks[CLK_CDECHIFI4_ROOT] = starfive_clk_mux("cdechifi4_root", base + 0x24, 2, cdechifi4_root_sels, ARRAY_SIZE(cdechifi4_root_sels));
+ clks[CLK_CDEC_ROOT] = starfive_clk_mux("cdec_root", base + 0x28, 2, cdec_root_sels, ARRAY_SIZE(cdec_root_sels));
+ clks[CLK_VOUTBUS_ROOT] = starfive_clk_mux("voutbus_root", base + 0x2C, 2, voutbus_root_sels, ARRAY_SIZE(voutbus_root_sels));
+ clks[CLK_CPUNBUS_ROOT_DIV] = starfive_clk_divider("cpunbus_root_div", "cpunbus_root", base + 0x30, 2);
+ clks[CLK_DSP_ROOT_DIV] = starfive_clk_divider("dsp_root_div", "dsp_root", base + 0x34, 3);
+ clks[CLK_PERH0_SRC] = starfive_clk_divider("perh0_src", "perh0_root", base + 0x38, 3);
+ clks[CLK_PERH1_SRC] = starfive_clk_divider("perh1_src", "perh1_root", base + 0x3C, 3);
+ clks[CLK_PLL0_TESTOUT] = starfive_clk_gated_divider("pll0_testout", "pll0_out", base + 0x40, 5);
+ clks[CLK_PLL1_TESTOUT] = starfive_clk_gated_divider("pll1_testout", "pll1_out", base + 0x44, 5);
+ clks[CLK_PLL2_TESTOUT] = starfive_clk_gated_divider("pll2_testout", "pll2_out", base + 0x48, 5);
+ clks[CLK_PLL2_REF] = starfive_clk_mux("pll2_refclk", base + 0x4C, 1, pll2_refclk_sels, ARRAY_SIZE(pll2_refclk_sels));
+ clks[CLK_CPU_CORE] = starfive_clk_divider("cpu_core", UNKNOWN, base + 0x50, 4);
+ clks[CLK_CPU_AXI] = starfive_clk_divider("cpu_axi", UNKNOWN, base + 0x54, 4);
+ clks[CLK_AHB_BUS] = starfive_clk_divider("ahb_bus", UNKNOWN, base + 0x58, 4);
+ clks[CLK_APB1_BUS] = starfive_clk_divider("apb1_bus", UNKNOWN, base + 0x5C, 4);
+ clks[CLK_APB2_BUS] = starfive_clk_divider("apb2_bus", UNKNOWN, base + 0x60, 4);
+ clks[CLK_DOM3AHB_BUS] = starfive_clk_gate("dom3ahb_bus", UNKNOWN, base + 0x64);
+ clks[CLK_DOM7AHB_BUS] = starfive_clk_gate("dom7ahb_bus", UNKNOWN, base + 0x68);
+ clks[CLK_U74_CORE0] = starfive_clk_gate("u74_core0", UNKNOWN, base + 0x6C);
+ clks[CLK_U74_CORE1] = starfive_clk_gated_divider("u74_core1", "", base + 0x70, 4);
+ clks[CLK_U74_AXI] = starfive_clk_gate("u74_axi", UNKNOWN, base + 0x74);
+ clks[CLK_U74RTC_TOGGLE] = starfive_clk_gate("u74rtc_toggle", UNKNOWN, base + 0x78);
+ clks[CLK_SGDMA2P_AXI] = starfive_clk_gate("sgdma2p_axi", UNKNOWN, base + 0x7C);
+ clks[CLK_DMA2PNOC_AXI] = starfive_clk_gate("dma2pnoc_axi", UNKNOWN, base + 0x80);
+ clks[CLK_SGDMA2P_AHB] = starfive_clk_gate("sgdma2p_ahb", UNKNOWN, base + 0x84);
+ clks[CLK_DLA_BUS] = starfive_clk_divider("dla_bus", UNKNOWN, base + 0x88, 3);
+ clks[CLK_DLA_AXI] = starfive_clk_gate("dla_axi", UNKNOWN, base + 0x8C);
+ clks[CLK_DLANOC_AXI] = starfive_clk_gate("dlanoc_axi", UNKNOWN, base + 0x90);
+ clks[CLK_DLA_APB] = starfive_clk_gate("dla_apb", UNKNOWN, base + 0x94);
+ clks[CLK_VP6_CORE] = starfive_clk_gated_divider("vp6_core", UNKNOWN, base + 0x98, 3);
+ clks[CLK_VP6BUS_SRC] = starfive_clk_divider("vp6bus_src", UNKNOWN, base + 0x9C, 3);
+ clks[CLK_VP6_AXI] = starfive_clk_gated_divider("vp6_axi", UNKNOWN, base + 0xA0, 3);
+ clks[CLK_VCDECBUS_SRC] = starfive_clk_divider("vcdecbus_src", UNKNOWN, base + 0xA4, 3);
+ clks[CLK_VDEC_BUS] = starfive_clk_divider("vdec_bus", UNKNOWN, base + 0xA8, 4);
+ clks[CLK_VDEC_AXI] = starfive_clk_gate("vdec_axi", UNKNOWN, base + 0xAC);
+ clks[CLK_VDECBRG_MAIN] = starfive_clk_gate("vdecbrg_mainclk", UNKNOWN, base + 0xB0);
+ clks[CLK_VDEC_BCLK] = starfive_clk_gated_divider("vdec_bclk", UNKNOWN, base + 0xB4, 4);
+ clks[CLK_VDEC_CCLK] = starfive_clk_gated_divider("vdec_cclk", UNKNOWN, base + 0xB8, 4);
+ clks[CLK_VDEC_APB] = starfive_clk_gate("vdec_apb", UNKNOWN, base + 0xBC);
+ clks[CLK_JPEG_AXI] = starfive_clk_gated_divider("jpeg_axi", UNKNOWN, base + 0xC0, 4);
+ clks[CLK_JPEG_CCLK] = starfive_clk_gated_divider("jpeg_cclk", UNKNOWN, base + 0xC4, 4);
+ clks[CLK_JPEG_APB] = starfive_clk_gate("jpeg_apb", UNKNOWN, base + 0xC8);
+ clks[CLK_GC300_2X] = starfive_clk_gated_divider("gc300_2x", UNKNOWN, base + 0xCC, 4);
+ clks[CLK_GC300_AHB] = starfive_clk_gate("gc300_ahb", UNKNOWN, base + 0xD0);
+ clks[CLK_JPCGC300_AXIBUS] = starfive_clk_divider("jpcgc300_axibus", UNKNOWN, base + 0xD4, 4);
+ clks[CLK_GC300_AXI] = starfive_clk_gate("gc300_axi", UNKNOWN, base + 0xD8);
+ clks[CLK_JPCGC300_MAIN] = starfive_clk_gate("jpcgc300_mainclk", UNKNOWN, base + 0xDC);
+ clks[CLK_VENC_BUS] = starfive_clk_divider("venc_bus", UNKNOWN, base + 0xE0, 4);
+ clks[CLK_VENC_AXI] = starfive_clk_gate("venc_axi", UNKNOWN, base + 0xE4);
+ clks[CLK_VENCBRG_MAIN] = starfive_clk_gate("vencbrg_mainclk", UNKNOWN, base + 0xE8);
+ clks[CLK_VENC_BCLK] = starfive_clk_gated_divider("venc_bclk", UNKNOWN, base + 0xEC, 4);
+ clks[CLK_VENC_CCLK] = starfive_clk_gated_divider("venc_cclk", UNKNOWN, base + 0xF0, 4);
+ clks[CLK_VENC_APB] = starfive_clk_gate("venc_apb", UNKNOWN, base + 0xF4);
+ clks[CLK_DDRPLL_DIV2] = starfive_clk_gated_divider("ddrpll_div2", UNKNOWN, base + 0xF8, 2);
+ clks[CLK_DDRPLL_DIV4] = starfive_clk_gated_divider("ddrpll_div4", UNKNOWN, base + 0xFC, 2);
+ clks[CLK_DDRPLL_DIV8] = starfive_clk_gated_divider("ddrpll_div8", UNKNOWN, base + 0x100, 2);
+ clks[CLK_DDROSC_DIV2] = starfive_clk_gated_divider("ddrosc_div2", UNKNOWN, base + 0x104, 2);
+ clks[CLK_DDRC0] = starfive_clk_mux("ddrc0", base + 0x108, 2, ddrc0_sels, ARRAY_SIZE(ddrc0_sels));
+ clks[CLK_DDRC1] = starfive_clk_mux("ddrc1", base + 0x10C, 2, ddrc1_sels, ARRAY_SIZE(ddrc1_sels));
+ clks[CLK_DDRPHY_APB] = starfive_clk_gate("ddrphy_apb", UNKNOWN, base + 0x110);
+ clks[CLK_NOC_ROB] = starfive_clk_divider("noc_rob", UNKNOWN, base + 0x114, 4);
+ clks[CLK_NOC_COG] = starfive_clk_divider("noc_cog", UNKNOWN, base + 0x118, 4);
+ clks[CLK_NNE_AHB] = starfive_clk_gate("nne_ahb", UNKNOWN, base + 0x11C);
+ clks[CLK_NNEBUS_SRC1] = starfive_clk_divider("nnebus_src1", UNKNOWN, base + 0x120, 3);
+ clks[CLK_NNE_BUS] = starfive_clk_mux("nne_bus", base + 0x124, 2, nne_bus_sels, ARRAY_SIZE(nne_bus_sels));
+ clks[CLK_NNE_AXI] = starfive_clk_gate("nne_axi", UNKNOWN, base + 0x128);
+ clks[CLK_NNENOC_AXI] = starfive_clk_gate("nnenoc_axi", UNKNOWN, base + 0x12C);
+ clks[CLK_DLASLV_AXI] = starfive_clk_gate("dlaslv_axi", UNKNOWN, base + 0x130);
+ clks[CLK_DSPX2C_AXI] = starfive_clk_gate("dspx2c_axi", UNKNOWN, base + 0x134);
+ clks[CLK_HIFI4_SRC] = starfive_clk_divider("hifi4_src", UNKNOWN, base + 0x138, 3);
+ clks[CLK_HIFI4_COREFREE] = starfive_clk_divider("hifi4_corefree", UNKNOWN, base + 0x13C, 4);
+ clks[CLK_HIFI4_CORE] = starfive_clk_gate("hifi4_core", UNKNOWN, base + 0x140);
+ clks[CLK_HIFI4_BUS] = starfive_clk_divider("hifi4_bus", UNKNOWN, base + 0x144, 4);
+ clks[CLK_HIFI4_AXI] = starfive_clk_gate("hifi4_axi", UNKNOWN, base + 0x148);
+ clks[CLK_HIFI4NOC_AXI] = starfive_clk_gate("hifi4noc_axi", UNKNOWN, base + 0x14C);
+ clks[CLK_SGDMA1P_BUS] = starfive_clk_divider("sgdma1p_bus", UNKNOWN, base + 0x150, 4);
+ clks[CLK_SGDMA1P_AXI] = starfive_clk_gate("sgdma1p_axi", UNKNOWN, base + 0x154);
+ clks[CLK_DMA1P_AXI] = starfive_clk_gate("dma1p_axi", UNKNOWN, base + 0x158);
+ clks[CLK_X2C_AXI] = starfive_clk_gated_divider("x2c_axi", UNKNOWN, base + 0x15C, 4);
+ clks[CLK_USB_BUS] = starfive_clk_divider("usb_bus", UNKNOWN, base + 0x160, 4);
+ clks[CLK_USB_AXI] = starfive_clk_gate("usb_axi", UNKNOWN, base + 0x164);
+ clks[CLK_USBNOC_AXI] = starfive_clk_gate("usbnoc_axi", UNKNOWN, base + 0x168);
+ clks[CLK_USBPHY_ROOTDIV] = starfive_clk_divider("usbphy_rootdiv", UNKNOWN, base + 0x16C, 3);
+ clks[CLK_USBPHY_125M] = starfive_clk_gated_divider("usbphy_125m", UNKNOWN, base + 0x170, 4);
+ clks[CLK_USBPHY_PLLDIV25M] = starfive_clk_gated_divider("usbphy_plldiv25m", UNKNOWN, base + 0x174, 6);
+ clks[CLK_USBPHY_25M] = starfive_clk_mux("usbphy_25m", base + 0x178, 1, usbphy_25m_sels, ARRAY_SIZE(usbphy_25m_sels));
+ clks[CLK_AUDIO_DIV] = starfive_clk_divider("audio_div", UNKNOWN, base + 0x17C, 18);
+ clks[CLK_AUDIO_SRC] = starfive_clk_gate("audio_src", UNKNOWN, base + 0x180);
+ clks[CLK_AUDIO_12288] = starfive_clk_gate("audio_12288", UNKNOWN, base + 0x184);
+ clks[CLK_VIN_SRC] = starfive_clk_gated_divider("vin_src", UNKNOWN, base + 0x188, 3);
+ clks[CLK_ISP0_BUS] = starfive_clk_divider("isp0_bus", UNKNOWN, base + 0x18C, 4);
+ clks[CLK_ISP0_AXI] = starfive_clk_gate("isp0_axi", UNKNOWN, base + 0x190);
+ clks[CLK_ISP0NOC_AXI] = starfive_clk_gate("isp0noc_axi", UNKNOWN, base + 0x194);
+ clks[CLK_ISPSLV_AXI] = starfive_clk_gate("ispslv_axi", UNKNOWN, base + 0x198);
+ clks[CLK_ISP1_BUS] = starfive_clk_divider("isp1_bus", UNKNOWN, base + 0x19C, 4);
+ clks[CLK_ISP1_AXI] = starfive_clk_gate("isp1_axi", UNKNOWN, base + 0x1A0);
+ clks[CLK_ISP1NOC_AXI] = starfive_clk_gate("isp1noc_axi", UNKNOWN, base + 0x1A4);
+ clks[CLK_VIN_BUS] = starfive_clk_divider("vin_bus", UNKNOWN, base + 0x1A8, 4);
+ clks[CLK_VIN_AXI] = starfive_clk_gate("vin_axi", UNKNOWN, base + 0x1AC);
+ clks[CLK_VINNOC_AXI] = starfive_clk_gate("vinnoc_axi", UNKNOWN, base + 0x1B0);
+ clks[CLK_VOUT_SRC] = starfive_clk_gated_divider("vout_src", UNKNOWN, base + 0x1B4, 3);
+ clks[CLK_DISPBUS_SRC] = starfive_clk_divider("dispbus_src", UNKNOWN, base + 0x1B8, 3);
+ clks[CLK_DISP_BUS] = starfive_clk_divider("disp_bus", UNKNOWN, base + 0x1BC, 3);
+ clks[CLK_DISP_AXI] = starfive_clk_gate("disp_axi", UNKNOWN, base + 0x1C0);
+ clks[CLK_DISPNOC_AXI] = starfive_clk_gate("dispnoc_axi", UNKNOWN, base + 0x1C4);
+ clks[CLK_SDIO0_AHB] = starfive_clk_gate("sdio0_ahb", UNKNOWN, base + 0x1C8);
+ clks[CLK_SDIO0_CCLKINT] = starfive_clk_gated_divider("sdio0_cclkint", UNKNOWN, base + 0x1CC, 5);
+ clks[CLK_SDIO0_CCLKINT_INV] = starfive_clk_gate_dis("sdio0_cclkint_inv", UNKNOWN, base + 0x1D0);
+ clks[CLK_SDIO1_AHB] = starfive_clk_gate("sdio1_ahb", UNKNOWN, base + 0x1D4);
+ clks[CLK_SDIO1_CCLKINT] = starfive_clk_gated_divider("sdio1_cclkint", UNKNOWN, base + 0x1D8, 5);
+ clks[CLK_SDIO1_CCLKINT_INV] = starfive_clk_gate_dis("sdio1_cclkint_inv", UNKNOWN, base + 0x1DC);
+ clks[CLK_GMAC_AHB] = starfive_clk_gate("gmac_ahb", UNKNOWN, base + 0x1E0);
+ clks[CLK_GMAC_ROOT_DIV] = starfive_clk_divider("gmac_root_div", UNKNOWN, base + 0x1E4, 4);
+ clks[CLK_GMAC_PTP_REF] = starfive_clk_gated_divider("gmac_ptp_refclk", UNKNOWN, base + 0x1E8, 5);
+ clks[CLK_GMAC_GTX] = starfive_clk_gated_divider("gmac_gtxclk", UNKNOWN, base + 0x1EC, 8);
+ clks[CLK_GMAC_RMII_TX] = starfive_clk_gated_divider("gmac_rmii_txclk", UNKNOWN, base + 0x1F0, 4);
+ clks[CLK_GMAC_RMII_RX] = starfive_clk_gated_divider("gmac_rmii_rxclk", UNKNOWN, base + 0x1F4, 4);
+ clks[CLK_GMAC_TX] = starfive_clk_mux("gmac_tx", base + 0x1F8, 2, gmac_tx_sels, ARRAY_SIZE(gmac_tx_sels));
+ clks[CLK_GMAC_TX_INV] = starfive_clk_gate_dis("gmac_tx_inv", UNKNOWN, base + 0x1FC);
+ clks[CLK_GMAC_RX_PRE] = starfive_clk_mux("gmac_rx_pre", base + 0x200, 1, gmac_rx_pre_sels, ARRAY_SIZE(gmac_rx_pre_sels));
+ clks[CLK_GMAC_RX_INV] = starfive_clk_gate_dis("gmac_rx_inv", UNKNOWN, base + 0x204);
+ clks[CLK_GMAC_RMII] = starfive_clk_gate("gmac_rmii", UNKNOWN, base + 0x208);
+ clks[CLK_GMAC_TOPHYREF] = starfive_clk_gated_divider("gmac_tophyref", UNKNOWN, base + 0x20C, 7);
+ clks[CLK_SPI2AHB_AHB] = starfive_clk_gate("spi2ahb_ahb", UNKNOWN, base + 0x210);
+ clks[CLK_SPI2AHB_CORE] = starfive_clk_gated_divider("spi2ahb_core", UNKNOWN, base + 0x214, 5);
+ clks[CLK_EZMASTER_AHB] = starfive_clk_gate("ezmaster_ahb", UNKNOWN, base + 0x218);
+ clks[CLK_E24_AHB] = starfive_clk_gate("e24_ahb", UNKNOWN, base + 0x21C);
+ clks[CLK_E24RTC_TOGGLE] = starfive_clk_gate("e24rtc_toggle", UNKNOWN, base + 0x220);
+ clks[CLK_QSPI_AHB] = starfive_clk_gate("qspi_ahb", UNKNOWN, base + 0x224);
+ clks[CLK_QSPI_APB] = starfive_clk_gate("qspi_apb", UNKNOWN, base + 0x228);
+ clks[CLK_QSPI_REF] = starfive_clk_gated_divider("qspi_refclk", UNKNOWN, base + 0x22C, 5);
+ clks[CLK_SEC_AHB] = starfive_clk_gate("sec_ahb", UNKNOWN, base + 0x230);
+ clks[CLK_AES] = starfive_clk_gate("aes_clk", UNKNOWN, base + 0x234);
+ clks[CLK_SHA] = starfive_clk_gate("sha_clk", UNKNOWN, base + 0x238);
+ clks[CLK_PKA] = starfive_clk_gate("pka_clk", UNKNOWN, base + 0x23C);
+ clks[CLK_TRNG_APB] = starfive_clk_gate("trng_apb", UNKNOWN, base + 0x240);
+ clks[CLK_OTP_APB] = starfive_clk_gate("otp_apb", UNKNOWN, base + 0x244);
+ clks[CLK_UART0_APB] = starfive_clk_gate("uart0_apb", UNKNOWN, base + 0x248);
+ clks[CLK_UART0_CORE] = starfive_clk_gated_divider("uart0_core", UNKNOWN, base + 0x24C, 6);
+ clks[CLK_UART1_APB] = starfive_clk_gate("uart1_apb", UNKNOWN, base + 0x250);
+ clks[CLK_UART1_CORE] = starfive_clk_gated_divider("uart1_core", UNKNOWN, base + 0x254, 6);
+ clks[CLK_SPI0_APB] = starfive_clk_gate("spi0_apb", UNKNOWN, base + 0x258);
+ clks[CLK_SPI0_CORE] = starfive_clk_gated_divider("spi0_core", UNKNOWN, base + 0x25C, 6);
+ clks[CLK_SPI1_APB] = starfive_clk_gate("spi1_apb", UNKNOWN, base + 0x260);
+ clks[CLK_SPI1_CORE] = starfive_clk_gated_divider("spi1_core", UNKNOWN, base + 0x264, 6);
+ clks[CLK_I2C0_APB] = starfive_clk_gate("i2c0_apb", UNKNOWN, base + 0x268);
+ clks[CLK_I2C0_CORE] = starfive_clk_gated_divider("i2c0_core", UNKNOWN, base + 0x26C, 6);
+ clks[CLK_I2C1_APB] = starfive_clk_gate("i2c1_apb", UNKNOWN, base + 0x270);
+ clks[CLK_I2C1_CORE] = starfive_clk_gated_divider("i2c1_core", UNKNOWN, base + 0x274, 6);
+ clks[CLK_GPIO_APB] = starfive_clk_gate("gpio_apb", UNKNOWN, base + 0x278);
+ clks[CLK_UART2_APB] = starfive_clk_gate("uart2_apb", UNKNOWN, base + 0x27C);
+ clks[CLK_UART2_CORE] = starfive_clk_gated_divider("uart2_core", UNKNOWN, base + 0x280, 6);
+ clks[CLK_UART3_APB] = starfive_clk_gate("uart3_apb", UNKNOWN, base + 0x284);
+ clks[CLK_UART3_CORE] = starfive_clk_gated_divider("uart3_core", UNKNOWN, base + 0x288, 6);
+ clks[CLK_SPI2_APB] = starfive_clk_gate("spi2_apb", UNKNOWN, base + 0x28C);
+ clks[CLK_SPI2_CORE] = starfive_clk_gated_divider("spi2_core", UNKNOWN, base + 0x290, 6);
+ clks[CLK_SPI3_APB] = starfive_clk_gate("spi3_apb", UNKNOWN, base + 0x294);
+ clks[CLK_SPI3_CORE] = starfive_clk_gated_divider("spi3_core", UNKNOWN, base + 0x298, 6);
+ clks[CLK_I2C2_APB] = starfive_clk_gate("i2c2_apb", UNKNOWN, base + 0x29C);
+ clks[CLK_I2C2_CORE] = starfive_clk_gated_divider("i2c2_core", UNKNOWN, base + 0x2A0, 6);
+ clks[CLK_I2C3_APB] = starfive_clk_gate("i2c3_apb", UNKNOWN, base + 0x2A4);
+ clks[CLK_I2C3_CORE] = starfive_clk_gated_divider("i2c3_core", UNKNOWN, base + 0x2A8, 6);
+ clks[CLK_WDTIMER_APB] = starfive_clk_gate("wdtimer_apb", UNKNOWN, base + 0x2AC);
+ clks[CLK_WDT_CORE] = starfive_clk_gated_divider("wdt_coreclk", UNKNOWN, base + 0x2B0, 6);
+ clks[CLK_TIMER0_CORE] = starfive_clk_gated_divider("timer0_coreclk", UNKNOWN, base + 0x2B4, 6);
+ clks[CLK_TIMER1_CORE] = starfive_clk_gated_divider("timer1_coreclk", UNKNOWN, base + 0x2B8, 6);
+ clks[CLK_TIMER2_CORE] = starfive_clk_gated_divider("timer2_coreclk", UNKNOWN, base + 0x2BC, 6);
+ clks[CLK_TIMER3_CORE] = starfive_clk_gated_divider("timer3_coreclk", UNKNOWN, base + 0x2C0, 6);
+ clks[CLK_TIMER4_CORE] = starfive_clk_gated_divider("timer4_coreclk", UNKNOWN, base + 0x2C4, 6);
+ clks[CLK_TIMER5_CORE] = starfive_clk_gated_divider("timer5_coreclk", UNKNOWN, base + 0x2C8, 6);
+ clks[CLK_TIMER6_CORE] = starfive_clk_gated_divider("timer6_coreclk", UNKNOWN, base + 0x2CC, 6);
+ clks[CLK_VP6INTC_APB] = starfive_clk_gate("vp6intc_apb", UNKNOWN, base + 0x2D0);
+ clks[CLK_PWM_APB] = starfive_clk_gate("pwm_apb", UNKNOWN, base + 0x2D4);
+ clks[CLK_MSI_APB] = starfive_clk_gate("msi_apb", UNKNOWN, base + 0x2D8);
+ clks[CLK_TEMP_APB] = starfive_clk_gate("temp_apb", UNKNOWN, base + 0x2DC);
+ clks[CLK_TEMP_SENSE] = starfive_clk_gated_divider("temp_sense", UNKNOWN, base + 0x2E0, 5);
+ clks[CLK_SYSERR_APB] = starfive_clk_gate("syserr_apb", UNKNOWN, base + 0x2E4);
+}
+
+static struct clk_onecell_data clk_data;
+
+static int starfive_clkgen_clk_probe(struct device *dev)
+{
+ struct resource *iores;
+
+ iores = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(iores))
+ return PTR_ERR(iores);
+
+ starfive_clkgen_init(dev->of_node, IOMEM(iores->start));
+
+ clk_data.clks = clks;
+ clk_data.clk_num = ARRAY_SIZE(clks);
+ of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
+ &clk_data);
+
+ return 0;
+}
+
+static __maybe_unused struct of_device_id starfive_clkgen_clk_dt_ids[] = {
+ { .compatible = "starfive,jh7100-clkgen" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, starfive_clkgen_clk_dt_ids);
+
+static struct driver starfive_clkgen_clk_driver = {
+ .probe = starfive_clkgen_clk_probe,
+ .name = "starfive-clkgen",
+ .of_compatible = starfive_clkgen_clk_dt_ids,
+};
+core_platform_driver(starfive_clkgen_clk_driver);
diff --git a/drivers/clk/stm32/Makefile b/drivers/clk/stm32/Makefile
new file mode 100644
index 0000000000..95bd2230bb
--- /dev/null
+++ b/drivers/clk/stm32/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_COMMON_CLK_STM32MP135) += clk-stm32mp13.o clk-stm32-core.o reset-stm32.o
diff --git a/drivers/clk/stm32/clk-stm32-core.c b/drivers/clk/stm32/clk-stm32-core.c
new file mode 100644
index 0000000000..5d83c8c807
--- /dev/null
+++ b/drivers/clk/stm32/clk-stm32-core.c
@@ -0,0 +1,680 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2022 - All Rights Reserved
+ * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics.
+ */
+
+#include <linux/clk-provider.h>
+#include <clock.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <of.h>
+#include <of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "clk-stm32-core.h"
+#include "reset-stm32.h"
+
+static DEFINE_SPINLOCK(rlock);
+
+static int stm32_rcc_clock_init(struct device *dev,
+ const struct of_device_id *match,
+ void __iomem *base)
+{
+ const struct stm32_rcc_match_data *data = match->data;
+ struct clk_hw_onecell_data *clk_data = data->hw_clks;
+ struct device_node *np = dev_of_node(dev);
+ struct clk_hw **hws;
+ int n, max_binding;
+
+ max_binding = data->maxbinding;
+
+ clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, max_binding), GFP_KERNEL);
+ if (!clk_data)
+ return -ENOMEM;
+
+ clk_data->num = max_binding;
+
+ hws = clk_data->hws;
+
+ for (n = 0; n < max_binding; n++)
+ hws[n] = ERR_PTR(-ENOENT);
+
+ for (n = 0; n < data->num_clocks; n++) {
+ const struct clock_config *cfg_clock = &data->tab_clocks[n];
+ struct clk_hw *hw = ERR_PTR(-ENOENT);
+
+ if (data->check_security &&
+ data->check_security(base, cfg_clock))
+ continue;
+
+ if (cfg_clock->func)
+ hw = (*cfg_clock->func)(dev, data, base, &rlock,
+ cfg_clock);
+
+ if (IS_ERR(hw)) {
+ dev_err(dev, "Can't register clk %d: %ld\n", n,
+ PTR_ERR(hw));
+ return PTR_ERR(hw);
+ }
+
+ if (cfg_clock->id != NO_ID)
+ hws[cfg_clock->id] = hw;
+ }
+
+ return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
+}
+
+int stm32_rcc_init(struct device *dev, const struct of_device_id *match_data,
+ void __iomem *base)
+{
+ const struct of_device_id *match;
+ int err;
+
+ match = of_match_node(match_data, dev_of_node(dev));
+ if (!match) {
+ dev_err(dev, "match data not found\n");
+ return -ENODEV;
+ }
+
+ /* RCC Reset Configuration */
+ err = stm32_rcc_reset_init(dev, match, base);
+ if (err) {
+ pr_err("stm32 reset failed to initialize\n");
+ return err;
+ }
+
+ /* RCC Clock Configuration */
+ err = stm32_rcc_clock_init(dev, match, base);
+ if (err) {
+ pr_err("stm32 clock failed to initialize\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static u8 stm32_mux_get_parent(void __iomem *base,
+ struct clk_stm32_clock_data *data,
+ u16 mux_id)
+{
+ const struct stm32_mux_cfg *mux = &data->muxes[mux_id];
+ u32 mask = BIT(mux->width) - 1;
+ u32 val;
+
+ val = readl(base + mux->offset) >> mux->shift;
+ val &= mask;
+
+ return val;
+}
+
+static int stm32_mux_set_parent(void __iomem *base,
+ struct clk_stm32_clock_data *data,
+ u16 mux_id, u8 index)
+{
+ const struct stm32_mux_cfg *mux = &data->muxes[mux_id];
+
+ u32 mask = BIT(mux->width) - 1;
+ u32 reg = readl(base + mux->offset);
+ u32 val = index << mux->shift;
+
+ reg &= ~(mask << mux->shift);
+ reg |= val;
+
+ writel(reg, base + mux->offset);
+
+ return 0;
+}
+
+static void stm32_gate_endisable(void __iomem *base,
+ struct clk_stm32_clock_data *data,
+ u16 gate_id, int enable)
+{
+ const struct stm32_gate_cfg *gate = &data->gates[gate_id];
+ void __iomem *addr = base + gate->offset;
+
+ if (enable) {
+ if (data->gate_cpt[gate_id]++ > 0)
+ return;
+
+ if (gate->set_clr != 0)
+ writel(BIT(gate->bit_idx), addr);
+ else
+ writel(readl(addr) | BIT(gate->bit_idx), addr);
+ } else {
+ if (--data->gate_cpt[gate_id] > 0)
+ return;
+
+ if (gate->set_clr != 0)
+ writel(BIT(gate->bit_idx), addr + gate->set_clr);
+ else
+ writel(readl(addr) & ~BIT(gate->bit_idx), addr);
+ }
+}
+
+static int stm32_gate_is_enabled(void __iomem *base,
+ struct clk_stm32_clock_data *data,
+ u16 gate_id)
+{
+ const struct stm32_gate_cfg *gate = &data->gates[gate_id];
+
+ return (readl(base + gate->offset) & BIT(gate->bit_idx)) != 0;
+}
+
+static unsigned int _get_table_div(const struct clk_div_table *table,
+ unsigned int val)
+{
+ const struct clk_div_table *clkt;
+
+ for (clkt = table; clkt->div; clkt++)
+ if (clkt->val == val)
+ return clkt->div;
+ return 0;
+}
+
+static unsigned int _get_div(const struct clk_div_table *table,
+ unsigned int val, unsigned long flags, u8 width)
+{
+ if (flags & CLK_DIVIDER_ONE_BASED)
+ return val;
+ if (flags & CLK_DIVIDER_POWER_OF_TWO)
+ return 1 << val;
+ if (table)
+ return _get_table_div(table, val);
+ return val + 1;
+}
+
+static unsigned long stm32_divider_get_rate(void __iomem *base,
+ struct clk_stm32_clock_data *data,
+ u16 div_id,
+ unsigned long parent_rate)
+{
+ const struct stm32_div_cfg *divider = &data->dividers[div_id];
+ unsigned int val;
+ unsigned int div;
+
+ val = readl(base + divider->offset) >> divider->shift;
+ val &= clk_div_mask(divider->width);
+ div = _get_div(divider->table, val, divider->flags, divider->width);
+
+ if (!div) {
+ WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO),
+ "%d: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
+ div_id);
+ return parent_rate;
+ }
+
+ return DIV_ROUND_UP_ULL((u64)parent_rate, div);
+}
+
+static int stm32_divider_set_rate(void __iomem *base,
+ struct clk_stm32_clock_data *data,
+ u16 div_id, unsigned long rate,
+ unsigned long parent_rate)
+{
+ const struct stm32_div_cfg *divider = &data->dividers[div_id];
+ int value;
+ u32 val;
+
+ value = divider_get_val(rate, parent_rate, divider->table,
+ divider->width, divider->flags);
+ if (value < 0)
+ return value;
+
+ if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
+ val = clk_div_mask(divider->width) << (divider->shift + 16);
+ } else {
+ val = readl(base + divider->offset);
+ val &= ~(clk_div_mask(divider->width) << divider->shift);
+ }
+
+ val |= (u32)value << divider->shift;
+
+ writel(val, base + divider->offset);
+
+ return 0;
+}
+
+static int clk_stm32_mux_get_parent(struct clk_hw *hw)
+{
+ struct clk_stm32_mux *mux = to_clk_stm32_mux(hw);
+
+ return stm32_mux_get_parent(mux->base, mux->clock_data, mux->mux_id);
+}
+
+static int clk_stm32_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct clk_stm32_mux *mux = to_clk_stm32_mux(hw);
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(mux->lock, flags);
+
+ stm32_mux_set_parent(mux->base, mux->clock_data, mux->mux_id, index);
+
+ spin_unlock_irqrestore(mux->lock, flags);
+
+ return 0;
+}
+
+const struct clk_ops clk_stm32_mux_ops = {
+ .round_rate = clk_mux_round_rate,
+ .get_parent = clk_stm32_mux_get_parent,
+ .set_parent = clk_stm32_mux_set_parent,
+};
+
+static void clk_stm32_gate_endisable(struct clk_hw *hw, int enable)
+{
+ struct clk_stm32_gate *gate = to_clk_stm32_gate(hw);
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(gate->lock, flags);
+
+ stm32_gate_endisable(gate->base, gate->clock_data, gate->gate_id, enable);
+
+ spin_unlock_irqrestore(gate->lock, flags);
+}
+
+static int clk_stm32_gate_enable(struct clk_hw *hw)
+{
+ clk_stm32_gate_endisable(hw, 1);
+
+ return 0;
+}
+
+static void clk_stm32_gate_disable(struct clk_hw *hw)
+{
+ clk_stm32_gate_endisable(hw, 0);
+}
+
+static int clk_stm32_gate_is_enabled(struct clk_hw *hw)
+{
+ struct clk_stm32_gate *gate = to_clk_stm32_gate(hw);
+
+ return stm32_gate_is_enabled(gate->base, gate->clock_data, gate->gate_id);
+}
+
+const struct clk_ops clk_stm32_gate_ops = {
+ .enable = clk_stm32_gate_enable,
+ .disable = clk_stm32_gate_disable,
+ .is_enabled = clk_stm32_gate_is_enabled,
+};
+
+static int clk_stm32_divider_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_stm32_div *div = to_clk_stm32_divider(hw);
+ unsigned long flags = 0;
+ int ret;
+
+ if (div->div_id == NO_STM32_DIV)
+ return rate;
+
+ spin_lock_irqsave(div->lock, flags);
+
+ ret = stm32_divider_set_rate(div->base, div->clock_data, div->div_id, rate, parent_rate);
+
+ spin_unlock_irqrestore(div->lock, flags);
+
+ return ret;
+}
+
+static long clk_stm32_divider_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct clk_stm32_div *div = to_clk_stm32_divider(hw);
+ const struct stm32_div_cfg *divider;
+
+ if (div->div_id == NO_STM32_DIV)
+ return rate;
+
+ divider = &div->clock_data->dividers[div->div_id];
+
+ /* if read only, just return current value */
+ if (divider->flags & CLK_DIVIDER_READ_ONLY) {
+ u32 val;
+
+ val = readl(div->base + divider->offset) >> divider->shift;
+ val &= clk_div_mask(divider->width);
+
+ return divider_ro_round_rate(hw, rate, prate, divider->table,
+ divider->width, divider->flags,
+ val);
+ }
+
+ return divider_round_rate_parent(hw, clk_hw_get_parent(hw),
+ rate, prate, divider->table,
+ divider->width, divider->flags);
+}
+
+static unsigned long clk_stm32_divider_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_stm32_div *div = to_clk_stm32_divider(hw);
+
+ if (div->div_id == NO_STM32_DIV)
+ return parent_rate;
+
+ return stm32_divider_get_rate(div->base, div->clock_data, div->div_id, parent_rate);
+}
+
+const struct clk_ops clk_stm32_divider_ops = {
+ .recalc_rate = clk_stm32_divider_recalc_rate,
+ .round_rate = clk_stm32_divider_round_rate,
+ .set_rate = clk_stm32_divider_set_rate,
+};
+
+static int clk_stm32_composite_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
+ unsigned long flags = 0;
+ int ret;
+
+ if (composite->div_id == NO_STM32_DIV)
+ return rate;
+
+ spin_lock_irqsave(composite->lock, flags);
+
+ ret = stm32_divider_set_rate(composite->base, composite->clock_data,
+ composite->div_id, rate, parent_rate);
+
+ spin_unlock_irqrestore(composite->lock, flags);
+
+ return ret;
+}
+
+static unsigned long clk_stm32_composite_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
+
+ if (composite->div_id == NO_STM32_DIV)
+ return parent_rate;
+
+ return stm32_divider_get_rate(composite->base, composite->clock_data,
+ composite->div_id, parent_rate);
+}
+
+static int clk_stm32_composite_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
+ const struct stm32_div_cfg *divider;
+ long rate;
+
+ if (composite->div_id == NO_STM32_DIV)
+ return 0;
+
+ divider = &composite->clock_data->dividers[composite->div_id];
+
+ /* if read only, just return current value */
+ if (divider->flags & CLK_DIVIDER_READ_ONLY) {
+ u32 val;
+
+ val = readl(composite->base + divider->offset) >> divider->shift;
+ val &= clk_div_mask(divider->width);
+
+ rate = divider_ro_round_rate(hw, req->rate, &req->best_parent_rate,
+ divider->table, divider->width, divider->flags,
+ val);
+ if (rate < 0)
+ return rate;
+
+ req->rate = rate;
+ return 0;
+ }
+
+ rate = divider_round_rate_parent(hw, clk_hw_get_parent(hw),
+ req->rate, &req->best_parent_rate,
+ divider->table, divider->width, divider->flags);
+ if (rate < 0)
+ return rate;
+
+ req->rate = rate;
+ return 0;
+}
+
+static long clk_stm32_composite_round_rate(struct clk_hw *hw,
+ unsigned long rate,
+ unsigned long *prate)
+{
+ struct clk_rate_request req = {};
+ int ret;
+
+ req.rate = rate;
+ req.best_parent_rate = *prate;
+
+ ret = clk_stm32_composite_determine_rate(hw, &req);
+ if (ret)
+ return ret;
+
+ *prate = req.best_parent_rate;
+
+ return req.rate;
+}
+
+static int clk_stm32_composite_get_parent(struct clk_hw *hw)
+{
+ struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
+
+ return stm32_mux_get_parent(composite->base, composite->clock_data, composite->mux_id);
+}
+
+static int clk_stm32_composite_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(composite->lock, flags);
+
+ stm32_mux_set_parent(composite->base, composite->clock_data, composite->mux_id, index);
+
+ spin_unlock_irqrestore(composite->lock, flags);
+
+ if (composite->clock_data->is_multi_mux) {
+ struct clk_hw *other_mux_hw = composite->clock_data->is_multi_mux(hw);
+
+ if (other_mux_hw) {
+ struct clk_hw *hwp = clk_hw_get_parent_by_index(hw, index);
+
+ clk_hw_reparent(other_mux_hw, hwp);
+ }
+ }
+
+ return 0;
+}
+
+static int clk_stm32_composite_is_enabled(struct clk_hw *hw)
+{
+ struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
+
+ if (composite->gate_id == NO_STM32_GATE)
+ return (__clk_get_enable_count(&hw->clk) > 0);
+
+ return stm32_gate_is_enabled(composite->base, composite->clock_data, composite->gate_id);
+}
+
+#define MUX_SAFE_POSITION 0
+
+static int clk_stm32_has_safe_mux(struct clk_hw *hw)
+{
+ struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
+ const struct stm32_mux_cfg *mux = &composite->clock_data->muxes[composite->mux_id];
+
+ return !!(mux->flags & MUX_SAFE);
+}
+
+static void clk_stm32_set_safe_position_mux(struct clk_hw *hw)
+{
+ struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
+
+ if (!clk_stm32_composite_is_enabled(hw)) {
+ unsigned long flags = 0;
+
+ if (composite->clock_data->is_multi_mux) {
+ struct clk_hw *other_mux_hw = NULL;
+
+ other_mux_hw = composite->clock_data->is_multi_mux(hw);
+
+ if (!other_mux_hw || clk_stm32_composite_is_enabled(other_mux_hw))
+ return;
+ }
+
+ spin_lock_irqsave(composite->lock, flags);
+
+ stm32_mux_set_parent(composite->base, composite->clock_data,
+ composite->mux_id, MUX_SAFE_POSITION);
+
+ spin_unlock_irqrestore(composite->lock, flags);
+ }
+}
+
+static void clk_stm32_safe_restore_position_mux(struct clk_hw *hw)
+{
+ struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
+ int sel = clk_hw_get_parent_index(hw);
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(composite->lock, flags);
+
+ stm32_mux_set_parent(composite->base, composite->clock_data, composite->mux_id, sel);
+
+ spin_unlock_irqrestore(composite->lock, flags);
+}
+
+static void clk_stm32_composite_gate_endisable(struct clk_hw *hw, int enable)
+{
+ struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(composite->lock, flags);
+
+ stm32_gate_endisable(composite->base, composite->clock_data, composite->gate_id, enable);
+
+ spin_unlock_irqrestore(composite->lock, flags);
+}
+
+static int clk_stm32_composite_gate_enable(struct clk_hw *hw)
+{
+ struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
+
+ if (composite->gate_id == NO_STM32_GATE)
+ return 0;
+
+ clk_stm32_composite_gate_endisable(hw, 1);
+
+ if (composite->mux_id != NO_STM32_MUX && clk_stm32_has_safe_mux(hw))
+ clk_stm32_safe_restore_position_mux(hw);
+
+ return 0;
+}
+
+static void clk_stm32_composite_gate_disable(struct clk_hw *hw)
+{
+ struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
+
+ if (composite->gate_id == NO_STM32_GATE)
+ return;
+
+ clk_stm32_composite_gate_endisable(hw, 0);
+
+ if (composite->mux_id != NO_STM32_MUX && clk_stm32_has_safe_mux(hw))
+ clk_stm32_set_safe_position_mux(hw);
+}
+
+const struct clk_ops clk_stm32_composite_ops = {
+ .set_rate = clk_stm32_composite_set_rate,
+ .recalc_rate = clk_stm32_composite_recalc_rate,
+ .round_rate = clk_stm32_composite_round_rate,
+ .get_parent = clk_stm32_composite_get_parent,
+ .set_parent = clk_stm32_composite_set_parent,
+ .enable = clk_stm32_composite_gate_enable,
+ .disable = clk_stm32_composite_gate_disable,
+ .is_enabled = clk_stm32_composite_is_enabled,
+};
+
+struct clk_hw *clk_stm32_mux_register(struct device *dev,
+ const struct stm32_rcc_match_data *data,
+ void __iomem *base,
+ spinlock_t *lock,
+ const struct clock_config *cfg)
+{
+ struct clk_stm32_mux *mux = cfg->clock_cfg;
+ struct clk_hw *hw = &mux->hw;
+ int err;
+
+ mux->base = base;
+ mux->lock = lock;
+ mux->clock_data = data->clock_data;
+
+ err = clk_hw_register(dev, hw);
+ if (err)
+ return ERR_PTR(err);
+
+ return hw;
+}
+
+struct clk_hw *clk_stm32_gate_register(struct device *dev,
+ const struct stm32_rcc_match_data *data,
+ void __iomem *base,
+ spinlock_t *lock,
+ const struct clock_config *cfg)
+{
+ struct clk_stm32_gate *gate = cfg->clock_cfg;
+ struct clk_hw *hw = &gate->hw;
+ int err;
+
+ gate->base = base;
+ gate->lock = lock;
+ gate->clock_data = data->clock_data;
+
+ err = clk_hw_register(dev, hw);
+ if (err)
+ return ERR_PTR(err);
+
+ return hw;
+}
+
+struct clk_hw *clk_stm32_div_register(struct device *dev,
+ const struct stm32_rcc_match_data *data,
+ void __iomem *base,
+ spinlock_t *lock,
+ const struct clock_config *cfg)
+{
+ struct clk_stm32_div *div = cfg->clock_cfg;
+ struct clk_hw *hw = &div->hw;
+ int err;
+
+ div->base = base;
+ div->lock = lock;
+ div->clock_data = data->clock_data;
+
+ err = clk_hw_register(dev, hw);
+ if (err)
+ return ERR_PTR(err);
+
+ return hw;
+}
+
+struct clk_hw *clk_stm32_composite_register(struct device *dev,
+ const struct stm32_rcc_match_data *data,
+ void __iomem *base,
+ spinlock_t *lock,
+ const struct clock_config *cfg)
+{
+ struct clk_stm32_composite *composite = cfg->clock_cfg;
+ struct clk_hw *hw = &composite->hw;
+ int err;
+
+ composite->base = base;
+ composite->lock = lock;
+ composite->clock_data = data->clock_data;
+
+ err = clk_hw_register(dev, hw);
+ if (err)
+ return ERR_PTR(err);
+
+ return hw;
+}
diff --git a/drivers/clk/stm32/clk-stm32-core.h b/drivers/clk/stm32/clk-stm32-core.h
new file mode 100644
index 0000000000..76cffda023
--- /dev/null
+++ b/drivers/clk/stm32/clk-stm32-core.h
@@ -0,0 +1,188 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) STMicroelectronics 2022 - All Rights Reserved
+ * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics.
+ */
+
+#include <linux/clk-provider.h>
+
+struct stm32_rcc_match_data;
+
+struct stm32_mux_cfg {
+ u16 offset;
+ u8 shift;
+ u8 width;
+ u8 flags;
+ u32 *table;
+ u8 ready;
+};
+
+struct stm32_gate_cfg {
+ u16 offset;
+ u8 bit_idx;
+ u8 set_clr;
+};
+
+struct stm32_div_cfg {
+ u16 offset;
+ u8 shift;
+ u8 width;
+ u8 flags;
+ u8 ready;
+ const struct clk_div_table *table;
+};
+
+struct stm32_composite_cfg {
+ int mux;
+ int gate;
+ int div;
+};
+
+#define NO_ID 0xFFFFFFFF
+
+#define NO_STM32_MUX 0xFFFF
+#define NO_STM32_DIV 0xFFFF
+#define NO_STM32_GATE 0xFFFF
+
+struct clock_config {
+ unsigned long id;
+ int sec_id;
+ void *clock_cfg;
+
+ struct clk_hw *(*func)(struct device *dev,
+ const struct stm32_rcc_match_data *data,
+ void __iomem *base,
+ spinlock_t *lock,
+ const struct clock_config *cfg);
+};
+
+struct clk_stm32_clock_data {
+ u16 *gate_cpt;
+ const struct stm32_gate_cfg *gates;
+ const struct stm32_mux_cfg *muxes;
+ const struct stm32_div_cfg *dividers;
+ struct clk_hw *(*is_multi_mux)(struct clk_hw *hw);
+};
+
+struct stm32_rcc_match_data {
+ struct clk_hw_onecell_data *hw_clks;
+ unsigned int num_clocks;
+ const struct clock_config *tab_clocks;
+ unsigned int maxbinding;
+ struct clk_stm32_clock_data *clock_data;
+ u32 clear_offset;
+ int (*check_security)(void __iomem *base,
+ const struct clock_config *cfg);
+ int (*multi_mux)(void __iomem *base, const struct clock_config *cfg);
+};
+
+int stm32_rcc_reset_init(struct device *dev, const struct of_device_id *match,
+ void __iomem *base);
+
+int stm32_rcc_init(struct device *dev, const struct of_device_id *match_data,
+ void __iomem *base);
+
+/* MUX define */
+#define MUX_NO_RDY 0xFF
+#define MUX_SAFE BIT(7)
+
+/* DIV define */
+#define DIV_NO_RDY 0xFF
+
+/* Definition of clock structure */
+struct clk_stm32_mux {
+ u16 mux_id;
+ struct clk_hw hw;
+ void __iomem *base;
+ struct clk_stm32_clock_data *clock_data;
+ spinlock_t *lock; /* spin lock */
+};
+
+#define to_clk_stm32_mux(_hw) container_of(_hw, struct clk_stm32_mux, hw)
+
+struct clk_stm32_gate {
+ u16 gate_id;
+ struct clk_hw hw;
+ void __iomem *base;
+ struct clk_stm32_clock_data *clock_data;
+ spinlock_t *lock; /* spin lock */
+};
+
+#define to_clk_stm32_gate(_hw) container_of(_hw, struct clk_stm32_gate, hw)
+
+struct clk_stm32_div {
+ u16 div_id;
+ struct clk_hw hw;
+ void __iomem *base;
+ struct clk_stm32_clock_data *clock_data;
+ spinlock_t *lock; /* spin lock */
+};
+
+#define to_clk_stm32_divider(_hw) container_of(_hw, struct clk_stm32_div, hw)
+
+struct clk_stm32_composite {
+ u16 gate_id;
+ u16 mux_id;
+ u16 div_id;
+ struct clk_hw hw;
+ void __iomem *base;
+ struct clk_stm32_clock_data *clock_data;
+ spinlock_t *lock; /* spin lock */
+};
+
+#define to_clk_stm32_composite(_hw) container_of(_hw, struct clk_stm32_composite, hw)
+
+/* Clock operators */
+extern const struct clk_ops clk_stm32_mux_ops;
+extern const struct clk_ops clk_stm32_gate_ops;
+extern const struct clk_ops clk_stm32_divider_ops;
+extern const struct clk_ops clk_stm32_composite_ops;
+
+/* Clock registering */
+struct clk_hw *clk_stm32_mux_register(struct device *dev,
+ const struct stm32_rcc_match_data *data,
+ void __iomem *base,
+ spinlock_t *lock,
+ const struct clock_config *cfg);
+
+struct clk_hw *clk_stm32_gate_register(struct device *dev,
+ const struct stm32_rcc_match_data *data,
+ void __iomem *base,
+ spinlock_t *lock,
+ const struct clock_config *cfg);
+
+struct clk_hw *clk_stm32_div_register(struct device *dev,
+ const struct stm32_rcc_match_data *data,
+ void __iomem *base,
+ spinlock_t *lock,
+ const struct clock_config *cfg);
+
+struct clk_hw *clk_stm32_composite_register(struct device *dev,
+ const struct stm32_rcc_match_data *data,
+ void __iomem *base,
+ spinlock_t *lock,
+ const struct clock_config *cfg);
+
+#define STM32_CLOCK_CFG(_binding, _clk, _sec_id, _struct, _register)\
+{\
+ .id = (_binding),\
+ .sec_id = (_sec_id),\
+ .clock_cfg = (_struct) {_clk},\
+ .func = (_register),\
+}
+
+#define STM32_MUX_CFG(_binding, _clk, _sec_id)\
+ STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_mux *,\
+ &clk_stm32_mux_register)
+
+#define STM32_GATE_CFG(_binding, _clk, _sec_id)\
+ STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_gate *,\
+ &clk_stm32_gate_register)
+
+#define STM32_DIV_CFG(_binding, _clk, _sec_id)\
+ STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_div *,\
+ &clk_stm32_div_register)
+
+#define STM32_COMPOSITE_CFG(_binding, _clk, _sec_id)\
+ STM32_CLOCK_CFG(_binding, &(_clk), _sec_id, struct clk_stm32_composite *,\
+ &clk_stm32_composite_register)
diff --git a/drivers/clk/stm32/clk-stm32mp13.c b/drivers/clk/stm32/clk-stm32mp13.c
new file mode 100644
index 0000000000..7816aa16e1
--- /dev/null
+++ b/drivers/clk/stm32/clk-stm32mp13.c
@@ -0,0 +1,1611 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2022 - All Rights Reserved
+ * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics.
+ */
+
+#include <linux/clk.h>
+#include <init.h>
+#include <of_address.h>
+#include <linux/device.h>
+#include <dt-bindings/clock/stm32mp13-clks.h>
+#include "clk-stm32-core.h"
+#include "stm32mp13_rcc.h"
+
+#define RCC_CLR_OFFSET 0x4
+
+/* STM32 Gates definition */
+enum enum_gate_cfg {
+ GATE_MCO1,
+ GATE_MCO2,
+ GATE_DBGCK,
+ GATE_TRACECK,
+ GATE_DDRC1,
+ GATE_DDRC1LP,
+ GATE_DDRPHYC,
+ GATE_DDRPHYCLP,
+ GATE_DDRCAPB,
+ GATE_DDRCAPBLP,
+ GATE_AXIDCG,
+ GATE_DDRPHYCAPB,
+ GATE_DDRPHYCAPBLP,
+ GATE_TIM2,
+ GATE_TIM3,
+ GATE_TIM4,
+ GATE_TIM5,
+ GATE_TIM6,
+ GATE_TIM7,
+ GATE_LPTIM1,
+ GATE_SPI2,
+ GATE_SPI3,
+ GATE_USART3,
+ GATE_UART4,
+ GATE_UART5,
+ GATE_UART7,
+ GATE_UART8,
+ GATE_I2C1,
+ GATE_I2C2,
+ GATE_SPDIF,
+ GATE_TIM1,
+ GATE_TIM8,
+ GATE_SPI1,
+ GATE_USART6,
+ GATE_SAI1,
+ GATE_SAI2,
+ GATE_DFSDM,
+ GATE_ADFSDM,
+ GATE_FDCAN,
+ GATE_LPTIM2,
+ GATE_LPTIM3,
+ GATE_LPTIM4,
+ GATE_LPTIM5,
+ GATE_VREF,
+ GATE_DTS,
+ GATE_PMBCTRL,
+ GATE_HDP,
+ GATE_SYSCFG,
+ GATE_DCMIPP,
+ GATE_DDRPERFM,
+ GATE_IWDG2APB,
+ GATE_USBPHY,
+ GATE_STGENRO,
+ GATE_LTDC,
+ GATE_RTCAPB,
+ GATE_TZC,
+ GATE_ETZPC,
+ GATE_IWDG1APB,
+ GATE_BSEC,
+ GATE_STGENC,
+ GATE_USART1,
+ GATE_USART2,
+ GATE_SPI4,
+ GATE_SPI5,
+ GATE_I2C3,
+ GATE_I2C4,
+ GATE_I2C5,
+ GATE_TIM12,
+ GATE_TIM13,
+ GATE_TIM14,
+ GATE_TIM15,
+ GATE_TIM16,
+ GATE_TIM17,
+ GATE_DMA1,
+ GATE_DMA2,
+ GATE_DMAMUX1,
+ GATE_DMA3,
+ GATE_DMAMUX2,
+ GATE_ADC1,
+ GATE_ADC2,
+ GATE_USBO,
+ GATE_TSC,
+ GATE_GPIOA,
+ GATE_GPIOB,
+ GATE_GPIOC,
+ GATE_GPIOD,
+ GATE_GPIOE,
+ GATE_GPIOF,
+ GATE_GPIOG,
+ GATE_GPIOH,
+ GATE_GPIOI,
+ GATE_PKA,
+ GATE_SAES,
+ GATE_CRYP1,
+ GATE_HASH1,
+ GATE_RNG1,
+ GATE_BKPSRAM,
+ GATE_AXIMC,
+ GATE_MCE,
+ GATE_ETH1CK,
+ GATE_ETH1TX,
+ GATE_ETH1RX,
+ GATE_ETH1MAC,
+ GATE_FMC,
+ GATE_QSPI,
+ GATE_SDMMC1,
+ GATE_SDMMC2,
+ GATE_CRC1,
+ GATE_USBH,
+ GATE_ETH2CK,
+ GATE_ETH2TX,
+ GATE_ETH2RX,
+ GATE_ETH2MAC,
+ GATE_ETH1STP,
+ GATE_ETH2STP,
+ GATE_MDMA,
+ GATE_NB
+};
+
+#define _CFG_GATE(_id, _offset, _bit_idx, _offset_clr)\
+ [(_id)] = {\
+ .offset = (_offset),\
+ .bit_idx = (_bit_idx),\
+ .set_clr = (_offset_clr),\
+ }
+
+#define CFG_GATE(_id, _offset, _bit_idx)\
+ _CFG_GATE(_id, _offset, _bit_idx, 0)
+
+#define CFG_GATE_SETCLR(_id, _offset, _bit_idx)\
+ _CFG_GATE(_id, _offset, _bit_idx, RCC_CLR_OFFSET)
+
+static struct stm32_gate_cfg stm32mp13_gates[] = {
+ CFG_GATE(GATE_MCO1, RCC_MCO1CFGR, 12),
+ CFG_GATE(GATE_MCO2, RCC_MCO2CFGR, 12),
+ CFG_GATE(GATE_DBGCK, RCC_DBGCFGR, 8),
+ CFG_GATE(GATE_TRACECK, RCC_DBGCFGR, 9),
+ CFG_GATE(GATE_DDRC1, RCC_DDRITFCR, 0),
+ CFG_GATE(GATE_DDRC1LP, RCC_DDRITFCR, 1),
+ CFG_GATE(GATE_DDRPHYC, RCC_DDRITFCR, 4),
+ CFG_GATE(GATE_DDRPHYCLP, RCC_DDRITFCR, 5),
+ CFG_GATE(GATE_DDRCAPB, RCC_DDRITFCR, 6),
+ CFG_GATE(GATE_DDRCAPBLP, RCC_DDRITFCR, 7),
+ CFG_GATE(GATE_AXIDCG, RCC_DDRITFCR, 8),
+ CFG_GATE(GATE_DDRPHYCAPB, RCC_DDRITFCR, 9),
+ CFG_GATE(GATE_DDRPHYCAPBLP, RCC_DDRITFCR, 10),
+ CFG_GATE_SETCLR(GATE_TIM2, RCC_MP_APB1ENSETR, 0),
+ CFG_GATE_SETCLR(GATE_TIM3, RCC_MP_APB1ENSETR, 1),
+ CFG_GATE_SETCLR(GATE_TIM4, RCC_MP_APB1ENSETR, 2),
+ CFG_GATE_SETCLR(GATE_TIM5, RCC_MP_APB1ENSETR, 3),
+ CFG_GATE_SETCLR(GATE_TIM6, RCC_MP_APB1ENSETR, 4),
+ CFG_GATE_SETCLR(GATE_TIM7, RCC_MP_APB1ENSETR, 5),
+ CFG_GATE_SETCLR(GATE_LPTIM1, RCC_MP_APB1ENSETR, 9),
+ CFG_GATE_SETCLR(GATE_SPI2, RCC_MP_APB1ENSETR, 11),
+ CFG_GATE_SETCLR(GATE_SPI3, RCC_MP_APB1ENSETR, 12),
+ CFG_GATE_SETCLR(GATE_USART3, RCC_MP_APB1ENSETR, 15),
+ CFG_GATE_SETCLR(GATE_UART4, RCC_MP_APB1ENSETR, 16),
+ CFG_GATE_SETCLR(GATE_UART5, RCC_MP_APB1ENSETR, 17),
+ CFG_GATE_SETCLR(GATE_UART7, RCC_MP_APB1ENSETR, 18),
+ CFG_GATE_SETCLR(GATE_UART8, RCC_MP_APB1ENSETR, 19),
+ CFG_GATE_SETCLR(GATE_I2C1, RCC_MP_APB1ENSETR, 21),
+ CFG_GATE_SETCLR(GATE_I2C2, RCC_MP_APB1ENSETR, 22),
+ CFG_GATE_SETCLR(GATE_SPDIF, RCC_MP_APB1ENSETR, 26),
+ CFG_GATE_SETCLR(GATE_TIM1, RCC_MP_APB2ENSETR, 0),
+ CFG_GATE_SETCLR(GATE_TIM8, RCC_MP_APB2ENSETR, 1),
+ CFG_GATE_SETCLR(GATE_SPI1, RCC_MP_APB2ENSETR, 8),
+ CFG_GATE_SETCLR(GATE_USART6, RCC_MP_APB2ENSETR, 13),
+ CFG_GATE_SETCLR(GATE_SAI1, RCC_MP_APB2ENSETR, 16),
+ CFG_GATE_SETCLR(GATE_SAI2, RCC_MP_APB2ENSETR, 17),
+ CFG_GATE_SETCLR(GATE_DFSDM, RCC_MP_APB2ENSETR, 20),
+ CFG_GATE_SETCLR(GATE_ADFSDM, RCC_MP_APB2ENSETR, 21),
+ CFG_GATE_SETCLR(GATE_FDCAN, RCC_MP_APB2ENSETR, 24),
+ CFG_GATE_SETCLR(GATE_LPTIM2, RCC_MP_APB3ENSETR, 0),
+ CFG_GATE_SETCLR(GATE_LPTIM3, RCC_MP_APB3ENSETR, 1),
+ CFG_GATE_SETCLR(GATE_LPTIM4, RCC_MP_APB3ENSETR, 2),
+ CFG_GATE_SETCLR(GATE_LPTIM5, RCC_MP_APB3ENSETR, 3),
+ CFG_GATE_SETCLR(GATE_VREF, RCC_MP_APB3ENSETR, 13),
+ CFG_GATE_SETCLR(GATE_DTS, RCC_MP_APB3ENSETR, 16),
+ CFG_GATE_SETCLR(GATE_PMBCTRL, RCC_MP_APB3ENSETR, 17),
+ CFG_GATE_SETCLR(GATE_HDP, RCC_MP_APB3ENSETR, 20),
+ CFG_GATE_SETCLR(GATE_SYSCFG, RCC_MP_NS_APB3ENSETR, 0),
+ CFG_GATE_SETCLR(GATE_DCMIPP, RCC_MP_APB4ENSETR, 1),
+ CFG_GATE_SETCLR(GATE_DDRPERFM, RCC_MP_APB4ENSETR, 8),
+ CFG_GATE_SETCLR(GATE_IWDG2APB, RCC_MP_APB4ENSETR, 15),
+ CFG_GATE_SETCLR(GATE_USBPHY, RCC_MP_APB4ENSETR, 16),
+ CFG_GATE_SETCLR(GATE_STGENRO, RCC_MP_APB4ENSETR, 20),
+ CFG_GATE_SETCLR(GATE_LTDC, RCC_MP_NS_APB4ENSETR, 0),
+ CFG_GATE_SETCLR(GATE_RTCAPB, RCC_MP_APB5ENSETR, 8),
+ CFG_GATE_SETCLR(GATE_TZC, RCC_MP_APB5ENSETR, 11),
+ CFG_GATE_SETCLR(GATE_ETZPC, RCC_MP_APB5ENSETR, 13),
+ CFG_GATE_SETCLR(GATE_IWDG1APB, RCC_MP_APB5ENSETR, 15),
+ CFG_GATE_SETCLR(GATE_BSEC, RCC_MP_APB5ENSETR, 16),
+ CFG_GATE_SETCLR(GATE_STGENC, RCC_MP_APB5ENSETR, 20),
+ CFG_GATE_SETCLR(GATE_USART1, RCC_MP_APB6ENSETR, 0),
+ CFG_GATE_SETCLR(GATE_USART2, RCC_MP_APB6ENSETR, 1),
+ CFG_GATE_SETCLR(GATE_SPI4, RCC_MP_APB6ENSETR, 2),
+ CFG_GATE_SETCLR(GATE_SPI5, RCC_MP_APB6ENSETR, 3),
+ CFG_GATE_SETCLR(GATE_I2C3, RCC_MP_APB6ENSETR, 4),
+ CFG_GATE_SETCLR(GATE_I2C4, RCC_MP_APB6ENSETR, 5),
+ CFG_GATE_SETCLR(GATE_I2C5, RCC_MP_APB6ENSETR, 6),
+ CFG_GATE_SETCLR(GATE_TIM12, RCC_MP_APB6ENSETR, 7),
+ CFG_GATE_SETCLR(GATE_TIM13, RCC_MP_APB6ENSETR, 8),
+ CFG_GATE_SETCLR(GATE_TIM14, RCC_MP_APB6ENSETR, 9),
+ CFG_GATE_SETCLR(GATE_TIM15, RCC_MP_APB6ENSETR, 10),
+ CFG_GATE_SETCLR(GATE_TIM16, RCC_MP_APB6ENSETR, 11),
+ CFG_GATE_SETCLR(GATE_TIM17, RCC_MP_APB6ENSETR, 12),
+ CFG_GATE_SETCLR(GATE_DMA1, RCC_MP_AHB2ENSETR, 0),
+ CFG_GATE_SETCLR(GATE_DMA2, RCC_MP_AHB2ENSETR, 1),
+ CFG_GATE_SETCLR(GATE_DMAMUX1, RCC_MP_AHB2ENSETR, 2),
+ CFG_GATE_SETCLR(GATE_DMA3, RCC_MP_AHB2ENSETR, 3),
+ CFG_GATE_SETCLR(GATE_DMAMUX2, RCC_MP_AHB2ENSETR, 4),
+ CFG_GATE_SETCLR(GATE_ADC1, RCC_MP_AHB2ENSETR, 5),
+ CFG_GATE_SETCLR(GATE_ADC2, RCC_MP_AHB2ENSETR, 6),
+ CFG_GATE_SETCLR(GATE_USBO, RCC_MP_AHB2ENSETR, 8),
+ CFG_GATE_SETCLR(GATE_TSC, RCC_MP_AHB4ENSETR, 15),
+ CFG_GATE_SETCLR(GATE_GPIOA, RCC_MP_NS_AHB4ENSETR, 0),
+ CFG_GATE_SETCLR(GATE_GPIOB, RCC_MP_NS_AHB4ENSETR, 1),
+ CFG_GATE_SETCLR(GATE_GPIOC, RCC_MP_NS_AHB4ENSETR, 2),
+ CFG_GATE_SETCLR(GATE_GPIOD, RCC_MP_NS_AHB4ENSETR, 3),
+ CFG_GATE_SETCLR(GATE_GPIOE, RCC_MP_NS_AHB4ENSETR, 4),
+ CFG_GATE_SETCLR(GATE_GPIOF, RCC_MP_NS_AHB4ENSETR, 5),
+ CFG_GATE_SETCLR(GATE_GPIOG, RCC_MP_NS_AHB4ENSETR, 6),
+ CFG_GATE_SETCLR(GATE_GPIOH, RCC_MP_NS_AHB4ENSETR, 7),
+ CFG_GATE_SETCLR(GATE_GPIOI, RCC_MP_NS_AHB4ENSETR, 8),
+ CFG_GATE_SETCLR(GATE_PKA, RCC_MP_AHB5ENSETR, 2),
+ CFG_GATE_SETCLR(GATE_SAES, RCC_MP_AHB5ENSETR, 3),
+ CFG_GATE_SETCLR(GATE_CRYP1, RCC_MP_AHB5ENSETR, 4),
+ CFG_GATE_SETCLR(GATE_HASH1, RCC_MP_AHB5ENSETR, 5),
+ CFG_GATE_SETCLR(GATE_RNG1, RCC_MP_AHB5ENSETR, 6),
+ CFG_GATE_SETCLR(GATE_BKPSRAM, RCC_MP_AHB5ENSETR, 8),
+ CFG_GATE_SETCLR(GATE_AXIMC, RCC_MP_AHB5ENSETR, 16),
+ CFG_GATE_SETCLR(GATE_MCE, RCC_MP_AHB6ENSETR, 1),
+ CFG_GATE_SETCLR(GATE_ETH1CK, RCC_MP_AHB6ENSETR, 7),
+ CFG_GATE_SETCLR(GATE_ETH1TX, RCC_MP_AHB6ENSETR, 8),
+ CFG_GATE_SETCLR(GATE_ETH1RX, RCC_MP_AHB6ENSETR, 9),
+ CFG_GATE_SETCLR(GATE_ETH1MAC, RCC_MP_AHB6ENSETR, 10),
+ CFG_GATE_SETCLR(GATE_FMC, RCC_MP_AHB6ENSETR, 12),
+ CFG_GATE_SETCLR(GATE_QSPI, RCC_MP_AHB6ENSETR, 14),
+ CFG_GATE_SETCLR(GATE_SDMMC1, RCC_MP_AHB6ENSETR, 16),
+ CFG_GATE_SETCLR(GATE_SDMMC2, RCC_MP_AHB6ENSETR, 17),
+ CFG_GATE_SETCLR(GATE_CRC1, RCC_MP_AHB6ENSETR, 20),
+ CFG_GATE_SETCLR(GATE_USBH, RCC_MP_AHB6ENSETR, 24),
+ CFG_GATE_SETCLR(GATE_ETH2CK, RCC_MP_AHB6ENSETR, 27),
+ CFG_GATE_SETCLR(GATE_ETH2TX, RCC_MP_AHB6ENSETR, 28),
+ CFG_GATE_SETCLR(GATE_ETH2RX, RCC_MP_AHB6ENSETR, 29),
+ CFG_GATE_SETCLR(GATE_ETH2MAC, RCC_MP_AHB6ENSETR, 30),
+ CFG_GATE_SETCLR(GATE_ETH1STP, RCC_MP_AHB6LPENSETR, 11),
+ CFG_GATE_SETCLR(GATE_ETH2STP, RCC_MP_AHB6LPENSETR, 31),
+ CFG_GATE_SETCLR(GATE_MDMA, RCC_MP_NS_AHB6ENSETR, 0),
+};
+
+/* STM32 Divivers definition */
+enum enum_div_cfg {
+ DIV_RTC,
+ DIV_HSI,
+ DIV_MCO1,
+ DIV_MCO2,
+ DIV_TRACE,
+ DIV_ETH1PTP,
+ DIV_ETH2PTP,
+ DIV_NB
+};
+
+static const struct clk_div_table ck_trace_div_table[] = {
+ { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 },
+ { 4, 16 }, { 5, 16 }, { 6, 16 }, { 7, 16 },
+ { 0 },
+};
+
+#define CFG_DIV(_id, _offset, _shift, _width, _flags, _table, _ready)\
+ [(_id)] = {\
+ .offset = (_offset),\
+ .shift = (_shift),\
+ .width = (_width),\
+ .flags = (_flags),\
+ .table = (_table),\
+ .ready = (_ready),\
+ }
+
+static const struct stm32_div_cfg stm32mp13_dividers[DIV_NB] = {
+ CFG_DIV(DIV_RTC, RCC_RTCDIVR, 0, 6, 0, NULL, DIV_NO_RDY),
+ CFG_DIV(DIV_MCO1, RCC_MCO1CFGR, 4, 4, 0, NULL, DIV_NO_RDY),
+ CFG_DIV(DIV_MCO2, RCC_MCO2CFGR, 4, 4, 0, NULL, DIV_NO_RDY),
+ CFG_DIV(DIV_TRACE, RCC_DBGCFGR, 0, 3, 0, ck_trace_div_table, DIV_NO_RDY),
+ CFG_DIV(DIV_ETH1PTP, RCC_ETH12CKSELR, 4, 4, 0, NULL, DIV_NO_RDY),
+ CFG_DIV(DIV_ETH2PTP, RCC_ETH12CKSELR, 12, 4, 0, NULL, DIV_NO_RDY),
+};
+
+/* STM32 Muxes definition */
+enum enum_mux_cfg {
+ MUX_ADC1,
+ MUX_ADC2,
+ MUX_DCMIPP,
+ MUX_ETH1,
+ MUX_ETH2,
+ MUX_FDCAN,
+ MUX_FMC,
+ MUX_I2C12,
+ MUX_I2C3,
+ MUX_I2C4,
+ MUX_I2C5,
+ MUX_LPTIM1,
+ MUX_LPTIM2,
+ MUX_LPTIM3,
+ MUX_LPTIM45,
+ MUX_MCO1,
+ MUX_MCO2,
+ MUX_QSPI,
+ MUX_RNG1,
+ MUX_SAES,
+ MUX_SAI1,
+ MUX_SAI2,
+ MUX_SDMMC1,
+ MUX_SDMMC2,
+ MUX_SPDIF,
+ MUX_SPI1,
+ MUX_SPI23,
+ MUX_SPI4,
+ MUX_SPI5,
+ MUX_STGEN,
+ MUX_UART1,
+ MUX_UART2,
+ MUX_UART4,
+ MUX_UART6,
+ MUX_UART35,
+ MUX_UART78,
+ MUX_USBO,
+ MUX_USBPHY,
+ MUX_NB
+};
+
+#define _CFG_MUX(_id, _offset, _shift, _witdh, _ready, _flags)\
+ [_id] = {\
+ .offset = (_offset),\
+ .shift = (_shift),\
+ .width = (_witdh),\
+ .ready = (_ready),\
+ .flags = (_flags),\
+ }
+
+#define CFG_MUX(_id, _offset, _shift, _witdh)\
+ _CFG_MUX(_id, _offset, _shift, _witdh, MUX_NO_RDY, 0)
+
+#define CFG_MUX_SAFE(_id, _offset, _shift, _witdh)\
+ _CFG_MUX(_id, _offset, _shift, _witdh, MUX_NO_RDY, MUX_SAFE)
+
+static const struct stm32_mux_cfg stm32mp13_muxes[] = {
+ CFG_MUX(MUX_I2C12, RCC_I2C12CKSELR, 0, 3),
+ CFG_MUX(MUX_LPTIM45, RCC_LPTIM45CKSELR, 0, 3),
+ CFG_MUX(MUX_SPI23, RCC_SPI2S23CKSELR, 0, 3),
+ CFG_MUX(MUX_UART35, RCC_UART35CKSELR, 0, 3),
+ CFG_MUX(MUX_UART78, RCC_UART78CKSELR, 0, 3),
+ CFG_MUX(MUX_ADC1, RCC_ADC12CKSELR, 0, 2),
+ CFG_MUX(MUX_ADC2, RCC_ADC12CKSELR, 2, 2),
+ CFG_MUX(MUX_DCMIPP, RCC_DCMIPPCKSELR, 0, 2),
+ CFG_MUX(MUX_ETH1, RCC_ETH12CKSELR, 0, 2),
+ CFG_MUX(MUX_ETH2, RCC_ETH12CKSELR, 8, 2),
+ CFG_MUX(MUX_FDCAN, RCC_FDCANCKSELR, 0, 2),
+ CFG_MUX(MUX_I2C3, RCC_I2C345CKSELR, 0, 3),
+ CFG_MUX(MUX_I2C4, RCC_I2C345CKSELR, 3, 3),
+ CFG_MUX(MUX_I2C5, RCC_I2C345CKSELR, 6, 3),
+ CFG_MUX(MUX_LPTIM1, RCC_LPTIM1CKSELR, 0, 3),
+ CFG_MUX(MUX_LPTIM2, RCC_LPTIM23CKSELR, 0, 3),
+ CFG_MUX(MUX_LPTIM3, RCC_LPTIM23CKSELR, 3, 3),
+ CFG_MUX(MUX_MCO1, RCC_MCO1CFGR, 0, 3),
+ CFG_MUX(MUX_MCO2, RCC_MCO2CFGR, 0, 3),
+ CFG_MUX(MUX_RNG1, RCC_RNG1CKSELR, 0, 2),
+ CFG_MUX(MUX_SAES, RCC_SAESCKSELR, 0, 2),
+ CFG_MUX(MUX_SAI1, RCC_SAI1CKSELR, 0, 3),
+ CFG_MUX(MUX_SAI2, RCC_SAI2CKSELR, 0, 3),
+ CFG_MUX(MUX_SPDIF, RCC_SPDIFCKSELR, 0, 2),
+ CFG_MUX(MUX_SPI1, RCC_SPI2S1CKSELR, 0, 3),
+ CFG_MUX(MUX_SPI4, RCC_SPI45CKSELR, 0, 3),
+ CFG_MUX(MUX_SPI5, RCC_SPI45CKSELR, 3, 3),
+ CFG_MUX(MUX_STGEN, RCC_STGENCKSELR, 0, 2),
+ CFG_MUX(MUX_UART1, RCC_UART12CKSELR, 0, 3),
+ CFG_MUX(MUX_UART2, RCC_UART12CKSELR, 3, 3),
+ CFG_MUX(MUX_UART4, RCC_UART4CKSELR, 0, 3),
+ CFG_MUX(MUX_UART6, RCC_UART6CKSELR, 0, 3),
+ CFG_MUX(MUX_USBO, RCC_USBCKSELR, 4, 1),
+ CFG_MUX(MUX_USBPHY, RCC_USBCKSELR, 0, 2),
+ CFG_MUX_SAFE(MUX_FMC, RCC_FMCCKSELR, 0, 2),
+ CFG_MUX_SAFE(MUX_QSPI, RCC_QSPICKSELR, 0, 2),
+ CFG_MUX_SAFE(MUX_SDMMC1, RCC_SDMMC12CKSELR, 0, 3),
+ CFG_MUX_SAFE(MUX_SDMMC2, RCC_SDMMC12CKSELR, 3, 3),
+};
+
+struct clk_stm32_securiy {
+ u32 offset;
+ u8 bit_idx;
+ unsigned long scmi_id;
+};
+
+enum security_clk {
+ SECF_NONE,
+ SECF_LPTIM2,
+ SECF_LPTIM3,
+ SECF_VREF,
+ SECF_DCMIPP,
+ SECF_USBPHY,
+ SECF_TZC,
+ SECF_ETZPC,
+ SECF_IWDG1,
+ SECF_BSEC,
+ SECF_STGENC,
+ SECF_STGENRO,
+ SECF_USART1,
+ SECF_USART2,
+ SECF_SPI4,
+ SECF_SPI5,
+ SECF_I2C3,
+ SECF_I2C4,
+ SECF_I2C5,
+ SECF_TIM12,
+ SECF_TIM13,
+ SECF_TIM14,
+ SECF_TIM15,
+ SECF_TIM16,
+ SECF_TIM17,
+ SECF_DMA3,
+ SECF_DMAMUX2,
+ SECF_ADC1,
+ SECF_ADC2,
+ SECF_USBO,
+ SECF_TSC,
+ SECF_PKA,
+ SECF_SAES,
+ SECF_CRYP1,
+ SECF_HASH1,
+ SECF_RNG1,
+ SECF_BKPSRAM,
+ SECF_MCE,
+ SECF_FMC,
+ SECF_QSPI,
+ SECF_SDMMC1,
+ SECF_SDMMC2,
+ SECF_ETH1CK,
+ SECF_ETH1TX,
+ SECF_ETH1RX,
+ SECF_ETH1MAC,
+ SECF_ETH1STP,
+ SECF_ETH2CK,
+ SECF_ETH2TX,
+ SECF_ETH2RX,
+ SECF_ETH2MAC,
+ SECF_ETH2STP,
+ SECF_MCO1,
+ SECF_MCO2
+};
+
+#define SECF(_sec_id, _offset, _bit_idx)[_sec_id] = {\
+ .offset = _offset,\
+ .bit_idx = _bit_idx,\
+ .scmi_id = -1,\
+}
+
+static const struct clk_stm32_securiy stm32mp13_security[] = {
+ SECF(SECF_LPTIM2, RCC_APB3SECSR, RCC_APB3SECSR_LPTIM2SECF),
+ SECF(SECF_LPTIM3, RCC_APB3SECSR, RCC_APB3SECSR_LPTIM3SECF),
+ SECF(SECF_VREF, RCC_APB3SECSR, RCC_APB3SECSR_VREFSECF),
+ SECF(SECF_DCMIPP, RCC_APB4SECSR, RCC_APB4SECSR_DCMIPPSECF),
+ SECF(SECF_USBPHY, RCC_APB4SECSR, RCC_APB4SECSR_USBPHYSECF),
+ SECF(SECF_TZC, RCC_APB5SECSR, RCC_APB5SECSR_TZCSECF),
+ SECF(SECF_ETZPC, RCC_APB5SECSR, RCC_APB5SECSR_ETZPCSECF),
+ SECF(SECF_IWDG1, RCC_APB5SECSR, RCC_APB5SECSR_IWDG1SECF),
+ SECF(SECF_BSEC, RCC_APB5SECSR, RCC_APB5SECSR_BSECSECF),
+ SECF(SECF_STGENC, RCC_APB5SECSR, RCC_APB5SECSR_STGENCSECF),
+ SECF(SECF_STGENRO, RCC_APB5SECSR, RCC_APB5SECSR_STGENROSECF),
+ SECF(SECF_USART1, RCC_APB6SECSR, RCC_APB6SECSR_USART1SECF),
+ SECF(SECF_USART2, RCC_APB6SECSR, RCC_APB6SECSR_USART2SECF),
+ SECF(SECF_SPI4, RCC_APB6SECSR, RCC_APB6SECSR_SPI4SECF),
+ SECF(SECF_SPI5, RCC_APB6SECSR, RCC_APB6SECSR_SPI5SECF),
+ SECF(SECF_I2C3, RCC_APB6SECSR, RCC_APB6SECSR_I2C3SECF),
+ SECF(SECF_I2C4, RCC_APB6SECSR, RCC_APB6SECSR_I2C4SECF),
+ SECF(SECF_I2C5, RCC_APB6SECSR, RCC_APB6SECSR_I2C5SECF),
+ SECF(SECF_TIM12, RCC_APB6SECSR, RCC_APB6SECSR_TIM12SECF),
+ SECF(SECF_TIM13, RCC_APB6SECSR, RCC_APB6SECSR_TIM13SECF),
+ SECF(SECF_TIM14, RCC_APB6SECSR, RCC_APB6SECSR_TIM14SECF),
+ SECF(SECF_TIM15, RCC_APB6SECSR, RCC_APB6SECSR_TIM15SECF),
+ SECF(SECF_TIM16, RCC_APB6SECSR, RCC_APB6SECSR_TIM16SECF),
+ SECF(SECF_TIM17, RCC_APB6SECSR, RCC_APB6SECSR_TIM17SECF),
+ SECF(SECF_DMA3, RCC_AHB2SECSR, RCC_AHB2SECSR_DMA3SECF),
+ SECF(SECF_DMAMUX2, RCC_AHB2SECSR, RCC_AHB2SECSR_DMAMUX2SECF),
+ SECF(SECF_ADC1, RCC_AHB2SECSR, RCC_AHB2SECSR_ADC1SECF),
+ SECF(SECF_ADC2, RCC_AHB2SECSR, RCC_AHB2SECSR_ADC2SECF),
+ SECF(SECF_USBO, RCC_AHB2SECSR, RCC_AHB2SECSR_USBOSECF),
+ SECF(SECF_TSC, RCC_AHB4SECSR, RCC_AHB4SECSR_TSCSECF),
+ SECF(SECF_PKA, RCC_AHB5SECSR, RCC_AHB5SECSR_PKASECF),
+ SECF(SECF_SAES, RCC_AHB5SECSR, RCC_AHB5SECSR_SAESSECF),
+ SECF(SECF_CRYP1, RCC_AHB5SECSR, RCC_AHB5SECSR_CRYP1SECF),
+ SECF(SECF_HASH1, RCC_AHB5SECSR, RCC_AHB5SECSR_HASH1SECF),
+ SECF(SECF_RNG1, RCC_AHB5SECSR, RCC_AHB5SECSR_RNG1SECF),
+ SECF(SECF_BKPSRAM, RCC_AHB5SECSR, RCC_AHB5SECSR_BKPSRAMSECF),
+ SECF(SECF_MCE, RCC_AHB6SECSR, RCC_AHB6SECSR_MCESECF),
+ SECF(SECF_FMC, RCC_AHB6SECSR, RCC_AHB6SECSR_FMCSECF),
+ SECF(SECF_QSPI, RCC_AHB6SECSR, RCC_AHB6SECSR_QSPISECF),
+ SECF(SECF_SDMMC1, RCC_AHB6SECSR, RCC_AHB6SECSR_SDMMC1SECF),
+ SECF(SECF_SDMMC2, RCC_AHB6SECSR, RCC_AHB6SECSR_SDMMC2SECF),
+ SECF(SECF_ETH1CK, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH1CKSECF),
+ SECF(SECF_ETH1TX, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH1TXSECF),
+ SECF(SECF_ETH1RX, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH1RXSECF),
+ SECF(SECF_ETH1MAC, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH1MACSECF),
+ SECF(SECF_ETH1STP, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH1STPSECF),
+ SECF(SECF_ETH2CK, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH2CKSECF),
+ SECF(SECF_ETH2TX, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH2TXSECF),
+ SECF(SECF_ETH2RX, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH2RXSECF),
+ SECF(SECF_ETH2MAC, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH2MACSECF),
+ SECF(SECF_ETH2STP, RCC_AHB6SECSR, RCC_AHB6SECSR_ETH2STPSECF),
+ SECF(SECF_MCO1, RCC_SECCFGR, RCC_SECCFGR_MCO1SEC),
+ SECF(SECF_MCO2, RCC_SECCFGR, RCC_SECCFGR_MCO2SEC),
+};
+
+static const char * const adc12_src[] = {
+ "pll4_r", "ck_per", "pll3_q"
+};
+
+static const char * const dcmipp_src[] = {
+ "ck_axi", "pll2_q", "pll4_p", "ck_per",
+};
+
+static const char * const eth12_src[] = {
+ "pll4_p", "pll3_q"
+};
+
+static const char * const fdcan_src[] = {
+ "ck_hse", "pll3_q", "pll4_q", "pll4_r"
+};
+
+static const char * const fmc_src[] = {
+ "ck_axi", "pll3_r", "pll4_p", "ck_per"
+};
+
+static const char * const i2c12_src[] = {
+ "pclk1", "pll4_r", "ck_hsi", "ck_csi"
+};
+
+static const char * const i2c345_src[] = {
+ "pclk6", "pll4_r", "ck_hsi", "ck_csi"
+};
+
+static const char * const lptim1_src[] = {
+ "pclk1", "pll4_p", "pll3_q", "ck_lse", "ck_lsi", "ck_per"
+};
+
+static const char * const lptim23_src[] = {
+ "pclk3", "pll4_q", "ck_per", "ck_lse", "ck_lsi"
+};
+
+static const char * const lptim45_src[] = {
+ "pclk3", "pll4_p", "pll3_q", "ck_lse", "ck_lsi", "ck_per"
+};
+
+static const char * const mco1_src[] = {
+ "ck_hsi", "ck_hse", "ck_csi", "ck_lsi", "ck_lse"
+};
+
+static const char * const mco2_src[] = {
+ "ck_mpu", "ck_axi", "ck_mlahb", "pll4_p", "ck_hse", "ck_hsi"
+};
+
+static const char * const qspi_src[] = {
+ "ck_axi", "pll3_r", "pll4_p", "ck_per"
+};
+
+static const char * const rng1_src[] = {
+ "ck_csi", "pll4_r", "ck_lse", "ck_lsi"
+};
+
+static const char * const saes_src[] = {
+ "ck_axi", "ck_per", "pll4_r", "ck_lsi"
+};
+
+static const char * const sai1_src[] = {
+ "pll4_q", "pll3_q", "i2s_ckin", "ck_per", "pll3_r"
+};
+
+static const char * const sai2_src[] = {
+ "pll4_q", "pll3_q", "i2s_ckin", "ck_per", "spdif_ck_symb", "pll3_r"
+};
+
+static const char * const sdmmc12_src[] = {
+ "ck_axi", "pll3_r", "pll4_p", "ck_hsi"
+};
+
+static const char * const spdif_src[] = {
+ "pll4_p", "pll3_q", "ck_hsi"
+};
+
+static const char * const spi123_src[] = {
+ "pll4_p", "pll3_q", "i2s_ckin", "ck_per", "pll3_r"
+};
+
+static const char * const spi4_src[] = {
+ "pclk6", "pll4_q", "ck_hsi", "ck_csi", "ck_hse", "i2s_ckin"
+};
+
+static const char * const spi5_src[] = {
+ "pclk6", "pll4_q", "ck_hsi", "ck_csi", "ck_hse"
+};
+
+static const char * const stgen_src[] = {
+ "ck_hsi", "ck_hse"
+};
+
+static const char * const usart12_src[] = {
+ "pclk6", "pll3_q", "ck_hsi", "ck_csi", "pll4_q", "ck_hse"
+};
+
+static const char * const usart34578_src[] = {
+ "pclk1", "pll4_q", "ck_hsi", "ck_csi", "ck_hse"
+};
+
+static const char * const usart6_src[] = {
+ "pclk2", "pll4_q", "ck_hsi", "ck_csi", "ck_hse"
+};
+
+static const char * const usbo_src[] = {
+ "pll4_r", "ck_usbo_48m"
+};
+
+static const char * const usbphy_src[] = {
+ "ck_hse", "pll4_r", "clk-hse-div2"
+};
+
+/* Timer clocks */
+static struct clk_stm32_gate tim2_k = {
+ .gate_id = GATE_TIM2,
+ .hw.init = CLK_HW_INIT("tim2_k", "timg1_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT),
+};
+
+static struct clk_stm32_gate tim3_k = {
+ .gate_id = GATE_TIM3,
+ .hw.init = CLK_HW_INIT("tim3_k", "timg1_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT),
+};
+
+static struct clk_stm32_gate tim4_k = {
+ .gate_id = GATE_TIM4,
+ .hw.init = CLK_HW_INIT("tim4_k", "timg1_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT),
+};
+
+static struct clk_stm32_gate tim5_k = {
+ .gate_id = GATE_TIM5,
+ .hw.init = CLK_HW_INIT("tim5_k", "timg1_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT),
+};
+
+static struct clk_stm32_gate tim6_k = {
+ .gate_id = GATE_TIM6,
+ .hw.init = CLK_HW_INIT("tim6_k", "timg1_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT),
+};
+
+static struct clk_stm32_gate tim7_k = {
+ .gate_id = GATE_TIM7,
+ .hw.init = CLK_HW_INIT("tim7_k", "timg1_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT),
+};
+
+static struct clk_stm32_gate tim1_k = {
+ .gate_id = GATE_TIM1,
+ .hw.init = CLK_HW_INIT("tim1_k", "timg2_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT),
+};
+
+static struct clk_stm32_gate tim8_k = {
+ .gate_id = GATE_TIM8,
+ .hw.init = CLK_HW_INIT("tim8_k", "timg2_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT),
+};
+
+static struct clk_stm32_gate tim12_k = {
+ .gate_id = GATE_TIM12,
+ .hw.init = CLK_HW_INIT("tim12_k", "timg3_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT),
+};
+
+static struct clk_stm32_gate tim13_k = {
+ .gate_id = GATE_TIM13,
+ .hw.init = CLK_HW_INIT("tim13_k", "timg3_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT),
+};
+
+static struct clk_stm32_gate tim14_k = {
+ .gate_id = GATE_TIM14,
+ .hw.init = CLK_HW_INIT("tim14_k", "timg3_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT),
+};
+
+static struct clk_stm32_gate tim15_k = {
+ .gate_id = GATE_TIM15,
+ .hw.init = CLK_HW_INIT("tim15_k", "timg3_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT),
+};
+
+static struct clk_stm32_gate tim16_k = {
+ .gate_id = GATE_TIM16,
+ .hw.init = CLK_HW_INIT("tim16_k", "timg3_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT),
+};
+
+static struct clk_stm32_gate tim17_k = {
+ .gate_id = GATE_TIM17,
+ .hw.init = CLK_HW_INIT("tim17_k", "timg3_ck", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT),
+};
+
+/* Peripheral clocks */
+static struct clk_stm32_gate sai1 = {
+ .gate_id = GATE_SAI1,
+ .hw.init = CLK_HW_INIT("sai1", "pclk2", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate sai2 = {
+ .gate_id = GATE_SAI2,
+ .hw.init = CLK_HW_INIT("sai2", "pclk2", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate syscfg = {
+ .gate_id = GATE_SYSCFG,
+ .hw.init = CLK_HW_INIT("syscfg", "pclk3", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate vref = {
+ .gate_id = GATE_VREF,
+ .hw.init = CLK_HW_INIT("vref", "pclk3", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate dts = {
+ .gate_id = GATE_DTS,
+ .hw.init = CLK_HW_INIT("dts", "pclk3", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate pmbctrl = {
+ .gate_id = GATE_PMBCTRL,
+ .hw.init = CLK_HW_INIT("pmbctrl", "pclk3", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate hdp = {
+ .gate_id = GATE_HDP,
+ .hw.init = CLK_HW_INIT("hdp", "pclk3", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate iwdg2 = {
+ .gate_id = GATE_IWDG2APB,
+ .hw.init = CLK_HW_INIT("iwdg2", "pclk4", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate stgenro = {
+ .gate_id = GATE_STGENRO,
+ .hw.init = CLK_HW_INIT("stgenro", "pclk4", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate gpioa = {
+ .gate_id = GATE_GPIOA,
+ .hw.init = CLK_HW_INIT("gpioa", "pclk4", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate gpiob = {
+ .gate_id = GATE_GPIOB,
+ .hw.init = CLK_HW_INIT("gpiob", "pclk4", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate gpioc = {
+ .gate_id = GATE_GPIOC,
+ .hw.init = CLK_HW_INIT("gpioc", "pclk4", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate gpiod = {
+ .gate_id = GATE_GPIOD,
+ .hw.init = CLK_HW_INIT("gpiod", "pclk4", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate gpioe = {
+ .gate_id = GATE_GPIOE,
+ .hw.init = CLK_HW_INIT("gpioe", "pclk4", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate gpiof = {
+ .gate_id = GATE_GPIOF,
+ .hw.init = CLK_HW_INIT("gpiof", "pclk4", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate gpiog = {
+ .gate_id = GATE_GPIOG,
+ .hw.init = CLK_HW_INIT("gpiog", "pclk4", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate gpioh = {
+ .gate_id = GATE_GPIOH,
+ .hw.init = CLK_HW_INIT("gpioh", "pclk4", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate gpioi = {
+ .gate_id = GATE_GPIOI,
+ .hw.init = CLK_HW_INIT("gpioi", "pclk4", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate tsc = {
+ .gate_id = GATE_TSC,
+ .hw.init = CLK_HW_INIT("tsc", "pclk4", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate ddrperfm = {
+ .gate_id = GATE_DDRPERFM,
+ .hw.init = CLK_HW_INIT("ddrperfm", "pclk4", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate tzpc = {
+ .gate_id = GATE_TZC,
+ .hw.init = CLK_HW_INIT("tzpc", "pclk5", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate iwdg1 = {
+ .gate_id = GATE_IWDG1APB,
+ .hw.init = CLK_HW_INIT("iwdg1", "pclk5", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate bsec = {
+ .gate_id = GATE_BSEC,
+ .hw.init = CLK_HW_INIT("bsec", "pclk5", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate dma1 = {
+ .gate_id = GATE_DMA1,
+ .hw.init = CLK_HW_INIT("dma1", "ck_mlahb", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate dma2 = {
+ .gate_id = GATE_DMA2,
+ .hw.init = CLK_HW_INIT("dma2", "ck_mlahb", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate dmamux1 = {
+ .gate_id = GATE_DMAMUX1,
+ .hw.init = CLK_HW_INIT("dmamux1", "ck_mlahb", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate dma3 = {
+ .gate_id = GATE_DMA3,
+ .hw.init = CLK_HW_INIT("dma3", "ck_mlahb", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate dmamux2 = {
+ .gate_id = GATE_DMAMUX2,
+ .hw.init = CLK_HW_INIT("dmamux2", "ck_mlahb", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate adc1 = {
+ .gate_id = GATE_ADC1,
+ .hw.init = CLK_HW_INIT("adc1", "ck_mlahb", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate adc2 = {
+ .gate_id = GATE_ADC2,
+ .hw.init = CLK_HW_INIT("adc2", "ck_mlahb", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate pka = {
+ .gate_id = GATE_PKA,
+ .hw.init = CLK_HW_INIT("pka", "ck_axi", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate cryp1 = {
+ .gate_id = GATE_CRYP1,
+ .hw.init = CLK_HW_INIT("cryp1", "ck_axi", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate hash1 = {
+ .gate_id = GATE_HASH1,
+ .hw.init = CLK_HW_INIT("hash1", "ck_axi", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate bkpsram = {
+ .gate_id = GATE_BKPSRAM,
+ .hw.init = CLK_HW_INIT("bkpsram", "ck_axi", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate mdma = {
+ .gate_id = GATE_MDMA,
+ .hw.init = CLK_HW_INIT("mdma", "ck_axi", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate eth1tx = {
+ .gate_id = GATE_ETH1TX,
+ .hw.init = CLK_HW_INIT("eth1tx", "ck_axi", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate eth1rx = {
+ .gate_id = GATE_ETH1RX,
+ .hw.init = CLK_HW_INIT("eth1rx", "ck_axi", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate eth1mac = {
+ .gate_id = GATE_ETH1MAC,
+ .hw.init = CLK_HW_INIT("eth1mac", "ck_axi", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate eth2tx = {
+ .gate_id = GATE_ETH2TX,
+ .hw.init = CLK_HW_INIT("eth2tx", "ck_axi", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate eth2rx = {
+ .gate_id = GATE_ETH2RX,
+ .hw.init = CLK_HW_INIT("eth2rx", "ck_axi", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate eth2mac = {
+ .gate_id = GATE_ETH2MAC,
+ .hw.init = CLK_HW_INIT("eth2mac", "ck_axi", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate crc1 = {
+ .gate_id = GATE_CRC1,
+ .hw.init = CLK_HW_INIT("crc1", "ck_axi", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate usbh = {
+ .gate_id = GATE_USBH,
+ .hw.init = CLK_HW_INIT("usbh", "ck_axi", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate eth1stp = {
+ .gate_id = GATE_ETH1STP,
+ .hw.init = CLK_HW_INIT("eth1stp", "ck_axi", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate eth2stp = {
+ .gate_id = GATE_ETH2STP,
+ .hw.init = CLK_HW_INIT("eth2stp", "ck_axi", &clk_stm32_gate_ops, 0),
+};
+
+/* Kernel clocks */
+static struct clk_stm32_composite sdmmc1_k = {
+ .gate_id = GATE_SDMMC1,
+ .mux_id = MUX_SDMMC1,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("sdmmc1_k", sdmmc12_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite sdmmc2_k = {
+ .gate_id = GATE_SDMMC2,
+ .mux_id = MUX_SDMMC2,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("sdmmc2_k", sdmmc12_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite fmc_k = {
+ .gate_id = GATE_FMC,
+ .mux_id = MUX_FMC,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("fmc_k", fmc_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite qspi_k = {
+ .gate_id = GATE_QSPI,
+ .mux_id = MUX_QSPI,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("qspi_k", qspi_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite spi2_k = {
+ .gate_id = GATE_SPI2,
+ .mux_id = MUX_SPI23,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("spi2_k", spi123_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite spi3_k = {
+ .gate_id = GATE_SPI3,
+ .mux_id = MUX_SPI23,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("spi3_k", spi123_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite i2c1_k = {
+ .gate_id = GATE_I2C1,
+ .mux_id = MUX_I2C12,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("i2c1_k", i2c12_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite i2c2_k = {
+ .gate_id = GATE_I2C2,
+ .mux_id = MUX_I2C12,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("i2c2_k", i2c12_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite lptim4_k = {
+ .gate_id = GATE_LPTIM4,
+ .mux_id = MUX_LPTIM45,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("lptim4_k", lptim45_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite lptim5_k = {
+ .gate_id = GATE_LPTIM5,
+ .mux_id = MUX_LPTIM45,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("lptim5_k", lptim45_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite usart3_k = {
+ .gate_id = GATE_USART3,
+ .mux_id = MUX_UART35,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("usart3_k", usart34578_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite uart5_k = {
+ .gate_id = GATE_UART5,
+ .mux_id = MUX_UART35,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("uart5_k", usart34578_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite uart7_k = {
+ .gate_id = GATE_UART7,
+ .mux_id = MUX_UART78,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("uart7_k", usart34578_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite uart8_k = {
+ .gate_id = GATE_UART8,
+ .mux_id = MUX_UART78,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("uart8_k", usart34578_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite sai1_k = {
+ .gate_id = GATE_SAI1,
+ .mux_id = MUX_SAI1,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("sai1_k", sai1_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite adfsdm_k = {
+ .gate_id = GATE_ADFSDM,
+ .mux_id = MUX_SAI1,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("adfsdm_k", sai1_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite sai2_k = {
+ .gate_id = GATE_SAI2,
+ .mux_id = MUX_SAI2,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("sai2_k", sai2_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite adc1_k = {
+ .gate_id = GATE_ADC1,
+ .mux_id = MUX_ADC1,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("adc1_k", adc12_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite adc2_k = {
+ .gate_id = GATE_ADC2,
+ .mux_id = MUX_ADC2,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("adc2_k", adc12_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite rng1_k = {
+ .gate_id = GATE_RNG1,
+ .mux_id = MUX_RNG1,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("rng1_k", rng1_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite usbphy_k = {
+ .gate_id = GATE_USBPHY,
+ .mux_id = MUX_USBPHY,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("usbphy_k", usbphy_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite stgen_k = {
+ .gate_id = GATE_STGENC,
+ .mux_id = MUX_STGEN,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("stgen_k", stgen_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite spdif_k = {
+ .gate_id = GATE_SPDIF,
+ .mux_id = MUX_SPDIF,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("spdif_k", spdif_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite spi1_k = {
+ .gate_id = GATE_SPI1,
+ .mux_id = MUX_SPI1,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("spi1_k", spi123_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite spi4_k = {
+ .gate_id = GATE_SPI4,
+ .mux_id = MUX_SPI4,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("spi4_k", spi4_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite spi5_k = {
+ .gate_id = GATE_SPI5,
+ .mux_id = MUX_SPI5,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("spi5_k", spi5_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite i2c3_k = {
+ .gate_id = GATE_I2C3,
+ .mux_id = MUX_I2C3,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("i2c3_k", i2c345_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite i2c4_k = {
+ .gate_id = GATE_I2C4,
+ .mux_id = MUX_I2C4,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("i2c4_k", i2c345_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite i2c5_k = {
+ .gate_id = GATE_I2C5,
+ .mux_id = MUX_I2C5,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("i2c5_k", i2c345_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite lptim1_k = {
+ .gate_id = GATE_LPTIM1,
+ .mux_id = MUX_LPTIM1,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("lptim1_k", lptim1_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite lptim2_k = {
+ .gate_id = GATE_LPTIM2,
+ .mux_id = MUX_LPTIM2,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("lptim2_k", lptim23_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite lptim3_k = {
+ .gate_id = GATE_LPTIM3,
+ .mux_id = MUX_LPTIM3,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("lptim3_k", lptim23_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite usart1_k = {
+ .gate_id = GATE_USART1,
+ .mux_id = MUX_UART1,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("usart1_k", usart12_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite usart2_k = {
+ .gate_id = GATE_USART2,
+ .mux_id = MUX_UART2,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("usart2_k", usart12_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite uart4_k = {
+ .gate_id = GATE_UART4,
+ .mux_id = MUX_UART4,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("uart4_k", usart34578_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite uart6_k = {
+ .gate_id = GATE_USART6,
+ .mux_id = MUX_UART6,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("uart6_k", usart6_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite fdcan_k = {
+ .gate_id = GATE_FDCAN,
+ .mux_id = MUX_FDCAN,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("fdcan_k", fdcan_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite dcmipp_k = {
+ .gate_id = GATE_DCMIPP,
+ .mux_id = MUX_DCMIPP,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("dcmipp_k", dcmipp_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite usbo_k = {
+ .gate_id = GATE_USBO,
+ .mux_id = MUX_USBO,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("usbo_k", usbo_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite saes_k = {
+ .gate_id = GATE_SAES,
+ .mux_id = MUX_SAES,
+ .div_id = NO_STM32_DIV,
+ .hw.init = CLK_HW_INIT_PARENTS("saes_k", saes_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_gate dfsdm_k = {
+ .gate_id = GATE_DFSDM,
+ .hw.init = CLK_HW_INIT("dfsdm_k", "ck_mlahb", &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_gate ltdc_px = {
+ .gate_id = GATE_LTDC,
+ .hw.init = CLK_HW_INIT("ltdc_px", "pll4_q", &clk_stm32_gate_ops, CLK_SET_RATE_PARENT),
+};
+
+static struct clk_stm32_mux ck_ker_eth1 = {
+ .mux_id = MUX_ETH1,
+ .hw.init = CLK_HW_INIT_PARENTS("ck_ker_eth1", eth12_src, &clk_stm32_mux_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_gate eth1ck_k = {
+ .gate_id = GATE_ETH1CK,
+ .hw.init = CLK_HW_INIT_HW("eth1ck_k", &ck_ker_eth1.hw, &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_div eth1ptp_k = {
+ .div_id = DIV_ETH1PTP,
+ .hw.init = CLK_HW_INIT_HW("eth1ptp_k", &ck_ker_eth1.hw, &clk_stm32_divider_ops,
+ CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_mux ck_ker_eth2 = {
+ .mux_id = MUX_ETH2,
+ .hw.init = CLK_HW_INIT_PARENTS("ck_ker_eth2", eth12_src, &clk_stm32_mux_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_gate eth2ck_k = {
+ .gate_id = GATE_ETH2CK,
+ .hw.init = CLK_HW_INIT_HW("eth2ck_k", &ck_ker_eth2.hw, &clk_stm32_gate_ops, 0),
+};
+
+static struct clk_stm32_div eth2ptp_k = {
+ .div_id = DIV_ETH2PTP,
+ .hw.init = CLK_HW_INIT_HW("eth2ptp_k", &ck_ker_eth2.hw, &clk_stm32_divider_ops,
+ CLK_SET_RATE_NO_REPARENT),
+};
+
+static struct clk_stm32_composite ck_mco1 = {
+ .gate_id = GATE_MCO1,
+ .mux_id = MUX_MCO1,
+ .div_id = DIV_MCO1,
+ .hw.init = CLK_HW_INIT_PARENTS("ck_mco1", mco1_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT |
+ CLK_IGNORE_UNUSED),
+};
+
+static struct clk_stm32_composite ck_mco2 = {
+ .gate_id = GATE_MCO2,
+ .mux_id = MUX_MCO2,
+ .div_id = DIV_MCO2,
+ .hw.init = CLK_HW_INIT_PARENTS("ck_mco2", mco2_src, &clk_stm32_composite_ops,
+ CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT |
+ CLK_IGNORE_UNUSED),
+};
+
+/* Debug clocks */
+static struct clk_stm32_gate ck_sys_dbg = {
+ .gate_id = GATE_DBGCK,
+ .hw.init = CLK_HW_INIT("ck_sys_dbg", "ck_axi", &clk_stm32_gate_ops, CLK_IS_CRITICAL),
+};
+
+static struct clk_stm32_composite ck_trace = {
+ .gate_id = GATE_TRACECK,
+ .mux_id = NO_STM32_MUX,
+ .div_id = DIV_TRACE,
+ .hw.init = CLK_HW_INIT("ck_trace", "ck_axi", &clk_stm32_composite_ops, CLK_IGNORE_UNUSED),
+};
+
+static const struct clock_config stm32mp13_clock_cfg[] = {
+ /* Timer clocks */
+ STM32_GATE_CFG(TIM2_K, tim2_k, SECF_NONE),
+ STM32_GATE_CFG(TIM3_K, tim3_k, SECF_NONE),
+ STM32_GATE_CFG(TIM4_K, tim4_k, SECF_NONE),
+ STM32_GATE_CFG(TIM5_K, tim5_k, SECF_NONE),
+ STM32_GATE_CFG(TIM6_K, tim6_k, SECF_NONE),
+ STM32_GATE_CFG(TIM7_K, tim7_k, SECF_NONE),
+ STM32_GATE_CFG(TIM1_K, tim1_k, SECF_NONE),
+ STM32_GATE_CFG(TIM8_K, tim8_k, SECF_NONE),
+ STM32_GATE_CFG(TIM12_K, tim12_k, SECF_TIM12),
+ STM32_GATE_CFG(TIM13_K, tim13_k, SECF_TIM13),
+ STM32_GATE_CFG(TIM14_K, tim14_k, SECF_TIM14),
+ STM32_GATE_CFG(TIM15_K, tim15_k, SECF_TIM15),
+ STM32_GATE_CFG(TIM16_K, tim16_k, SECF_TIM16),
+ STM32_GATE_CFG(TIM17_K, tim17_k, SECF_TIM17),
+
+ /* Peripheral clocks */
+ STM32_GATE_CFG(SAI1, sai1, SECF_NONE),
+ STM32_GATE_CFG(SAI2, sai2, SECF_NONE),
+ STM32_GATE_CFG(SYSCFG, syscfg, SECF_NONE),
+ STM32_GATE_CFG(VREF, vref, SECF_VREF),
+ STM32_GATE_CFG(DTS, dts, SECF_NONE),
+ STM32_GATE_CFG(PMBCTRL, pmbctrl, SECF_NONE),
+ STM32_GATE_CFG(HDP, hdp, SECF_NONE),
+ STM32_GATE_CFG(IWDG2, iwdg2, SECF_NONE),
+ STM32_GATE_CFG(STGENRO, stgenro, SECF_STGENRO),
+ STM32_GATE_CFG(TZPC, tzpc, SECF_TZC),
+ STM32_GATE_CFG(IWDG1, iwdg1, SECF_IWDG1),
+ STM32_GATE_CFG(BSEC, bsec, SECF_BSEC),
+ STM32_GATE_CFG(DMA1, dma1, SECF_NONE),
+ STM32_GATE_CFG(DMA2, dma2, SECF_NONE),
+ STM32_GATE_CFG(DMAMUX1, dmamux1, SECF_NONE),
+ STM32_GATE_CFG(DMA3, dma3, SECF_DMA3),
+ STM32_GATE_CFG(DMAMUX2, dmamux2, SECF_DMAMUX2),
+ STM32_GATE_CFG(ADC1, adc1, SECF_ADC1),
+ STM32_GATE_CFG(ADC2, adc2, SECF_ADC2),
+ STM32_GATE_CFG(GPIOA, gpioa, SECF_NONE),
+ STM32_GATE_CFG(GPIOB, gpiob, SECF_NONE),
+ STM32_GATE_CFG(GPIOC, gpioc, SECF_NONE),
+ STM32_GATE_CFG(GPIOD, gpiod, SECF_NONE),
+ STM32_GATE_CFG(GPIOE, gpioe, SECF_NONE),
+ STM32_GATE_CFG(GPIOF, gpiof, SECF_NONE),
+ STM32_GATE_CFG(GPIOG, gpiog, SECF_NONE),
+ STM32_GATE_CFG(GPIOH, gpioh, SECF_NONE),
+ STM32_GATE_CFG(GPIOI, gpioi, SECF_NONE),
+ STM32_GATE_CFG(TSC, tsc, SECF_TZC),
+ STM32_GATE_CFG(PKA, pka, SECF_PKA),
+ STM32_GATE_CFG(CRYP1, cryp1, SECF_CRYP1),
+ STM32_GATE_CFG(HASH1, hash1, SECF_HASH1),
+ STM32_GATE_CFG(BKPSRAM, bkpsram, SECF_BKPSRAM),
+ STM32_GATE_CFG(MDMA, mdma, SECF_NONE),
+ STM32_GATE_CFG(ETH1TX, eth1tx, SECF_ETH1TX),
+ STM32_GATE_CFG(ETH1RX, eth1rx, SECF_ETH1RX),
+ STM32_GATE_CFG(ETH1MAC, eth1mac, SECF_ETH1MAC),
+ STM32_GATE_CFG(ETH2TX, eth2tx, SECF_ETH2TX),
+ STM32_GATE_CFG(ETH2RX, eth2rx, SECF_ETH2RX),
+ STM32_GATE_CFG(ETH2MAC, eth2mac, SECF_ETH2MAC),
+ STM32_GATE_CFG(CRC1, crc1, SECF_NONE),
+ STM32_GATE_CFG(USBH, usbh, SECF_NONE),
+ STM32_GATE_CFG(DDRPERFM, ddrperfm, SECF_NONE),
+ STM32_GATE_CFG(ETH1STP, eth1stp, SECF_ETH1STP),
+ STM32_GATE_CFG(ETH2STP, eth2stp, SECF_ETH2STP),
+
+ /* Kernel clocks */
+ STM32_COMPOSITE_CFG(SDMMC1_K, sdmmc1_k, SECF_SDMMC1),
+ STM32_COMPOSITE_CFG(SDMMC2_K, sdmmc2_k, SECF_SDMMC2),
+ STM32_COMPOSITE_CFG(FMC_K, fmc_k, SECF_FMC),
+ STM32_COMPOSITE_CFG(QSPI_K, qspi_k, SECF_QSPI),
+ STM32_COMPOSITE_CFG(SPI2_K, spi2_k, SECF_NONE),
+ STM32_COMPOSITE_CFG(SPI3_K, spi3_k, SECF_NONE),
+ STM32_COMPOSITE_CFG(I2C1_K, i2c1_k, SECF_NONE),
+ STM32_COMPOSITE_CFG(I2C2_K, i2c2_k, SECF_NONE),
+ STM32_COMPOSITE_CFG(LPTIM4_K, lptim4_k, SECF_NONE),
+ STM32_COMPOSITE_CFG(LPTIM5_K, lptim5_k, SECF_NONE),
+ STM32_COMPOSITE_CFG(USART3_K, usart3_k, SECF_NONE),
+ STM32_COMPOSITE_CFG(UART5_K, uart5_k, SECF_NONE),
+ STM32_COMPOSITE_CFG(UART7_K, uart7_k, SECF_NONE),
+ STM32_COMPOSITE_CFG(UART8_K, uart8_k, SECF_NONE),
+ STM32_COMPOSITE_CFG(SAI1_K, sai1_k, SECF_NONE),
+ STM32_COMPOSITE_CFG(SAI2_K, sai2_k, SECF_NONE),
+ STM32_COMPOSITE_CFG(ADFSDM_K, adfsdm_k, SECF_NONE),
+ STM32_COMPOSITE_CFG(ADC1_K, adc1_k, SECF_ADC1),
+ STM32_COMPOSITE_CFG(ADC2_K, adc2_k, SECF_ADC2),
+ STM32_COMPOSITE_CFG(RNG1_K, rng1_k, SECF_RNG1),
+ STM32_COMPOSITE_CFG(USBPHY_K, usbphy_k, SECF_USBPHY),
+ STM32_COMPOSITE_CFG(STGEN_K, stgen_k, SECF_STGENC),
+ STM32_COMPOSITE_CFG(SPDIF_K, spdif_k, SECF_NONE),
+ STM32_COMPOSITE_CFG(SPI1_K, spi1_k, SECF_NONE),
+ STM32_COMPOSITE_CFG(SPI4_K, spi4_k, SECF_SPI4),
+ STM32_COMPOSITE_CFG(SPI5_K, spi5_k, SECF_SPI5),
+ STM32_COMPOSITE_CFG(I2C3_K, i2c3_k, SECF_I2C3),
+ STM32_COMPOSITE_CFG(I2C4_K, i2c4_k, SECF_I2C4),
+ STM32_COMPOSITE_CFG(I2C5_K, i2c5_k, SECF_I2C5),
+ STM32_COMPOSITE_CFG(LPTIM1_K, lptim1_k, SECF_NONE),
+ STM32_COMPOSITE_CFG(LPTIM2_K, lptim2_k, SECF_LPTIM2),
+ STM32_COMPOSITE_CFG(LPTIM3_K, lptim3_k, SECF_LPTIM3),
+ STM32_COMPOSITE_CFG(USART1_K, usart1_k, SECF_USART1),
+ STM32_COMPOSITE_CFG(USART2_K, usart2_k, SECF_USART2),
+ STM32_COMPOSITE_CFG(UART4_K, uart4_k, SECF_NONE),
+ STM32_COMPOSITE_CFG(USART6_K, uart6_k, SECF_NONE),
+ STM32_COMPOSITE_CFG(FDCAN_K, fdcan_k, SECF_NONE),
+ STM32_COMPOSITE_CFG(DCMIPP_K, dcmipp_k, SECF_DCMIPP),
+ STM32_COMPOSITE_CFG(USBO_K, usbo_k, SECF_USBO),
+ STM32_COMPOSITE_CFG(SAES_K, saes_k, SECF_SAES),
+ STM32_GATE_CFG(DFSDM_K, dfsdm_k, SECF_NONE),
+ STM32_GATE_CFG(LTDC_PX, ltdc_px, SECF_NONE),
+
+ STM32_MUX_CFG(NO_ID, ck_ker_eth1, SECF_ETH1CK),
+ STM32_GATE_CFG(ETH1CK_K, eth1ck_k, SECF_ETH1CK),
+ STM32_DIV_CFG(ETH1PTP_K, eth1ptp_k, SECF_ETH1CK),
+
+ STM32_MUX_CFG(NO_ID, ck_ker_eth2, SECF_ETH2CK),
+ STM32_GATE_CFG(ETH2CK_K, eth2ck_k, SECF_ETH2CK),
+ STM32_DIV_CFG(ETH2PTP_K, eth2ptp_k, SECF_ETH2CK),
+
+ STM32_GATE_CFG(CK_DBG, ck_sys_dbg, SECF_NONE),
+ STM32_COMPOSITE_CFG(CK_TRACE, ck_trace, SECF_NONE),
+
+ STM32_COMPOSITE_CFG(CK_MCO1, ck_mco1, SECF_MCO1),
+ STM32_COMPOSITE_CFG(CK_MCO2, ck_mco2, SECF_MCO2),
+};
+
+static int stm32mp13_clock_is_provided_by_secure(void __iomem *base,
+ const struct clock_config *cfg)
+{
+ int sec_id = cfg->sec_id;
+
+ if (sec_id != SECF_NONE) {
+ const struct clk_stm32_securiy *secf;
+
+ secf = &stm32mp13_security[sec_id];
+
+ return !!(readl(base + secf->offset) & BIT(secf->bit_idx));
+ }
+
+ return 0;
+}
+
+struct multi_mux {
+ struct clk_hw *hw1;
+ struct clk_hw *hw2;
+};
+
+static struct multi_mux *stm32_mp13_multi_mux[MUX_NB] = {
+ [MUX_SPI23] = &(struct multi_mux){ &spi2_k.hw, &spi3_k.hw },
+ [MUX_I2C12] = &(struct multi_mux){ &i2c1_k.hw, &i2c2_k.hw },
+ [MUX_LPTIM45] = &(struct multi_mux){ &lptim4_k.hw, &lptim5_k.hw },
+ [MUX_UART35] = &(struct multi_mux){ &usart3_k.hw, &uart5_k.hw },
+ [MUX_UART78] = &(struct multi_mux){ &uart7_k.hw, &uart8_k.hw },
+ [MUX_SAI1] = &(struct multi_mux){ &sai1_k.hw, &adfsdm_k.hw },
+};
+
+static struct clk_hw *stm32mp13_is_multi_mux(struct clk_hw *hw)
+{
+ struct clk_stm32_composite *composite = to_clk_stm32_composite(hw);
+ struct multi_mux *mmux = stm32_mp13_multi_mux[composite->mux_id];
+
+ if (mmux) {
+ if (!(mmux->hw1 == hw))
+ return mmux->hw1;
+ else
+ return mmux->hw2;
+ }
+
+ return NULL;
+}
+
+static u16 stm32mp13_cpt_gate[GATE_NB];
+
+static struct clk_stm32_clock_data stm32mp13_clock_data = {
+ .gate_cpt = stm32mp13_cpt_gate,
+ .gates = stm32mp13_gates,
+ .muxes = stm32mp13_muxes,
+ .dividers = stm32mp13_dividers,
+ .is_multi_mux = stm32mp13_is_multi_mux,
+};
+
+static const struct stm32_rcc_match_data stm32mp13_data = {
+ .tab_clocks = stm32mp13_clock_cfg,
+ .num_clocks = ARRAY_SIZE(stm32mp13_clock_cfg),
+ .clock_data = &stm32mp13_clock_data,
+ .check_security = &stm32mp13_clock_is_provided_by_secure,
+ .maxbinding = STM32MP1_LAST_CLK,
+ .clear_offset = RCC_CLR_OFFSET,
+};
+
+static const struct of_device_id stm32mp13_match_data[] = {
+ {
+ .compatible = "st,stm32mp13-rcc",
+ .data = &stm32mp13_data,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, stm32mp13_match_data);
+
+static int stm32mp1_rcc_init(struct device *dev)
+{
+ void __iomem *rcc_base;
+ int ret = -ENOMEM;
+
+ rcc_base = of_iomap(dev_of_node(dev), 0);
+ if (!rcc_base) {
+ dev_err(dev, "%pOFn: unable to map resource", dev_of_node(dev));
+ goto out;
+ }
+
+ ret = stm32_rcc_init(dev, stm32mp13_match_data, rcc_base);
+out:
+ if (ret) {
+ of_node_put(dev_of_node(dev));
+ }
+
+ return ret;
+}
+
+static int get_clock_deps(struct device *dev)
+{
+ static const char * const clock_deps_name[] = {
+ "hsi", "hse", "csi", "lsi", "lse",
+ };
+ size_t deps_size = sizeof(struct clk *) * ARRAY_SIZE(clock_deps_name);
+ struct clk **clk_deps;
+ int i;
+
+ clk_deps = devm_kzalloc(dev, deps_size, GFP_KERNEL);
+ if (!clk_deps)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(clock_deps_name); i++) {
+ struct clk *clk = of_clk_get_by_name(dev_of_node(dev),
+ clock_deps_name[i]);
+
+ if (IS_ERR(clk)) {
+ if (PTR_ERR(clk) != -EINVAL && PTR_ERR(clk) != -ENOENT)
+ return PTR_ERR(clk);
+ } else {
+ /* Device gets a reference count on the clock */
+ clk_deps[i] = clk_get(dev, __clk_get_name(clk));
+ clk_put(clk);
+ }
+ }
+
+ return 0;
+}
+
+static int stm32mp1_rcc_clocks_probe(struct device *dev)
+{
+ int ret = get_clock_deps(dev);
+
+ if (!ret)
+ ret = stm32mp1_rcc_init(dev);
+
+ return ret;
+}
+
+static void stm32mp1_rcc_clocks_remove(struct device *dev)
+{
+ struct device_node *child, *np = dev_of_node(dev);
+
+ for_each_available_child_of_node(np, child)
+ of_clk_del_provider(child);
+}
+
+static struct driver stm32mp13_rcc_clocks_driver = {
+ .name = "stm32mp13_rcc",
+ .of_match_table = stm32mp13_match_data,
+ .probe = stm32mp1_rcc_clocks_probe,
+ .remove = stm32mp1_rcc_clocks_remove,
+};
+
+static int __init stm32mp13_clocks_init(void)
+{
+ return platform_driver_register(&stm32mp13_rcc_clocks_driver);
+}
+core_initcall(stm32mp13_clocks_init);
diff --git a/drivers/clk/stm32/reset-stm32.c b/drivers/clk/stm32/reset-stm32.c
new file mode 100644
index 0000000000..534afd0942
--- /dev/null
+++ b/drivers/clk/stm32/reset-stm32.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2022 - All Rights Reserved
+ * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics.
+ */
+
+#include <of.h>
+#include <linux/device.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "clk-stm32-core.h"
+
+#define STM32_RESET_ID_MASK GENMASK(15, 0)
+
+struct stm32_reset_data {
+ /* reset lock */
+ spinlock_t lock;
+ struct reset_controller_dev rcdev;
+ void __iomem *membase;
+ u32 clear_offset;
+};
+
+static inline struct stm32_reset_data *
+to_stm32_reset_data(struct reset_controller_dev *rcdev)
+{
+ return container_of(rcdev, struct stm32_reset_data, rcdev);
+}
+
+static int stm32_reset_update(struct reset_controller_dev *rcdev,
+ unsigned long id, bool assert)
+{
+ struct stm32_reset_data *data = to_stm32_reset_data(rcdev);
+ int reg_width = sizeof(u32);
+ int bank = id / (reg_width * BITS_PER_BYTE);
+ int offset = id % (reg_width * BITS_PER_BYTE);
+
+ if (data->clear_offset) {
+ void __iomem *addr;
+
+ addr = data->membase + (bank * reg_width);
+ if (!assert)
+ addr += data->clear_offset;
+
+ writel(BIT(offset), addr);
+
+ } else {
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&data->lock, flags);
+
+ reg = readl(data->membase + (bank * reg_width));
+
+ if (assert)
+ reg |= BIT(offset);
+ else
+ reg &= ~BIT(offset);
+
+ writel(reg, data->membase + (bank * reg_width));
+
+ spin_unlock_irqrestore(&data->lock, flags);
+ }
+
+ return 0;
+}
+
+static int stm32_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return stm32_reset_update(rcdev, id, true);
+}
+
+static int stm32_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return stm32_reset_update(rcdev, id, false);
+}
+
+static int stm32_reset_status(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct stm32_reset_data *data = to_stm32_reset_data(rcdev);
+ int reg_width = sizeof(u32);
+ int bank = id / (reg_width * BITS_PER_BYTE);
+ int offset = id % (reg_width * BITS_PER_BYTE);
+ u32 reg;
+
+ reg = readl(data->membase + (bank * reg_width));
+
+ return !!(reg & BIT(offset));
+}
+
+static const struct reset_control_ops stm32_reset_ops = {
+ .assert = stm32_reset_assert,
+ .deassert = stm32_reset_deassert,
+ .status = stm32_reset_status,
+};
+
+int stm32_rcc_reset_init(struct device *dev, const struct of_device_id *match,
+ void __iomem *base)
+{
+ const struct stm32_rcc_match_data *data = match->data;
+ struct stm32_reset_data *reset_data = NULL;
+
+ data = match->data;
+
+ reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
+ if (!reset_data)
+ return -ENOMEM;
+
+ spin_lock_init(&reset_data->lock);
+ reset_data->membase = base;
+ reset_data->rcdev.ops = &stm32_reset_ops;
+ reset_data->rcdev.of_node = dev_of_node(dev);
+ reset_data->rcdev.nr_resets = STM32_RESET_ID_MASK;
+ reset_data->clear_offset = data->clear_offset;
+
+ return reset_controller_register(&reset_data->rcdev);
+}
diff --git a/drivers/clk/stm32/reset-stm32.h b/drivers/clk/stm32/reset-stm32.h
new file mode 100644
index 0000000000..6eb6ea4b55
--- /dev/null
+++ b/drivers/clk/stm32/reset-stm32.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) STMicroelectronics 2022 - All Rights Reserved
+ * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics.
+ */
+
+int stm32_rcc_reset_init(struct device *dev, const struct of_device_id *match,
+ void __iomem *base);
diff --git a/drivers/clk/stm32/stm32mp13_rcc.h b/drivers/clk/stm32/stm32mp13_rcc.h
new file mode 100644
index 0000000000..a82512ae08
--- /dev/null
+++ b/drivers/clk/stm32/stm32mp13_rcc.h
@@ -0,0 +1,1748 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (C) 2020, STMicroelectronics - All Rights Reserved
+ *
+ * Configuration settings for the STM32MP13x CPU
+ */
+
+#ifndef STM32MP13_RCC_H
+#define STM32MP13_RCC_H
+/* RCC registers */
+#define RCC_SECCFGR 0x0
+#define RCC_MP_SREQSETR 0x100
+#define RCC_MP_SREQCLRR 0x104
+#define RCC_MP_APRSTCR 0x108
+#define RCC_MP_APRSTSR 0x10c
+#define RCC_PWRLPDLYCR 0x110
+#define RCC_MP_GRSTCSETR 0x114
+#define RCC_BR_RSTSCLRR 0x118
+#define RCC_MP_RSTSSETR 0x11c
+#define RCC_MP_RSTSCLRR 0x120
+#define RCC_MP_IWDGFZSETR 0x124
+#define RCC_MP_IWDGFZCLRR 0x128
+#define RCC_MP_CIER 0x200
+#define RCC_MP_CIFR 0x204
+#define RCC_BDCR 0x400
+#define RCC_RDLSICR 0x404
+#define RCC_OCENSETR 0x420
+#define RCC_OCENCLRR 0x424
+#define RCC_OCRDYR 0x428
+#define RCC_HSICFGR 0x440
+#define RCC_CSICFGR 0x444
+#define RCC_MCO1CFGR 0x460
+#define RCC_MCO2CFGR 0x464
+#define RCC_DBGCFGR 0x468
+#define RCC_RCK12SELR 0x480
+#define RCC_RCK3SELR 0x484
+#define RCC_RCK4SELR 0x488
+#define RCC_PLL1CR 0x4a0
+#define RCC_PLL1CFGR1 0x4a4
+#define RCC_PLL1CFGR2 0x4a8
+#define RCC_PLL1FRACR 0x4ac
+#define RCC_PLL1CSGR 0x4b0
+#define RCC_PLL2CR 0x4d0
+#define RCC_PLL2CFGR1 0x4d4
+#define RCC_PLL2CFGR2 0x4d8
+#define RCC_PLL2FRACR 0x4dc
+#define RCC_PLL2CSGR 0x4e0
+#define RCC_PLL3CR 0x500
+#define RCC_PLL3CFGR1 0x504
+#define RCC_PLL3CFGR2 0x508
+#define RCC_PLL3FRACR 0x50c
+#define RCC_PLL3CSGR 0x510
+#define RCC_PLL4CR 0x520
+#define RCC_PLL4CFGR1 0x524
+#define RCC_PLL4CFGR2 0x528
+#define RCC_PLL4FRACR 0x52c
+#define RCC_PLL4CSGR 0x530
+#define RCC_MPCKSELR 0x540
+#define RCC_ASSCKSELR 0x544
+#define RCC_MSSCKSELR 0x548
+#define RCC_CPERCKSELR 0x54c
+#define RCC_RTCDIVR 0x560
+#define RCC_MPCKDIVR 0x564
+#define RCC_AXIDIVR 0x568
+#define RCC_MLAHBDIVR 0x56c
+#define RCC_APB1DIVR 0x570
+#define RCC_APB2DIVR 0x574
+#define RCC_APB3DIVR 0x578
+#define RCC_APB4DIVR 0x57c
+#define RCC_APB5DIVR 0x580
+#define RCC_APB6DIVR 0x584
+#define RCC_TIMG1PRER 0x5a0
+#define RCC_TIMG2PRER 0x5a4
+#define RCC_TIMG3PRER 0x5a8
+#define RCC_DDRITFCR 0x5c0
+#define RCC_I2C12CKSELR 0x600
+#define RCC_I2C345CKSELR 0x604
+#define RCC_SPI2S1CKSELR 0x608
+#define RCC_SPI2S23CKSELR 0x60c
+#define RCC_SPI45CKSELR 0x610
+#define RCC_UART12CKSELR 0x614
+#define RCC_UART35CKSELR 0x618
+#define RCC_UART4CKSELR 0x61c
+#define RCC_UART6CKSELR 0x620
+#define RCC_UART78CKSELR 0x624
+#define RCC_LPTIM1CKSELR 0x628
+#define RCC_LPTIM23CKSELR 0x62c
+#define RCC_LPTIM45CKSELR 0x630
+#define RCC_SAI1CKSELR 0x634
+#define RCC_SAI2CKSELR 0x638
+#define RCC_FDCANCKSELR 0x63c
+#define RCC_SPDIFCKSELR 0x640
+#define RCC_ADC12CKSELR 0x644
+#define RCC_SDMMC12CKSELR 0x648
+#define RCC_ETH12CKSELR 0x64c
+#define RCC_USBCKSELR 0x650
+#define RCC_QSPICKSELR 0x654
+#define RCC_FMCCKSELR 0x658
+#define RCC_RNG1CKSELR 0x65c
+#define RCC_STGENCKSELR 0x660
+#define RCC_DCMIPPCKSELR 0x664
+#define RCC_SAESCKSELR 0x668
+#define RCC_APB1RSTSETR 0x6a0
+#define RCC_APB1RSTCLRR 0x6a4
+#define RCC_APB2RSTSETR 0x6a8
+#define RCC_APB2RSTCLRR 0x6ac
+#define RCC_APB3RSTSETR 0x6b0
+#define RCC_APB3RSTCLRR 0x6b4
+#define RCC_APB4RSTSETR 0x6b8
+#define RCC_APB4RSTCLRR 0x6bc
+#define RCC_APB5RSTSETR 0x6c0
+#define RCC_APB5RSTCLRR 0x6c4
+#define RCC_APB6RSTSETR 0x6c8
+#define RCC_APB6RSTCLRR 0x6cc
+#define RCC_AHB2RSTSETR 0x6d0
+#define RCC_AHB2RSTCLRR 0x6d4
+#define RCC_AHB4RSTSETR 0x6e0
+#define RCC_AHB4RSTCLRR 0x6e4
+#define RCC_AHB5RSTSETR 0x6e8
+#define RCC_AHB5RSTCLRR 0x6ec
+#define RCC_AHB6RSTSETR 0x6f0
+#define RCC_AHB6RSTCLRR 0x6f4
+#define RCC_MP_APB1ENSETR 0x700
+#define RCC_MP_APB1ENCLRR 0x704
+#define RCC_MP_APB2ENSETR 0x708
+#define RCC_MP_APB2ENCLRR 0x70c
+#define RCC_MP_APB3ENSETR 0x710
+#define RCC_MP_APB3ENCLRR 0x714
+#define RCC_MP_S_APB3ENSETR 0x718
+#define RCC_MP_S_APB3ENCLRR 0x71c
+#define RCC_MP_NS_APB3ENSETR 0x720
+#define RCC_MP_NS_APB3ENCLRR 0x724
+#define RCC_MP_APB4ENSETR 0x728
+#define RCC_MP_APB4ENCLRR 0x72c
+#define RCC_MP_S_APB4ENSETR 0x730
+#define RCC_MP_S_APB4ENCLRR 0x734
+#define RCC_MP_NS_APB4ENSETR 0x738
+#define RCC_MP_NS_APB4ENCLRR 0x73c
+#define RCC_MP_APB5ENSETR 0x740
+#define RCC_MP_APB5ENCLRR 0x744
+#define RCC_MP_APB6ENSETR 0x748
+#define RCC_MP_APB6ENCLRR 0x74c
+#define RCC_MP_AHB2ENSETR 0x750
+#define RCC_MP_AHB2ENCLRR 0x754
+#define RCC_MP_AHB4ENSETR 0x760
+#define RCC_MP_AHB4ENCLRR 0x764
+#define RCC_MP_S_AHB4ENSETR 0x768
+#define RCC_MP_S_AHB4ENCLRR 0x76c
+#define RCC_MP_NS_AHB4ENSETR 0x770
+#define RCC_MP_NS_AHB4ENCLRR 0x774
+#define RCC_MP_AHB5ENSETR 0x778
+#define RCC_MP_AHB5ENCLRR 0x77c
+#define RCC_MP_AHB6ENSETR 0x780
+#define RCC_MP_AHB6ENCLRR 0x784
+#define RCC_MP_S_AHB6ENSETR 0x788
+#define RCC_MP_S_AHB6ENCLRR 0x78c
+#define RCC_MP_NS_AHB6ENSETR 0x790
+#define RCC_MP_NS_AHB6ENCLRR 0x794
+#define RCC_MP_APB1LPENSETR 0x800
+#define RCC_MP_APB1LPENCLRR 0x804
+#define RCC_MP_APB2LPENSETR 0x808
+#define RCC_MP_APB2LPENCLRR 0x80c
+#define RCC_MP_APB3LPENSETR 0x810
+#define RCC_MP_APB3LPENCLRR 0x814
+#define RCC_MP_S_APB3LPENSETR 0x818
+#define RCC_MP_S_APB3LPENCLRR 0x81c
+#define RCC_MP_NS_APB3LPENSETR 0x820
+#define RCC_MP_NS_APB3LPENCLRR 0x824
+#define RCC_MP_APB4LPENSETR 0x828
+#define RCC_MP_APB4LPENCLRR 0x82c
+#define RCC_MP_S_APB4LPENSETR 0x830
+#define RCC_MP_S_APB4LPENCLRR 0x834
+#define RCC_MP_NS_APB4LPENSETR 0x838
+#define RCC_MP_NS_APB4LPENCLRR 0x83c
+#define RCC_MP_APB5LPENSETR 0x840
+#define RCC_MP_APB5LPENCLRR 0x844
+#define RCC_MP_APB6LPENSETR 0x848
+#define RCC_MP_APB6LPENCLRR 0x84c
+#define RCC_MP_AHB2LPENSETR 0x850
+#define RCC_MP_AHB2LPENCLRR 0x854
+#define RCC_MP_AHB4LPENSETR 0x858
+#define RCC_MP_AHB4LPENCLRR 0x85c
+#define RCC_MP_S_AHB4LPENSETR 0x868
+#define RCC_MP_S_AHB4LPENCLRR 0x86c
+#define RCC_MP_NS_AHB4LPENSETR 0x870
+#define RCC_MP_NS_AHB4LPENCLRR 0x874
+#define RCC_MP_AHB5LPENSETR 0x878
+#define RCC_MP_AHB5LPENCLRR 0x87c
+#define RCC_MP_AHB6LPENSETR 0x880
+#define RCC_MP_AHB6LPENCLRR 0x884
+#define RCC_MP_S_AHB6LPENSETR 0x888
+#define RCC_MP_S_AHB6LPENCLRR 0x88c
+#define RCC_MP_NS_AHB6LPENSETR 0x890
+#define RCC_MP_NS_AHB6LPENCLRR 0x894
+#define RCC_MP_S_AXIMLPENSETR 0x898
+#define RCC_MP_S_AXIMLPENCLRR 0x89c
+#define RCC_MP_NS_AXIMLPENSETR 0x8a0
+#define RCC_MP_NS_AXIMLPENCLRR 0x8a4
+#define RCC_MP_MLAHBLPENSETR 0x8a8
+#define RCC_MP_MLAHBLPENCLRR 0x8ac
+#define RCC_APB3SECSR 0x8c0
+#define RCC_APB4SECSR 0x8c4
+#define RCC_APB5SECSR 0x8c8
+#define RCC_APB6SECSR 0x8cc
+#define RCC_AHB2SECSR 0x8d0
+#define RCC_AHB4SECSR 0x8d4
+#define RCC_AHB5SECSR 0x8d8
+#define RCC_AHB6SECSR 0x8dc
+#define RCC_VERR 0xff4
+#define RCC_IDR 0xff8
+#define RCC_SIDR 0xffc
+
+/* RCC_SECCFGR register fields */
+#define RCC_SECCFGR_HSISEC 0
+#define RCC_SECCFGR_CSISEC 1
+#define RCC_SECCFGR_HSESEC 2
+#define RCC_SECCFGR_LSISEC 3
+#define RCC_SECCFGR_LSESEC 4
+#define RCC_SECCFGR_PLL12SEC 8
+#define RCC_SECCFGR_PLL3SEC 9
+#define RCC_SECCFGR_PLL4SEC 10
+#define RCC_SECCFGR_MPUSEC 11
+#define RCC_SECCFGR_AXISEC 12
+#define RCC_SECCFGR_MLAHBSEC 13
+#define RCC_SECCFGR_APB3DIVSEC 16
+#define RCC_SECCFGR_APB4DIVSEC 17
+#define RCC_SECCFGR_APB5DIVSEC 18
+#define RCC_SECCFGR_APB6DIVSEC 19
+#define RCC_SECCFGR_TIMG3SEC 20
+#define RCC_SECCFGR_CPERSEC 21
+#define RCC_SECCFGR_MCO1SEC 22
+#define RCC_SECCFGR_MCO2SEC 23
+#define RCC_SECCFGR_STPSEC 24
+#define RCC_SECCFGR_RSTSEC 25
+#define RCC_SECCFGR_PWRSEC 31
+
+/* RCC_MP_SREQSETR register fields */
+#define RCC_MP_SREQSETR_STPREQ_P0 BIT(0)
+
+/* RCC_MP_SREQCLRR register fields */
+#define RCC_MP_SREQCLRR_STPREQ_P0 BIT(0)
+
+/* RCC_MP_APRSTCR register fields */
+#define RCC_MP_APRSTCR_RDCTLEN BIT(0)
+#define RCC_MP_APRSTCR_RSTTO_MASK GENMASK(14, 8)
+#define RCC_MP_APRSTCR_RSTTO_SHIFT 8
+
+/* RCC_MP_APRSTSR register fields */
+#define RCC_MP_APRSTSR_RSTTOV_MASK GENMASK(14, 8)
+#define RCC_MP_APRSTSR_RSTTOV_SHIFT 8
+
+/* RCC_PWRLPDLYCR register fields */
+#define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK(21, 0)
+#define RCC_PWRLPDLYCR_PWRLP_DLY_SHIFT 0
+
+/* RCC_MP_GRSTCSETR register fields */
+#define RCC_MP_GRSTCSETR_MPSYSRST BIT(0)
+#define RCC_MP_GRSTCSETR_MPUP0RST BIT(4)
+
+/* RCC_BR_RSTSCLRR register fields */
+#define RCC_BR_RSTSCLRR_PORRSTF BIT(0)
+#define RCC_BR_RSTSCLRR_BORRSTF BIT(1)
+#define RCC_BR_RSTSCLRR_PADRSTF BIT(2)
+#define RCC_BR_RSTSCLRR_HCSSRSTF BIT(3)
+#define RCC_BR_RSTSCLRR_VCORERSTF BIT(4)
+#define RCC_BR_RSTSCLRR_VCPURSTF BIT(5)
+#define RCC_BR_RSTSCLRR_MPSYSRSTF BIT(6)
+#define RCC_BR_RSTSCLRR_IWDG1RSTF BIT(8)
+#define RCC_BR_RSTSCLRR_IWDG2RSTF BIT(9)
+#define RCC_BR_RSTSCLRR_MPUP0RSTF BIT(13)
+
+/* RCC_MP_RSTSSETR register fields */
+#define RCC_MP_RSTSSETR_PORRSTF BIT(0)
+#define RCC_MP_RSTSSETR_BORRSTF BIT(1)
+#define RCC_MP_RSTSSETR_PADRSTF BIT(2)
+#define RCC_MP_RSTSSETR_HCSSRSTF BIT(3)
+#define RCC_MP_RSTSSETR_VCORERSTF BIT(4)
+#define RCC_MP_RSTSSETR_VCPURSTF BIT(5)
+#define RCC_MP_RSTSSETR_MPSYSRSTF BIT(6)
+#define RCC_MP_RSTSSETR_IWDG1RSTF BIT(8)
+#define RCC_MP_RSTSSETR_IWDG2RSTF BIT(9)
+#define RCC_MP_RSTSSETR_STP2RSTF BIT(10)
+#define RCC_MP_RSTSSETR_STDBYRSTF BIT(11)
+#define RCC_MP_RSTSSETR_CSTDBYRSTF BIT(12)
+#define RCC_MP_RSTSSETR_MPUP0RSTF BIT(13)
+#define RCC_MP_RSTSSETR_SPARE BIT(15)
+
+/* RCC_MP_RSTSCLRR register fields */
+#define RCC_MP_RSTSCLRR_PORRSTF BIT(0)
+#define RCC_MP_RSTSCLRR_BORRSTF BIT(1)
+#define RCC_MP_RSTSCLRR_PADRSTF BIT(2)
+#define RCC_MP_RSTSCLRR_HCSSRSTF BIT(3)
+#define RCC_MP_RSTSCLRR_VCORERSTF BIT(4)
+#define RCC_MP_RSTSCLRR_VCPURSTF BIT(5)
+#define RCC_MP_RSTSCLRR_MPSYSRSTF BIT(6)
+#define RCC_MP_RSTSCLRR_IWDG1RSTF BIT(8)
+#define RCC_MP_RSTSCLRR_IWDG2RSTF BIT(9)
+#define RCC_MP_RSTSCLRR_STP2RSTF BIT(10)
+#define RCC_MP_RSTSCLRR_STDBYRSTF BIT(11)
+#define RCC_MP_RSTSCLRR_CSTDBYRSTF BIT(12)
+#define RCC_MP_RSTSCLRR_MPUP0RSTF BIT(13)
+#define RCC_MP_RSTSCLRR_SPARE BIT(15)
+
+/* RCC_MP_IWDGFZSETR register fields */
+#define RCC_MP_IWDGFZSETR_FZ_IWDG1 BIT(0)
+#define RCC_MP_IWDGFZSETR_FZ_IWDG2 BIT(1)
+
+/* RCC_MP_IWDGFZCLRR register fields */
+#define RCC_MP_IWDGFZCLRR_FZ_IWDG1 BIT(0)
+#define RCC_MP_IWDGFZCLRR_FZ_IWDG2 BIT(1)
+
+/* RCC_MP_CIER register fields */
+#define RCC_MP_CIER_LSIRDYIE BIT(0)
+#define RCC_MP_CIER_LSERDYIE BIT(1)
+#define RCC_MP_CIER_HSIRDYIE BIT(2)
+#define RCC_MP_CIER_HSERDYIE BIT(3)
+#define RCC_MP_CIER_CSIRDYIE BIT(4)
+#define RCC_MP_CIER_PLL1DYIE BIT(8)
+#define RCC_MP_CIER_PLL2DYIE BIT(9)
+#define RCC_MP_CIER_PLL3DYIE BIT(10)
+#define RCC_MP_CIER_PLL4DYIE BIT(11)
+#define RCC_MP_CIER_LSECSSIE BIT(16)
+#define RCC_MP_CIER_WKUPIE BIT(20)
+
+/* RCC_MP_CIFR register fields */
+#define RCC_MP_CIFR_LSIRDYF BIT(0)
+#define RCC_MP_CIFR_LSERDYF BIT(1)
+#define RCC_MP_CIFR_HSIRDYF BIT(2)
+#define RCC_MP_CIFR_HSERDYF BIT(3)
+#define RCC_MP_CIFR_CSIRDYF BIT(4)
+#define RCC_MP_CIFR_PLL1DYF BIT(8)
+#define RCC_MP_CIFR_PLL2DYF BIT(9)
+#define RCC_MP_CIFR_PLL3DYF BIT(10)
+#define RCC_MP_CIFR_PLL4DYF BIT(11)
+#define RCC_MP_CIFR_LSECSSF BIT(16)
+#define RCC_MP_CIFR_WKUPF BIT(20)
+
+/* RCC_BDCR register fields */
+#define RCC_BDCR_LSEON BIT(0)
+#define RCC_BDCR_LSEBYP BIT(1)
+#define RCC_BDCR_LSERDY BIT(2)
+#define RCC_BDCR_DIGBYP BIT(3)
+#define RCC_BDCR_LSEDRV_MASK GENMASK(5, 4)
+#define RCC_BDCR_LSECSSON BIT(8)
+#define RCC_BDCR_LSECSSD BIT(9)
+#define RCC_BDCR_RTCSRC_MASK GENMASK(17, 16)
+#define RCC_BDCR_RTCCKEN BIT(20)
+#define RCC_BDCR_VSWRST BIT(31)
+#define RCC_BDCR_LSEDRV_SHIFT 4
+#define RCC_BDCR_RTCSRC_SHIFT 16
+
+/* RCC_RDLSICR register fields */
+#define RCC_RDLSICR_LSION BIT(0)
+#define RCC_RDLSICR_LSIRDY BIT(1)
+#define RCC_RDLSICR_MRD_MASK GENMASK(20, 16)
+#define RCC_RDLSICR_EADLY_MASK GENMASK(26, 24)
+#define RCC_RDLSICR_SPARE_MASK GENMASK(31, 27)
+#define RCC_RDLSICR_MRD_SHIFT 16
+#define RCC_RDLSICR_EADLY_SHIFT 24
+#define RCC_RDLSICR_SPARE_SHIFT 27
+
+/* RCC_OCENSETR register fields */
+#define RCC_OCENSETR_HSION BIT(0)
+#define RCC_OCENSETR_HSIKERON BIT(1)
+#define RCC_OCENSETR_CSION BIT(4)
+#define RCC_OCENSETR_CSIKERON BIT(5)
+#define RCC_OCENSETR_DIGBYP BIT(7)
+#define RCC_OCENSETR_HSEON BIT(8)
+#define RCC_OCENSETR_HSEKERON BIT(9)
+#define RCC_OCENSETR_HSEBYP BIT(10)
+#define RCC_OCENSETR_HSECSSON BIT(11)
+
+/* RCC_OCENCLRR register fields */
+#define RCC_OCENCLRR_HSION BIT(0)
+#define RCC_OCENCLRR_HSIKERON BIT(1)
+#define RCC_OCENCLRR_CSION BIT(4)
+#define RCC_OCENCLRR_CSIKERON BIT(5)
+#define RCC_OCENCLRR_DIGBYP BIT(7)
+#define RCC_OCENCLRR_HSEON BIT(8)
+#define RCC_OCENCLRR_HSEKERON BIT(9)
+#define RCC_OCENCLRR_HSEBYP BIT(10)
+
+/* RCC_OCRDYR register fields */
+#define RCC_OCRDYR_HSIRDY BIT(0)
+#define RCC_OCRDYR_HSIDIVRDY BIT(2)
+#define RCC_OCRDYR_CSIRDY BIT(4)
+#define RCC_OCRDYR_HSERDY BIT(8)
+#define RCC_OCRDYR_MPUCKRDY BIT(23)
+#define RCC_OCRDYR_AXICKRDY BIT(24)
+
+/* RCC_HSICFGR register fields */
+#define RCC_HSICFGR_HSIDIV_MASK GENMASK(1, 0)
+#define RCC_HSICFGR_HSITRIM_MASK GENMASK(14, 8)
+#define RCC_HSICFGR_HSICAL_MASK GENMASK(27, 16)
+#define RCC_HSICFGR_HSIDIV_SHIFT 0
+#define RCC_HSICFGR_HSITRIM_SHIFT 8
+#define RCC_HSICFGR_HSICAL_SHIFT 16
+
+/* RCC_CSICFGR register fields */
+#define RCC_CSICFGR_CSITRIM_MASK GENMASK(12, 8)
+#define RCC_CSICFGR_CSICAL_MASK GENMASK(23, 16)
+#define RCC_CSICFGR_CSITRIM_SHIFT 8
+#define RCC_CSICFGR_CSICAL_SHIFT 16
+
+/* RCC_MCO1CFGR register fields */
+#define RCC_MCO1CFGR_MCO1SEL_MASK GENMASK(2, 0)
+#define RCC_MCO1CFGR_MCO1DIV_MASK GENMASK(7, 4)
+#define RCC_MCO1CFGR_MCO1ON BIT(12)
+#define RCC_MCO1CFGR_MCO1SEL_SHIFT 0
+#define RCC_MCO1CFGR_MCO1DIV_SHIFT 4
+
+/* RCC_MCO2CFGR register fields */
+#define RCC_MCO2CFGR_MCO2SEL_MASK GENMASK(2, 0)
+#define RCC_MCO2CFGR_MCO2DIV_MASK GENMASK(7, 4)
+#define RCC_MCO2CFGR_MCO2ON BIT(12)
+#define RCC_MCO2CFGR_MCO2SEL_SHIFT 0
+#define RCC_MCO2CFGR_MCO2DIV_SHIFT 4
+
+/* RCC_DBGCFGR register fields */
+#define RCC_DBGCFGR_TRACEDIV_MASK GENMASK(2, 0)
+#define RCC_DBGCFGR_DBGCKEN BIT(8)
+#define RCC_DBGCFGR_TRACECKEN BIT(9)
+#define RCC_DBGCFGR_DBGRST BIT(12)
+#define RCC_DBGCFGR_TRACEDIV_SHIFT 0
+
+/* RCC_RCK12SELR register fields */
+#define RCC_RCK12SELR_PLL12SRC_MASK GENMASK(1, 0)
+#define RCC_RCK12SELR_PLL12SRCRDY BIT(31)
+#define RCC_RCK12SELR_PLL12SRC_SHIFT 0
+
+/* RCC_RCK3SELR register fields */
+#define RCC_RCK3SELR_PLL3SRC_MASK GENMASK(1, 0)
+#define RCC_RCK3SELR_PLL3SRCRDY BIT(31)
+#define RCC_RCK3SELR_PLL3SRC_SHIFT 0
+
+/* RCC_RCK4SELR register fields */
+#define RCC_RCK4SELR_PLL4SRC_MASK GENMASK(1, 0)
+#define RCC_RCK4SELR_PLL4SRCRDY BIT(31)
+#define RCC_RCK4SELR_PLL4SRC_SHIFT 0
+
+/* RCC_PLL1CR register fields */
+#define RCC_PLL1CR_PLLON BIT(0)
+#define RCC_PLL1CR_PLL1RDY BIT(1)
+#define RCC_PLL1CR_SSCG_CTRL BIT(2)
+#define RCC_PLL1CR_DIVPEN BIT(4)
+#define RCC_PLL1CR_DIVQEN BIT(5)
+#define RCC_PLL1CR_DIVREN BIT(6)
+
+/* RCC_PLL1CFGR1 register fields */
+#define RCC_PLL1CFGR1_DIVN_MASK GENMASK(8, 0)
+#define RCC_PLL1CFGR1_DIVM1_MASK GENMASK(21, 16)
+#define RCC_PLL1CFGR1_DIVN_SHIFT 0
+#define RCC_PLL1CFGR1_DIVM1_SHIFT 16
+
+/* RCC_PLL1CFGR2 register fields */
+#define RCC_PLL1CFGR2_DIVP_MASK GENMASK(6, 0)
+#define RCC_PLL1CFGR2_DIVQ_MASK GENMASK(14, 8)
+#define RCC_PLL1CFGR2_DIVR_MASK GENMASK(22, 16)
+#define RCC_PLL1CFGR2_DIVP_SHIFT 0
+#define RCC_PLL1CFGR2_DIVQ_SHIFT 8
+#define RCC_PLL1CFGR2_DIVR_SHIFT 16
+
+/* RCC_PLL1FRACR register fields */
+#define RCC_PLL1FRACR_FRACV_MASK GENMASK(15, 3)
+#define RCC_PLL1FRACR_FRACLE BIT(16)
+#define RCC_PLL1FRACR_FRACV_SHIFT 3
+
+/* RCC_PLL1CSGR register fields */
+#define RCC_PLL1CSGR_MOD_PER_MASK GENMASK(12, 0)
+#define RCC_PLL1CSGR_TPDFN_DIS BIT(13)
+#define RCC_PLL1CSGR_RPDFN_DIS BIT(14)
+#define RCC_PLL1CSGR_SSCG_MODE BIT(15)
+#define RCC_PLL1CSGR_INC_STEP_MASK GENMASK(30, 16)
+#define RCC_PLL1CSGR_MOD_PER_SHIFT 0
+#define RCC_PLL1CSGR_INC_STEP_SHIFT 16
+
+/* RCC_PLL2CR register fields */
+#define RCC_PLL2CR_PLLON BIT(0)
+#define RCC_PLL2CR_PLL2RDY BIT(1)
+#define RCC_PLL2CR_SSCG_CTRL BIT(2)
+#define RCC_PLL2CR_DIVPEN BIT(4)
+#define RCC_PLL2CR_DIVQEN BIT(5)
+#define RCC_PLL2CR_DIVREN BIT(6)
+
+/* RCC_PLL2CFGR1 register fields */
+#define RCC_PLL2CFGR1_DIVN_MASK GENMASK(8, 0)
+#define RCC_PLL2CFGR1_DIVM2_MASK GENMASK(21, 16)
+#define RCC_PLL2CFGR1_DIVN_SHIFT 0
+#define RCC_PLL2CFGR1_DIVM2_SHIFT 16
+
+/* RCC_PLL2CFGR2 register fields */
+#define RCC_PLL2CFGR2_DIVP_MASK GENMASK(6, 0)
+#define RCC_PLL2CFGR2_DIVQ_MASK GENMASK(14, 8)
+#define RCC_PLL2CFGR2_DIVR_MASK GENMASK(22, 16)
+#define RCC_PLL2CFGR2_DIVP_SHIFT 0
+#define RCC_PLL2CFGR2_DIVQ_SHIFT 8
+#define RCC_PLL2CFGR2_DIVR_SHIFT 16
+
+/* RCC_PLL2FRACR register fields */
+#define RCC_PLL2FRACR_FRACV_MASK GENMASK(15, 3)
+#define RCC_PLL2FRACR_FRACLE BIT(16)
+#define RCC_PLL2FRACR_FRACV_SHIFT 3
+
+/* RCC_PLL2CSGR register fields */
+#define RCC_PLL2CSGR_MOD_PER_MASK GENMASK(12, 0)
+#define RCC_PLL2CSGR_TPDFN_DIS BIT(13)
+#define RCC_PLL2CSGR_RPDFN_DIS BIT(14)
+#define RCC_PLL2CSGR_SSCG_MODE BIT(15)
+#define RCC_PLL2CSGR_INC_STEP_MASK GENMASK(30, 16)
+#define RCC_PLL2CSGR_MOD_PER_SHIFT 0
+#define RCC_PLL2CSGR_INC_STEP_SHIFT 16
+
+/* RCC_PLL3CR register fields */
+#define RCC_PLL3CR_PLLON BIT(0)
+#define RCC_PLL3CR_PLL3RDY BIT(1)
+#define RCC_PLL3CR_SSCG_CTRL BIT(2)
+#define RCC_PLL3CR_DIVPEN BIT(4)
+#define RCC_PLL3CR_DIVQEN BIT(5)
+#define RCC_PLL3CR_DIVREN BIT(6)
+
+/* RCC_PLL3CFGR1 register fields */
+#define RCC_PLL3CFGR1_DIVN_MASK GENMASK(8, 0)
+#define RCC_PLL3CFGR1_DIVM3_MASK GENMASK(21, 16)
+#define RCC_PLL3CFGR1_IFRGE_MASK GENMASK(25, 24)
+#define RCC_PLL3CFGR1_DIVN_SHIFT 0
+#define RCC_PLL3CFGR1_DIVM3_SHIFT 16
+#define RCC_PLL3CFGR1_IFRGE_SHIFT 24
+
+/* RCC_PLL3CFGR2 register fields */
+#define RCC_PLL3CFGR2_DIVP_MASK GENMASK(6, 0)
+#define RCC_PLL3CFGR2_DIVQ_MASK GENMASK(14, 8)
+#define RCC_PLL3CFGR2_DIVR_MASK GENMASK(22, 16)
+#define RCC_PLL3CFGR2_DIVP_SHIFT 0
+#define RCC_PLL3CFGR2_DIVQ_SHIFT 8
+#define RCC_PLL3CFGR2_DIVR_SHIFT 16
+
+/* RCC_PLL3FRACR register fields */
+#define RCC_PLL3FRACR_FRACV_MASK GENMASK(15, 3)
+#define RCC_PLL3FRACR_FRACLE BIT(16)
+#define RCC_PLL3FRACR_FRACV_SHIFT 3
+
+/* RCC_PLL3CSGR register fields */
+#define RCC_PLL3CSGR_MOD_PER_MASK GENMASK(12, 0)
+#define RCC_PLL3CSGR_TPDFN_DIS BIT(13)
+#define RCC_PLL3CSGR_RPDFN_DIS BIT(14)
+#define RCC_PLL3CSGR_SSCG_MODE BIT(15)
+#define RCC_PLL3CSGR_INC_STEP_MASK GENMASK(30, 16)
+#define RCC_PLL3CSGR_MOD_PER_SHIFT 0
+#define RCC_PLL3CSGR_INC_STEP_SHIFT 16
+
+/* RCC_PLL4CR register fields */
+#define RCC_PLL4CR_PLLON BIT(0)
+#define RCC_PLL4CR_PLL4RDY BIT(1)
+#define RCC_PLL4CR_SSCG_CTRL BIT(2)
+#define RCC_PLL4CR_DIVPEN BIT(4)
+#define RCC_PLL4CR_DIVQEN BIT(5)
+#define RCC_PLL4CR_DIVREN BIT(6)
+
+/* RCC_PLL4CFGR1 register fields */
+#define RCC_PLL4CFGR1_DIVN_MASK GENMASK(8, 0)
+#define RCC_PLL4CFGR1_DIVM4_MASK GENMASK(21, 16)
+#define RCC_PLL4CFGR1_IFRGE_MASK GENMASK(25, 24)
+#define RCC_PLL4CFGR1_DIVN_SHIFT 0
+#define RCC_PLL4CFGR1_DIVM4_SHIFT 16
+#define RCC_PLL4CFGR1_IFRGE_SHIFT 24
+
+/* RCC_PLL4CFGR2 register fields */
+#define RCC_PLL4CFGR2_DIVP_MASK GENMASK(6, 0)
+#define RCC_PLL4CFGR2_DIVQ_MASK GENMASK(14, 8)
+#define RCC_PLL4CFGR2_DIVR_MASK GENMASK(22, 16)
+#define RCC_PLL4CFGR2_DIVP_SHIFT 0
+#define RCC_PLL4CFGR2_DIVQ_SHIFT 8
+#define RCC_PLL4CFGR2_DIVR_SHIFT 16
+
+/* RCC_PLL4FRACR register fields */
+#define RCC_PLL4FRACR_FRACV_MASK GENMASK(15, 3)
+#define RCC_PLL4FRACR_FRACLE BIT(16)
+#define RCC_PLL4FRACR_FRACV_SHIFT 3
+
+/* RCC_PLL4CSGR register fields */
+#define RCC_PLL4CSGR_MOD_PER_MASK GENMASK(12, 0)
+#define RCC_PLL4CSGR_TPDFN_DIS BIT(13)
+#define RCC_PLL4CSGR_RPDFN_DIS BIT(14)
+#define RCC_PLL4CSGR_SSCG_MODE BIT(15)
+#define RCC_PLL4CSGR_INC_STEP_MASK GENMASK(30, 16)
+#define RCC_PLL4CSGR_MOD_PER_SHIFT 0
+#define RCC_PLL4CSGR_INC_STEP_SHIFT 16
+
+/* RCC_MPCKSELR register fields */
+#define RCC_MPCKSELR_MPUSRC_MASK GENMASK(1, 0)
+#define RCC_MPCKSELR_MPUSRCRDY BIT(31)
+#define RCC_MPCKSELR_MPUSRC_SHIFT 0
+
+/* RCC_ASSCKSELR register fields */
+#define RCC_ASSCKSELR_AXISSRC_MASK GENMASK(2, 0)
+#define RCC_ASSCKSELR_AXISSRCRDY BIT(31)
+#define RCC_ASSCKSELR_AXISSRC_SHIFT 0
+
+/* RCC_MSSCKSELR register fields */
+#define RCC_MSSCKSELR_MLAHBSSRC_MASK GENMASK(1, 0)
+#define RCC_MSSCKSELR_MLAHBSSRCRDY BIT(31)
+#define RCC_MSSCKSELR_MLAHBSSRC_SHIFT 0
+
+/* RCC_CPERCKSELR register fields */
+#define RCC_CPERCKSELR_CKPERSRC_MASK GENMASK(1, 0)
+#define RCC_CPERCKSELR_CKPERSRC_SHIFT 0
+
+/* RCC_RTCDIVR register fields */
+#define RCC_RTCDIVR_RTCDIV_MASK GENMASK(5, 0)
+#define RCC_RTCDIVR_RTCDIV_SHIFT 0
+
+/* RCC_MPCKDIVR register fields */
+#define RCC_MPCKDIVR_MPUDIV_MASK GENMASK(3, 0)
+#define RCC_MPCKDIVR_MPUDIVRDY BIT(31)
+#define RCC_MPCKDIVR_MPUDIV_SHIFT 0
+
+/* RCC_AXIDIVR register fields */
+#define RCC_AXIDIVR_AXIDIV_MASK GENMASK(2, 0)
+#define RCC_AXIDIVR_AXIDIVRDY BIT(31)
+#define RCC_AXIDIVR_AXIDIV_SHIFT 0
+
+/* RCC_MLAHBDIVR register fields */
+#define RCC_MLAHBDIVR_MLAHBDIV_MASK GENMASK(3, 0)
+#define RCC_MLAHBDIVR_MLAHBDIVRDY BIT(31)
+#define RCC_MLAHBDIVR_MLAHBDIV_SHIFT 0
+
+/* RCC_APB1DIVR register fields */
+#define RCC_APB1DIVR_APB1DIV_MASK GENMASK(2, 0)
+#define RCC_APB1DIVR_APB1DIVRDY BIT(31)
+#define RCC_APB1DIVR_APB1DIV_SHIFT 0
+
+/* RCC_APB2DIVR register fields */
+#define RCC_APB2DIVR_APB2DIV_MASK GENMASK(2, 0)
+#define RCC_APB2DIVR_APB2DIVRDY BIT(31)
+#define RCC_APB2DIVR_APB2DIV_SHIFT 0
+
+/* RCC_APB3DIVR register fields */
+#define RCC_APB3DIVR_APB3DIV_MASK GENMASK(2, 0)
+#define RCC_APB3DIVR_APB3DIVRDY BIT(31)
+#define RCC_APB3DIVR_APB3DIV_SHIFT 0
+
+/* RCC_APB4DIVR register fields */
+#define RCC_APB4DIVR_APB4DIV_MASK GENMASK(2, 0)
+#define RCC_APB4DIVR_APB4DIVRDY BIT(31)
+#define RCC_APB4DIVR_APB4DIV_SHIFT 0
+
+/* RCC_APB5DIVR register fields */
+#define RCC_APB5DIVR_APB5DIV_MASK GENMASK(2, 0)
+#define RCC_APB5DIVR_APB5DIVRDY BIT(31)
+#define RCC_APB5DIVR_APB5DIV_SHIFT 0
+
+/* RCC_APB6DIVR register fields */
+#define RCC_APB6DIVR_APB6DIV_MASK GENMASK(2, 0)
+#define RCC_APB6DIVR_APB6DIVRDY BIT(31)
+#define RCC_APB6DIVR_APB6DIV_SHIFT 0
+
+/* RCC_TIMG1PRER register fields */
+#define RCC_TIMG1PRER_TIMG1PRE BIT(0)
+#define RCC_TIMG1PRER_TIMG1PRERDY BIT(31)
+
+/* RCC_TIMG2PRER register fields */
+#define RCC_TIMG2PRER_TIMG2PRE BIT(0)
+#define RCC_TIMG2PRER_TIMG2PRERDY BIT(31)
+
+/* RCC_TIMG3PRER register fields */
+#define RCC_TIMG3PRER_TIMG3PRE BIT(0)
+#define RCC_TIMG3PRER_TIMG3PRERDY BIT(31)
+
+/* RCC_DDRITFCR register fields */
+#define RCC_DDRITFCR_DDRC1EN BIT(0)
+#define RCC_DDRITFCR_DDRC1LPEN BIT(1)
+#define RCC_DDRITFCR_DDRPHYCEN BIT(4)
+#define RCC_DDRITFCR_DDRPHYCLPEN BIT(5)
+#define RCC_DDRITFCR_DDRCAPBEN BIT(6)
+#define RCC_DDRITFCR_DDRCAPBLPEN BIT(7)
+#define RCC_DDRITFCR_AXIDCGEN BIT(8)
+#define RCC_DDRITFCR_DDRPHYCAPBEN BIT(9)
+#define RCC_DDRITFCR_DDRPHYCAPBLPEN BIT(10)
+#define RCC_DDRITFCR_KERDCG_DLY_MASK GENMASK(13, 11)
+#define RCC_DDRITFCR_DDRCAPBRST BIT(14)
+#define RCC_DDRITFCR_DDRCAXIRST BIT(15)
+#define RCC_DDRITFCR_DDRCORERST BIT(16)
+#define RCC_DDRITFCR_DPHYAPBRST BIT(17)
+#define RCC_DDRITFCR_DPHYRST BIT(18)
+#define RCC_DDRITFCR_DPHYCTLRST BIT(19)
+#define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK(22, 20)
+#define RCC_DDRITFCR_GSKPMOD BIT(23)
+#define RCC_DDRITFCR_GSKPCTRL BIT(24)
+#define RCC_DDRITFCR_DFILP_WIDTH_MASK GENMASK(27, 25)
+#define RCC_DDRITFCR_GSKP_DUR_MASK GENMASK(31, 28)
+#define RCC_DDRITFCR_KERDCG_DLY_SHIFT 11
+#define RCC_DDRITFCR_DDRCKMOD_SHIFT 20
+#define RCC_DDRITFCR_DFILP_WIDTH_SHIFT 25
+#define RCC_DDRITFCR_GSKP_DUR_SHIFT 28
+
+/* RCC_I2C12CKSELR register fields */
+#define RCC_I2C12CKSELR_I2C12SRC_MASK GENMASK(2, 0)
+#define RCC_I2C12CKSELR_I2C12SRC_SHIFT 0
+
+/* RCC_I2C345CKSELR register fields */
+#define RCC_I2C345CKSELR_I2C3SRC_MASK GENMASK(2, 0)
+#define RCC_I2C345CKSELR_I2C4SRC_MASK GENMASK(5, 3)
+#define RCC_I2C345CKSELR_I2C5SRC_MASK GENMASK(8, 6)
+#define RCC_I2C345CKSELR_I2C3SRC_SHIFT 0
+#define RCC_I2C345CKSELR_I2C4SRC_SHIFT 3
+#define RCC_I2C345CKSELR_I2C5SRC_SHIFT 6
+
+/* RCC_SPI2S1CKSELR register fields */
+#define RCC_SPI2S1CKSELR_SPI1SRC_MASK GENMASK(2, 0)
+#define RCC_SPI2S1CKSELR_SPI1SRC_SHIFT 0
+
+/* RCC_SPI2S23CKSELR register fields */
+#define RCC_SPI2S23CKSELR_SPI23SRC_MASK GENMASK(2, 0)
+#define RCC_SPI2S23CKSELR_SPI23SRC_SHIFT 0
+
+/* RCC_SPI45CKSELR register fields */
+#define RCC_SPI45CKSELR_SPI4SRC_MASK GENMASK(2, 0)
+#define RCC_SPI45CKSELR_SPI5SRC_MASK GENMASK(5, 3)
+#define RCC_SPI45CKSELR_SPI4SRC_SHIFT 0
+#define RCC_SPI45CKSELR_SPI5SRC_SHIFT 3
+
+/* RCC_UART12CKSELR register fields */
+#define RCC_UART12CKSELR_UART1SRC_MASK GENMASK(2, 0)
+#define RCC_UART12CKSELR_UART2SRC_MASK GENMASK(5, 3)
+#define RCC_UART12CKSELR_UART1SRC_SHIFT 0
+#define RCC_UART12CKSELR_UART2SRC_SHIFT 3
+
+/* RCC_UART35CKSELR register fields */
+#define RCC_UART35CKSELR_UART35SRC_MASK GENMASK(2, 0)
+#define RCC_UART35CKSELR_UART35SRC_SHIFT 0
+
+/* RCC_UART4CKSELR register fields */
+#define RCC_UART4CKSELR_UART4SRC_MASK GENMASK(2, 0)
+#define RCC_UART4CKSELR_UART4SRC_SHIFT 0
+
+/* RCC_UART6CKSELR register fields */
+#define RCC_UART6CKSELR_UART6SRC_MASK GENMASK(2, 0)
+#define RCC_UART6CKSELR_UART6SRC_SHIFT 0
+
+/* RCC_UART78CKSELR register fields */
+#define RCC_UART78CKSELR_UART78SRC_MASK GENMASK(2, 0)
+#define RCC_UART78CKSELR_UART78SRC_SHIFT 0
+
+/* RCC_LPTIM1CKSELR register fields */
+#define RCC_LPTIM1CKSELR_LPTIM1SRC_MASK GENMASK(2, 0)
+#define RCC_LPTIM1CKSELR_LPTIM1SRC_SHIFT 0
+
+/* RCC_LPTIM23CKSELR register fields */
+#define RCC_LPTIM23CKSELR_LPTIM2SRC_MASK GENMASK(2, 0)
+#define RCC_LPTIM23CKSELR_LPTIM3SRC_MASK GENMASK(5, 3)
+#define RCC_LPTIM23CKSELR_LPTIM2SRC_SHIFT 0
+#define RCC_LPTIM23CKSELR_LPTIM3SRC_SHIFT 3
+
+/* RCC_LPTIM45CKSELR register fields */
+#define RCC_LPTIM45CKSELR_LPTIM45SRC_MASK GENMASK(2, 0)
+#define RCC_LPTIM45CKSELR_LPTIM45SRC_SHIFT 0
+
+/* RCC_SAI1CKSELR register fields */
+#define RCC_SAI1CKSELR_SAI1SRC_MASK GENMASK(2, 0)
+#define RCC_SAI1CKSELR_SAI1SRC_SHIFT 0
+
+/* RCC_SAI2CKSELR register fields */
+#define RCC_SAI2CKSELR_SAI2SRC_MASK GENMASK(2, 0)
+#define RCC_SAI2CKSELR_SAI2SRC_SHIFT 0
+
+/* RCC_FDCANCKSELR register fields */
+#define RCC_FDCANCKSELR_FDCANSRC_MASK GENMASK(1, 0)
+#define RCC_FDCANCKSELR_FDCANSRC_SHIFT 0
+
+/* RCC_SPDIFCKSELR register fields */
+#define RCC_SPDIFCKSELR_SPDIFSRC_MASK GENMASK(1, 0)
+#define RCC_SPDIFCKSELR_SPDIFSRC_SHIFT 0
+
+/* RCC_ADC12CKSELR register fields */
+#define RCC_ADC12CKSELR_ADC1SRC_MASK GENMASK(1, 0)
+#define RCC_ADC12CKSELR_ADC2SRC_MASK GENMASK(3, 2)
+#define RCC_ADC12CKSELR_ADC1SRC_SHIFT 0
+#define RCC_ADC12CKSELR_ADC2SRC_SHIFT 2
+
+/* RCC_SDMMC12CKSELR register fields */
+#define RCC_SDMMC12CKSELR_SDMMC1SRC_MASK GENMASK(2, 0)
+#define RCC_SDMMC12CKSELR_SDMMC2SRC_MASK GENMASK(5, 3)
+#define RCC_SDMMC12CKSELR_SDMMC1SRC_SHIFT 0
+#define RCC_SDMMC12CKSELR_SDMMC2SRC_SHIFT 3
+
+/* RCC_ETH12CKSELR register fields */
+#define RCC_ETH12CKSELR_ETH1SRC_MASK GENMASK(1, 0)
+#define RCC_ETH12CKSELR_ETH1PTPDIV_MASK GENMASK(7, 4)
+#define RCC_ETH12CKSELR_ETH2SRC_MASK GENMASK(9, 8)
+#define RCC_ETH12CKSELR_ETH2PTPDIV_MASK GENMASK(15, 12)
+#define RCC_ETH12CKSELR_ETH1SRC_SHIFT 0
+#define RCC_ETH12CKSELR_ETH1PTPDIV_SHIFT 4
+#define RCC_ETH12CKSELR_ETH2SRC_SHIFT 8
+#define RCC_ETH12CKSELR_ETH2PTPDIV_SHIFT 12
+
+/* RCC_USBCKSELR register fields */
+#define RCC_USBCKSELR_USBPHYSRC_MASK GENMASK(1, 0)
+#define RCC_USBCKSELR_USBOSRC BIT(4)
+#define RCC_USBCKSELR_USBPHYSRC_SHIFT 0
+
+/* RCC_QSPICKSELR register fields */
+#define RCC_QSPICKSELR_QSPISRC_MASK GENMASK(1, 0)
+#define RCC_QSPICKSELR_QSPISRC_SHIFT 0
+
+/* RCC_FMCCKSELR register fields */
+#define RCC_FMCCKSELR_FMCSRC_MASK GENMASK(1, 0)
+#define RCC_FMCCKSELR_FMCSRC_SHIFT 0
+
+/* RCC_RNG1CKSELR register fields */
+#define RCC_RNG1CKSELR_RNG1SRC_MASK GENMASK(1, 0)
+#define RCC_RNG1CKSELR_RNG1SRC_SHIFT 0
+
+/* RCC_STGENCKSELR register fields */
+#define RCC_STGENCKSELR_STGENSRC_MASK GENMASK(1, 0)
+#define RCC_STGENCKSELR_STGENSRC_SHIFT 0
+
+/* RCC_DCMIPPCKSELR register fields */
+#define RCC_DCMIPPCKSELR_DCMIPPSRC_MASK GENMASK(1, 0)
+#define RCC_DCMIPPCKSELR_DCMIPPSRC_SHIFT 0
+
+/* RCC_SAESCKSELR register fields */
+#define RCC_SAESCKSELR_SAESSRC_MASK GENMASK(1, 0)
+#define RCC_SAESCKSELR_SAESSRC_SHIFT 0
+
+/* RCC_APB1RSTSETR register fields */
+#define RCC_APB1RSTSETR_TIM2RST BIT(0)
+#define RCC_APB1RSTSETR_TIM3RST BIT(1)
+#define RCC_APB1RSTSETR_TIM4RST BIT(2)
+#define RCC_APB1RSTSETR_TIM5RST BIT(3)
+#define RCC_APB1RSTSETR_TIM6RST BIT(4)
+#define RCC_APB1RSTSETR_TIM7RST BIT(5)
+#define RCC_APB1RSTSETR_LPTIM1RST BIT(9)
+#define RCC_APB1RSTSETR_SPI2RST BIT(11)
+#define RCC_APB1RSTSETR_SPI3RST BIT(12)
+#define RCC_APB1RSTSETR_USART3RST BIT(15)
+#define RCC_APB1RSTSETR_UART4RST BIT(16)
+#define RCC_APB1RSTSETR_UART5RST BIT(17)
+#define RCC_APB1RSTSETR_UART7RST BIT(18)
+#define RCC_APB1RSTSETR_UART8RST BIT(19)
+#define RCC_APB1RSTSETR_I2C1RST BIT(21)
+#define RCC_APB1RSTSETR_I2C2RST BIT(22)
+#define RCC_APB1RSTSETR_SPDIFRST BIT(26)
+
+/* RCC_APB1RSTCLRR register fields */
+#define RCC_APB1RSTCLRR_TIM2RST BIT(0)
+#define RCC_APB1RSTCLRR_TIM3RST BIT(1)
+#define RCC_APB1RSTCLRR_TIM4RST BIT(2)
+#define RCC_APB1RSTCLRR_TIM5RST BIT(3)
+#define RCC_APB1RSTCLRR_TIM6RST BIT(4)
+#define RCC_APB1RSTCLRR_TIM7RST BIT(5)
+#define RCC_APB1RSTCLRR_LPTIM1RST BIT(9)
+#define RCC_APB1RSTCLRR_SPI2RST BIT(11)
+#define RCC_APB1RSTCLRR_SPI3RST BIT(12)
+#define RCC_APB1RSTCLRR_USART3RST BIT(15)
+#define RCC_APB1RSTCLRR_UART4RST BIT(16)
+#define RCC_APB1RSTCLRR_UART5RST BIT(17)
+#define RCC_APB1RSTCLRR_UART7RST BIT(18)
+#define RCC_APB1RSTCLRR_UART8RST BIT(19)
+#define RCC_APB1RSTCLRR_I2C1RST BIT(21)
+#define RCC_APB1RSTCLRR_I2C2RST BIT(22)
+#define RCC_APB1RSTCLRR_SPDIFRST BIT(26)
+
+/* RCC_APB2RSTSETR register fields */
+#define RCC_APB2RSTSETR_TIM1RST BIT(0)
+#define RCC_APB2RSTSETR_TIM8RST BIT(1)
+#define RCC_APB2RSTSETR_SPI1RST BIT(8)
+#define RCC_APB2RSTSETR_USART6RST BIT(13)
+#define RCC_APB2RSTSETR_SAI1RST BIT(16)
+#define RCC_APB2RSTSETR_SAI2RST BIT(17)
+#define RCC_APB2RSTSETR_DFSDMRST BIT(20)
+#define RCC_APB2RSTSETR_FDCANRST BIT(24)
+
+/* RCC_APB2RSTCLRR register fields */
+#define RCC_APB2RSTCLRR_TIM1RST BIT(0)
+#define RCC_APB2RSTCLRR_TIM8RST BIT(1)
+#define RCC_APB2RSTCLRR_SPI1RST BIT(8)
+#define RCC_APB2RSTCLRR_USART6RST BIT(13)
+#define RCC_APB2RSTCLRR_SAI1RST BIT(16)
+#define RCC_APB2RSTCLRR_SAI2RST BIT(17)
+#define RCC_APB2RSTCLRR_DFSDMRST BIT(20)
+#define RCC_APB2RSTCLRR_FDCANRST BIT(24)
+
+/* RCC_APB3RSTSETR register fields */
+#define RCC_APB3RSTSETR_LPTIM2RST BIT(0)
+#define RCC_APB3RSTSETR_LPTIM3RST BIT(1)
+#define RCC_APB3RSTSETR_LPTIM4RST BIT(2)
+#define RCC_APB3RSTSETR_LPTIM5RST BIT(3)
+#define RCC_APB3RSTSETR_SYSCFGRST BIT(11)
+#define RCC_APB3RSTSETR_VREFRST BIT(13)
+#define RCC_APB3RSTSETR_DTSRST BIT(16)
+#define RCC_APB3RSTSETR_PMBCTRLRST BIT(17)
+
+/* RCC_APB3RSTCLRR register fields */
+#define RCC_APB3RSTCLRR_LPTIM2RST BIT(0)
+#define RCC_APB3RSTCLRR_LPTIM3RST BIT(1)
+#define RCC_APB3RSTCLRR_LPTIM4RST BIT(2)
+#define RCC_APB3RSTCLRR_LPTIM5RST BIT(3)
+#define RCC_APB3RSTCLRR_SYSCFGRST BIT(11)
+#define RCC_APB3RSTCLRR_VREFRST BIT(13)
+#define RCC_APB3RSTCLRR_DTSRST BIT(16)
+#define RCC_APB3RSTCLRR_PMBCTRLRST BIT(17)
+
+/* RCC_APB4RSTSETR register fields */
+#define RCC_APB4RSTSETR_LTDCRST BIT(0)
+#define RCC_APB4RSTSETR_DCMIPPRST BIT(1)
+#define RCC_APB4RSTSETR_DDRPERFMRST BIT(8)
+#define RCC_APB4RSTSETR_USBPHYRST BIT(16)
+
+/* RCC_APB4RSTCLRR register fields */
+#define RCC_APB4RSTCLRR_LTDCRST BIT(0)
+#define RCC_APB4RSTCLRR_DCMIPPRST BIT(1)
+#define RCC_APB4RSTCLRR_DDRPERFMRST BIT(8)
+#define RCC_APB4RSTCLRR_USBPHYRST BIT(16)
+
+/* RCC_APB5RSTSETR register fields */
+#define RCC_APB5RSTSETR_STGENRST BIT(20)
+
+/* RCC_APB5RSTCLRR register fields */
+#define RCC_APB5RSTCLRR_STGENRST BIT(20)
+
+/* RCC_APB6RSTSETR register fields */
+#define RCC_APB6RSTSETR_USART1RST BIT(0)
+#define RCC_APB6RSTSETR_USART2RST BIT(1)
+#define RCC_APB6RSTSETR_SPI4RST BIT(2)
+#define RCC_APB6RSTSETR_SPI5RST BIT(3)
+#define RCC_APB6RSTSETR_I2C3RST BIT(4)
+#define RCC_APB6RSTSETR_I2C4RST BIT(5)
+#define RCC_APB6RSTSETR_I2C5RST BIT(6)
+#define RCC_APB6RSTSETR_TIM12RST BIT(7)
+#define RCC_APB6RSTSETR_TIM13RST BIT(8)
+#define RCC_APB6RSTSETR_TIM14RST BIT(9)
+#define RCC_APB6RSTSETR_TIM15RST BIT(10)
+#define RCC_APB6RSTSETR_TIM16RST BIT(11)
+#define RCC_APB6RSTSETR_TIM17RST BIT(12)
+
+/* RCC_APB6RSTCLRR register fields */
+#define RCC_APB6RSTCLRR_USART1RST BIT(0)
+#define RCC_APB6RSTCLRR_USART2RST BIT(1)
+#define RCC_APB6RSTCLRR_SPI4RST BIT(2)
+#define RCC_APB6RSTCLRR_SPI5RST BIT(3)
+#define RCC_APB6RSTCLRR_I2C3RST BIT(4)
+#define RCC_APB6RSTCLRR_I2C4RST BIT(5)
+#define RCC_APB6RSTCLRR_I2C5RST BIT(6)
+#define RCC_APB6RSTCLRR_TIM12RST BIT(7)
+#define RCC_APB6RSTCLRR_TIM13RST BIT(8)
+#define RCC_APB6RSTCLRR_TIM14RST BIT(9)
+#define RCC_APB6RSTCLRR_TIM15RST BIT(10)
+#define RCC_APB6RSTCLRR_TIM16RST BIT(11)
+#define RCC_APB6RSTCLRR_TIM17RST BIT(12)
+
+/* RCC_AHB2RSTSETR register fields */
+#define RCC_AHB2RSTSETR_DMA1RST BIT(0)
+#define RCC_AHB2RSTSETR_DMA2RST BIT(1)
+#define RCC_AHB2RSTSETR_DMAMUX1RST BIT(2)
+#define RCC_AHB2RSTSETR_DMA3RST BIT(3)
+#define RCC_AHB2RSTSETR_DMAMUX2RST BIT(4)
+#define RCC_AHB2RSTSETR_ADC1RST BIT(5)
+#define RCC_AHB2RSTSETR_ADC2RST BIT(6)
+#define RCC_AHB2RSTSETR_USBORST BIT(8)
+
+/* RCC_AHB2RSTCLRR register fields */
+#define RCC_AHB2RSTCLRR_DMA1RST BIT(0)
+#define RCC_AHB2RSTCLRR_DMA2RST BIT(1)
+#define RCC_AHB2RSTCLRR_DMAMUX1RST BIT(2)
+#define RCC_AHB2RSTCLRR_DMA3RST BIT(3)
+#define RCC_AHB2RSTCLRR_DMAMUX2RST BIT(4)
+#define RCC_AHB2RSTCLRR_ADC1RST BIT(5)
+#define RCC_AHB2RSTCLRR_ADC2RST BIT(6)
+#define RCC_AHB2RSTCLRR_USBORST BIT(8)
+
+/* RCC_AHB4RSTSETR register fields */
+#define RCC_AHB4RSTSETR_GPIOARST BIT(0)
+#define RCC_AHB4RSTSETR_GPIOBRST BIT(1)
+#define RCC_AHB4RSTSETR_GPIOCRST BIT(2)
+#define RCC_AHB4RSTSETR_GPIODRST BIT(3)
+#define RCC_AHB4RSTSETR_GPIOERST BIT(4)
+#define RCC_AHB4RSTSETR_GPIOFRST BIT(5)
+#define RCC_AHB4RSTSETR_GPIOGRST BIT(6)
+#define RCC_AHB4RSTSETR_GPIOHRST BIT(7)
+#define RCC_AHB4RSTSETR_GPIOIRST BIT(8)
+#define RCC_AHB4RSTSETR_TSCRST BIT(15)
+
+/* RCC_AHB4RSTCLRR register fields */
+#define RCC_AHB4RSTCLRR_GPIOARST BIT(0)
+#define RCC_AHB4RSTCLRR_GPIOBRST BIT(1)
+#define RCC_AHB4RSTCLRR_GPIOCRST BIT(2)
+#define RCC_AHB4RSTCLRR_GPIODRST BIT(3)
+#define RCC_AHB4RSTCLRR_GPIOERST BIT(4)
+#define RCC_AHB4RSTCLRR_GPIOFRST BIT(5)
+#define RCC_AHB4RSTCLRR_GPIOGRST BIT(6)
+#define RCC_AHB4RSTCLRR_GPIOHRST BIT(7)
+#define RCC_AHB4RSTCLRR_GPIOIRST BIT(8)
+#define RCC_AHB4RSTCLRR_TSCRST BIT(15)
+
+/* RCC_AHB5RSTSETR register fields */
+#define RCC_AHB5RSTSETR_PKARST BIT(2)
+#define RCC_AHB5RSTSETR_SAESRST BIT(3)
+#define RCC_AHB5RSTSETR_CRYP1RST BIT(4)
+#define RCC_AHB5RSTSETR_HASH1RST BIT(5)
+#define RCC_AHB5RSTSETR_RNG1RST BIT(6)
+#define RCC_AHB5RSTSETR_AXIMCRST BIT(16)
+
+/* RCC_AHB5RSTCLRR register fields */
+#define RCC_AHB5RSTCLRR_PKARST BIT(2)
+#define RCC_AHB5RSTCLRR_SAESRST BIT(3)
+#define RCC_AHB5RSTCLRR_CRYP1RST BIT(4)
+#define RCC_AHB5RSTCLRR_HASH1RST BIT(5)
+#define RCC_AHB5RSTCLRR_RNG1RST BIT(6)
+#define RCC_AHB5RSTCLRR_AXIMCRST BIT(16)
+
+/* RCC_AHB6RSTSETR register fields */
+#define RCC_AHB6RSTSETR_MDMARST BIT(0)
+#define RCC_AHB6RSTSETR_MCERST BIT(1)
+#define RCC_AHB6RSTSETR_ETH1MACRST BIT(10)
+#define RCC_AHB6RSTSETR_FMCRST BIT(12)
+#define RCC_AHB6RSTSETR_QSPIRST BIT(14)
+#define RCC_AHB6RSTSETR_SDMMC1RST BIT(16)
+#define RCC_AHB6RSTSETR_SDMMC2RST BIT(17)
+#define RCC_AHB6RSTSETR_CRC1RST BIT(20)
+#define RCC_AHB6RSTSETR_USBHRST BIT(24)
+#define RCC_AHB6RSTSETR_ETH2MACRST BIT(30)
+
+/* RCC_AHB6RSTCLRR register fields */
+#define RCC_AHB6RSTCLRR_MDMARST BIT(0)
+#define RCC_AHB6RSTCLRR_MCERST BIT(1)
+#define RCC_AHB6RSTCLRR_ETH1MACRST BIT(10)
+#define RCC_AHB6RSTCLRR_FMCRST BIT(12)
+#define RCC_AHB6RSTCLRR_QSPIRST BIT(14)
+#define RCC_AHB6RSTCLRR_SDMMC1RST BIT(16)
+#define RCC_AHB6RSTCLRR_SDMMC2RST BIT(17)
+#define RCC_AHB6RSTCLRR_CRC1RST BIT(20)
+#define RCC_AHB6RSTCLRR_USBHRST BIT(24)
+#define RCC_AHB6RSTCLRR_ETH2MACRST BIT(30)
+
+/* RCC_MP_APB1ENSETR register fields */
+#define RCC_MP_APB1ENSETR_TIM2EN BIT(0)
+#define RCC_MP_APB1ENSETR_TIM3EN BIT(1)
+#define RCC_MP_APB1ENSETR_TIM4EN BIT(2)
+#define RCC_MP_APB1ENSETR_TIM5EN BIT(3)
+#define RCC_MP_APB1ENSETR_TIM6EN BIT(4)
+#define RCC_MP_APB1ENSETR_TIM7EN BIT(5)
+#define RCC_MP_APB1ENSETR_LPTIM1EN BIT(9)
+#define RCC_MP_APB1ENSETR_SPI2EN BIT(11)
+#define RCC_MP_APB1ENSETR_SPI3EN BIT(12)
+#define RCC_MP_APB1ENSETR_USART3EN BIT(15)
+#define RCC_MP_APB1ENSETR_UART4EN BIT(16)
+#define RCC_MP_APB1ENSETR_UART5EN BIT(17)
+#define RCC_MP_APB1ENSETR_UART7EN BIT(18)
+#define RCC_MP_APB1ENSETR_UART8EN BIT(19)
+#define RCC_MP_APB1ENSETR_I2C1EN BIT(21)
+#define RCC_MP_APB1ENSETR_I2C2EN BIT(22)
+#define RCC_MP_APB1ENSETR_SPDIFEN BIT(26)
+
+/* RCC_MP_APB1ENCLRR register fields */
+#define RCC_MP_APB1ENCLRR_TIM2EN BIT(0)
+#define RCC_MP_APB1ENCLRR_TIM3EN BIT(1)
+#define RCC_MP_APB1ENCLRR_TIM4EN BIT(2)
+#define RCC_MP_APB1ENCLRR_TIM5EN BIT(3)
+#define RCC_MP_APB1ENCLRR_TIM6EN BIT(4)
+#define RCC_MP_APB1ENCLRR_TIM7EN BIT(5)
+#define RCC_MP_APB1ENCLRR_LPTIM1EN BIT(9)
+#define RCC_MP_APB1ENCLRR_SPI2EN BIT(11)
+#define RCC_MP_APB1ENCLRR_SPI3EN BIT(12)
+#define RCC_MP_APB1ENCLRR_USART3EN BIT(15)
+#define RCC_MP_APB1ENCLRR_UART4EN BIT(16)
+#define RCC_MP_APB1ENCLRR_UART5EN BIT(17)
+#define RCC_MP_APB1ENCLRR_UART7EN BIT(18)
+#define RCC_MP_APB1ENCLRR_UART8EN BIT(19)
+#define RCC_MP_APB1ENCLRR_I2C1EN BIT(21)
+#define RCC_MP_APB1ENCLRR_I2C2EN BIT(22)
+#define RCC_MP_APB1ENCLRR_SPDIFEN BIT(26)
+
+/* RCC_MP_APB2ENSETR register fields */
+#define RCC_MP_APB2ENSETR_TIM1EN BIT(0)
+#define RCC_MP_APB2ENSETR_TIM8EN BIT(1)
+#define RCC_MP_APB2ENSETR_SPI1EN BIT(8)
+#define RCC_MP_APB2ENSETR_USART6EN BIT(13)
+#define RCC_MP_APB2ENSETR_SAI1EN BIT(16)
+#define RCC_MP_APB2ENSETR_SAI2EN BIT(17)
+#define RCC_MP_APB2ENSETR_DFSDMEN BIT(20)
+#define RCC_MP_APB2ENSETR_ADFSDMEN BIT(21)
+#define RCC_MP_APB2ENSETR_FDCANEN BIT(24)
+
+/* RCC_MP_APB2ENCLRR register fields */
+#define RCC_MP_APB2ENCLRR_TIM1EN BIT(0)
+#define RCC_MP_APB2ENCLRR_TIM8EN BIT(1)
+#define RCC_MP_APB2ENCLRR_SPI1EN BIT(8)
+#define RCC_MP_APB2ENCLRR_USART6EN BIT(13)
+#define RCC_MP_APB2ENCLRR_SAI1EN BIT(16)
+#define RCC_MP_APB2ENCLRR_SAI2EN BIT(17)
+#define RCC_MP_APB2ENCLRR_DFSDMEN BIT(20)
+#define RCC_MP_APB2ENCLRR_ADFSDMEN BIT(21)
+#define RCC_MP_APB2ENCLRR_FDCANEN BIT(24)
+
+/* RCC_MP_APB3ENSETR register fields */
+#define RCC_MP_APB3ENSETR_LPTIM2EN BIT(0)
+#define RCC_MP_APB3ENSETR_LPTIM3EN BIT(1)
+#define RCC_MP_APB3ENSETR_LPTIM4EN BIT(2)
+#define RCC_MP_APB3ENSETR_LPTIM5EN BIT(3)
+#define RCC_MP_APB3ENSETR_VREFEN BIT(13)
+#define RCC_MP_APB3ENSETR_DTSEN BIT(16)
+#define RCC_MP_APB3ENSETR_PMBCTRLEN BIT(17)
+#define RCC_MP_APB3ENSETR_HDPEN BIT(20)
+
+/* RCC_MP_APB3ENCLRR register fields */
+#define RCC_MP_APB3ENCLRR_LPTIM2EN BIT(0)
+#define RCC_MP_APB3ENCLRR_LPTIM3EN BIT(1)
+#define RCC_MP_APB3ENCLRR_LPTIM4EN BIT(2)
+#define RCC_MP_APB3ENCLRR_LPTIM5EN BIT(3)
+#define RCC_MP_APB3ENCLRR_VREFEN BIT(13)
+#define RCC_MP_APB3ENCLRR_DTSEN BIT(16)
+#define RCC_MP_APB3ENCLRR_PMBCTRLEN BIT(17)
+#define RCC_MP_APB3ENCLRR_HDPEN BIT(20)
+
+/* RCC_MP_S_APB3ENSETR register fields */
+#define RCC_MP_S_APB3ENSETR_SYSCFGEN BIT(0)
+
+/* RCC_MP_S_APB3ENCLRR register fields */
+#define RCC_MP_S_APB3ENCLRR_SYSCFGEN BIT(0)
+
+/* RCC_MP_NS_APB3ENSETR register fields */
+#define RCC_MP_NS_APB3ENSETR_SYSCFGEN BIT(0)
+
+/* RCC_MP_NS_APB3ENCLRR register fields */
+#define RCC_MP_NS_APB3ENCLRR_SYSCFGEN BIT(0)
+
+/* RCC_MP_APB4ENSETR register fields */
+#define RCC_MP_APB4ENSETR_DCMIPPEN BIT(1)
+#define RCC_MP_APB4ENSETR_DDRPERFMEN BIT(8)
+#define RCC_MP_APB4ENSETR_IWDG2APBEN BIT(15)
+#define RCC_MP_APB4ENSETR_USBPHYEN BIT(16)
+#define RCC_MP_APB4ENSETR_STGENROEN BIT(20)
+
+/* RCC_MP_APB4ENCLRR register fields */
+#define RCC_MP_APB4ENCLRR_DCMIPPEN BIT(1)
+#define RCC_MP_APB4ENCLRR_DDRPERFMEN BIT(8)
+#define RCC_MP_APB4ENCLRR_IWDG2APBEN BIT(15)
+#define RCC_MP_APB4ENCLRR_USBPHYEN BIT(16)
+#define RCC_MP_APB4ENCLRR_STGENROEN BIT(20)
+
+/* RCC_MP_S_APB4ENSETR register fields */
+#define RCC_MP_S_APB4ENSETR_LTDCEN BIT(0)
+
+/* RCC_MP_S_APB4ENCLRR register fields */
+#define RCC_MP_S_APB4ENCLRR_LTDCEN BIT(0)
+
+/* RCC_MP_NS_APB4ENSETR register fields */
+#define RCC_MP_NS_APB4ENSETR_LTDCEN BIT(0)
+
+/* RCC_MP_NS_APB4ENCLRR register fields */
+#define RCC_MP_NS_APB4ENCLRR_LTDCEN BIT(0)
+
+/* RCC_MP_APB5ENSETR register fields */
+#define RCC_MP_APB5ENSETR_RTCAPBEN BIT(8)
+#define RCC_MP_APB5ENSETR_TZCEN BIT(11)
+#define RCC_MP_APB5ENSETR_ETZPCEN BIT(13)
+#define RCC_MP_APB5ENSETR_IWDG1APBEN BIT(15)
+#define RCC_MP_APB5ENSETR_BSECEN BIT(16)
+#define RCC_MP_APB5ENSETR_STGENCEN BIT(20)
+
+/* RCC_MP_APB5ENCLRR register fields */
+#define RCC_MP_APB5ENCLRR_RTCAPBEN BIT(8)
+#define RCC_MP_APB5ENCLRR_TZCEN BIT(11)
+#define RCC_MP_APB5ENCLRR_ETZPCEN BIT(13)
+#define RCC_MP_APB5ENCLRR_IWDG1APBEN BIT(15)
+#define RCC_MP_APB5ENCLRR_BSECEN BIT(16)
+#define RCC_MP_APB5ENCLRR_STGENCEN BIT(20)
+
+/* RCC_MP_APB6ENSETR register fields */
+#define RCC_MP_APB6ENSETR_USART1EN BIT(0)
+#define RCC_MP_APB6ENSETR_USART2EN BIT(1)
+#define RCC_MP_APB6ENSETR_SPI4EN BIT(2)
+#define RCC_MP_APB6ENSETR_SPI5EN BIT(3)
+#define RCC_MP_APB6ENSETR_I2C3EN BIT(4)
+#define RCC_MP_APB6ENSETR_I2C4EN BIT(5)
+#define RCC_MP_APB6ENSETR_I2C5EN BIT(6)
+#define RCC_MP_APB6ENSETR_TIM12EN BIT(7)
+#define RCC_MP_APB6ENSETR_TIM13EN BIT(8)
+#define RCC_MP_APB6ENSETR_TIM14EN BIT(9)
+#define RCC_MP_APB6ENSETR_TIM15EN BIT(10)
+#define RCC_MP_APB6ENSETR_TIM16EN BIT(11)
+#define RCC_MP_APB6ENSETR_TIM17EN BIT(12)
+
+/* RCC_MP_APB6ENCLRR register fields */
+#define RCC_MP_APB6ENCLRR_USART1EN BIT(0)
+#define RCC_MP_APB6ENCLRR_USART2EN BIT(1)
+#define RCC_MP_APB6ENCLRR_SPI4EN BIT(2)
+#define RCC_MP_APB6ENCLRR_SPI5EN BIT(3)
+#define RCC_MP_APB6ENCLRR_I2C3EN BIT(4)
+#define RCC_MP_APB6ENCLRR_I2C4EN BIT(5)
+#define RCC_MP_APB6ENCLRR_I2C5EN BIT(6)
+#define RCC_MP_APB6ENCLRR_TIM12EN BIT(7)
+#define RCC_MP_APB6ENCLRR_TIM13EN BIT(8)
+#define RCC_MP_APB6ENCLRR_TIM14EN BIT(9)
+#define RCC_MP_APB6ENCLRR_TIM15EN BIT(10)
+#define RCC_MP_APB6ENCLRR_TIM16EN BIT(11)
+#define RCC_MP_APB6ENCLRR_TIM17EN BIT(12)
+
+/* RCC_MP_AHB2ENSETR register fields */
+#define RCC_MP_AHB2ENSETR_DMA1EN BIT(0)
+#define RCC_MP_AHB2ENSETR_DMA2EN BIT(1)
+#define RCC_MP_AHB2ENSETR_DMAMUX1EN BIT(2)
+#define RCC_MP_AHB2ENSETR_DMA3EN BIT(3)
+#define RCC_MP_AHB2ENSETR_DMAMUX2EN BIT(4)
+#define RCC_MP_AHB2ENSETR_ADC1EN BIT(5)
+#define RCC_MP_AHB2ENSETR_ADC2EN BIT(6)
+#define RCC_MP_AHB2ENSETR_USBOEN BIT(8)
+
+/* RCC_MP_AHB2ENCLRR register fields */
+#define RCC_MP_AHB2ENCLRR_DMA1EN BIT(0)
+#define RCC_MP_AHB2ENCLRR_DMA2EN BIT(1)
+#define RCC_MP_AHB2ENCLRR_DMAMUX1EN BIT(2)
+#define RCC_MP_AHB2ENCLRR_DMA3EN BIT(3)
+#define RCC_MP_AHB2ENCLRR_DMAMUX2EN BIT(4)
+#define RCC_MP_AHB2ENCLRR_ADC1EN BIT(5)
+#define RCC_MP_AHB2ENCLRR_ADC2EN BIT(6)
+#define RCC_MP_AHB2ENCLRR_USBOEN BIT(8)
+
+/* RCC_MP_AHB4ENSETR register fields */
+#define RCC_MP_AHB4ENSETR_TSCEN BIT(15)
+
+/* RCC_MP_AHB4ENCLRR register fields */
+#define RCC_MP_AHB4ENCLRR_TSCEN BIT(15)
+
+/* RCC_MP_S_AHB4ENSETR register fields */
+#define RCC_MP_S_AHB4ENSETR_GPIOAEN BIT(0)
+#define RCC_MP_S_AHB4ENSETR_GPIOBEN BIT(1)
+#define RCC_MP_S_AHB4ENSETR_GPIOCEN BIT(2)
+#define RCC_MP_S_AHB4ENSETR_GPIODEN BIT(3)
+#define RCC_MP_S_AHB4ENSETR_GPIOEEN BIT(4)
+#define RCC_MP_S_AHB4ENSETR_GPIOFEN BIT(5)
+#define RCC_MP_S_AHB4ENSETR_GPIOGEN BIT(6)
+#define RCC_MP_S_AHB4ENSETR_GPIOHEN BIT(7)
+#define RCC_MP_S_AHB4ENSETR_GPIOIEN BIT(8)
+
+/* RCC_MP_S_AHB4ENCLRR register fields */
+#define RCC_MP_S_AHB4ENCLRR_GPIOAEN BIT(0)
+#define RCC_MP_S_AHB4ENCLRR_GPIOBEN BIT(1)
+#define RCC_MP_S_AHB4ENCLRR_GPIOCEN BIT(2)
+#define RCC_MP_S_AHB4ENCLRR_GPIODEN BIT(3)
+#define RCC_MP_S_AHB4ENCLRR_GPIOEEN BIT(4)
+#define RCC_MP_S_AHB4ENCLRR_GPIOFEN BIT(5)
+#define RCC_MP_S_AHB4ENCLRR_GPIOGEN BIT(6)
+#define RCC_MP_S_AHB4ENCLRR_GPIOHEN BIT(7)
+#define RCC_MP_S_AHB4ENCLRR_GPIOIEN BIT(8)
+
+/* RCC_MP_NS_AHB4ENSETR register fields */
+#define RCC_MP_NS_AHB4ENSETR_GPIOAEN BIT(0)
+#define RCC_MP_NS_AHB4ENSETR_GPIOBEN BIT(1)
+#define RCC_MP_NS_AHB4ENSETR_GPIOCEN BIT(2)
+#define RCC_MP_NS_AHB4ENSETR_GPIODEN BIT(3)
+#define RCC_MP_NS_AHB4ENSETR_GPIOEEN BIT(4)
+#define RCC_MP_NS_AHB4ENSETR_GPIOFEN BIT(5)
+#define RCC_MP_NS_AHB4ENSETR_GPIOGEN BIT(6)
+#define RCC_MP_NS_AHB4ENSETR_GPIOHEN BIT(7)
+#define RCC_MP_NS_AHB4ENSETR_GPIOIEN BIT(8)
+
+/* RCC_MP_NS_AHB4ENCLRR register fields */
+#define RCC_MP_NS_AHB4ENCLRR_GPIOAEN BIT(0)
+#define RCC_MP_NS_AHB4ENCLRR_GPIOBEN BIT(1)
+#define RCC_MP_NS_AHB4ENCLRR_GPIOCEN BIT(2)
+#define RCC_MP_NS_AHB4ENCLRR_GPIODEN BIT(3)
+#define RCC_MP_NS_AHB4ENCLRR_GPIOEEN BIT(4)
+#define RCC_MP_NS_AHB4ENCLRR_GPIOFEN BIT(5)
+#define RCC_MP_NS_AHB4ENCLRR_GPIOGEN BIT(6)
+#define RCC_MP_NS_AHB4ENCLRR_GPIOHEN BIT(7)
+#define RCC_MP_NS_AHB4ENCLRR_GPIOIEN BIT(8)
+
+/* RCC_MP_AHB5ENSETR register fields */
+#define RCC_MP_AHB5ENSETR_PKAEN BIT(2)
+#define RCC_MP_AHB5ENSETR_SAESEN BIT(3)
+#define RCC_MP_AHB5ENSETR_CRYP1EN BIT(4)
+#define RCC_MP_AHB5ENSETR_HASH1EN BIT(5)
+#define RCC_MP_AHB5ENSETR_RNG1EN BIT(6)
+#define RCC_MP_AHB5ENSETR_BKPSRAMEN BIT(8)
+#define RCC_MP_AHB5ENSETR_AXIMCEN BIT(16)
+
+/* RCC_MP_AHB5ENCLRR register fields */
+#define RCC_MP_AHB5ENCLRR_PKAEN BIT(2)
+#define RCC_MP_AHB5ENCLRR_SAESEN BIT(3)
+#define RCC_MP_AHB5ENCLRR_CRYP1EN BIT(4)
+#define RCC_MP_AHB5ENCLRR_HASH1EN BIT(5)
+#define RCC_MP_AHB5ENCLRR_RNG1EN BIT(6)
+#define RCC_MP_AHB5ENCLRR_BKPSRAMEN BIT(8)
+#define RCC_MP_AHB5ENCLRR_AXIMCEN BIT(16)
+
+/* RCC_MP_AHB6ENSETR register fields */
+#define RCC_MP_AHB6ENSETR_MCEEN BIT(1)
+#define RCC_MP_AHB6ENSETR_ETH1CKEN BIT(7)
+#define RCC_MP_AHB6ENSETR_ETH1TXEN BIT(8)
+#define RCC_MP_AHB6ENSETR_ETH1RXEN BIT(9)
+#define RCC_MP_AHB6ENSETR_ETH1MACEN BIT(10)
+#define RCC_MP_AHB6ENSETR_FMCEN BIT(12)
+#define RCC_MP_AHB6ENSETR_QSPIEN BIT(14)
+#define RCC_MP_AHB6ENSETR_SDMMC1EN BIT(16)
+#define RCC_MP_AHB6ENSETR_SDMMC2EN BIT(17)
+#define RCC_MP_AHB6ENSETR_CRC1EN BIT(20)
+#define RCC_MP_AHB6ENSETR_USBHEN BIT(24)
+#define RCC_MP_AHB6ENSETR_ETH2CKEN BIT(27)
+#define RCC_MP_AHB6ENSETR_ETH2TXEN BIT(28)
+#define RCC_MP_AHB6ENSETR_ETH2RXEN BIT(29)
+#define RCC_MP_AHB6ENSETR_ETH2MACEN BIT(30)
+
+/* RCC_MP_AHB6ENCLRR register fields */
+#define RCC_MP_AHB6ENCLRR_MCEEN BIT(1)
+#define RCC_MP_AHB6ENCLRR_ETH1CKEN BIT(7)
+#define RCC_MP_AHB6ENCLRR_ETH1TXEN BIT(8)
+#define RCC_MP_AHB6ENCLRR_ETH1RXEN BIT(9)
+#define RCC_MP_AHB6ENCLRR_ETH1MACEN BIT(10)
+#define RCC_MP_AHB6ENCLRR_FMCEN BIT(12)
+#define RCC_MP_AHB6ENCLRR_QSPIEN BIT(14)
+#define RCC_MP_AHB6ENCLRR_SDMMC1EN BIT(16)
+#define RCC_MP_AHB6ENCLRR_SDMMC2EN BIT(17)
+#define RCC_MP_AHB6ENCLRR_CRC1EN BIT(20)
+#define RCC_MP_AHB6ENCLRR_USBHEN BIT(24)
+#define RCC_MP_AHB6ENCLRR_ETH2CKEN BIT(27)
+#define RCC_MP_AHB6ENCLRR_ETH2TXEN BIT(28)
+#define RCC_MP_AHB6ENCLRR_ETH2RXEN BIT(29)
+#define RCC_MP_AHB6ENCLRR_ETH2MACEN BIT(30)
+
+/* RCC_MP_S_AHB6ENSETR register fields */
+#define RCC_MP_S_AHB6ENSETR_MDMAEN BIT(0)
+
+/* RCC_MP_S_AHB6ENCLRR register fields */
+#define RCC_MP_S_AHB6ENCLRR_MDMAEN BIT(0)
+
+/* RCC_MP_NS_AHB6ENSETR register fields */
+#define RCC_MP_NS_AHB6ENSETR_MDMAEN BIT(0)
+
+/* RCC_MP_NS_AHB6ENCLRR register fields */
+#define RCC_MP_NS_AHB6ENCLRR_MDMAEN BIT(0)
+
+/* RCC_MP_APB1LPENSETR register fields */
+#define RCC_MP_APB1LPENSETR_TIM2LPEN BIT(0)
+#define RCC_MP_APB1LPENSETR_TIM3LPEN BIT(1)
+#define RCC_MP_APB1LPENSETR_TIM4LPEN BIT(2)
+#define RCC_MP_APB1LPENSETR_TIM5LPEN BIT(3)
+#define RCC_MP_APB1LPENSETR_TIM6LPEN BIT(4)
+#define RCC_MP_APB1LPENSETR_TIM7LPEN BIT(5)
+#define RCC_MP_APB1LPENSETR_LPTIM1LPEN BIT(9)
+#define RCC_MP_APB1LPENSETR_SPI2LPEN BIT(11)
+#define RCC_MP_APB1LPENSETR_SPI3LPEN BIT(12)
+#define RCC_MP_APB1LPENSETR_USART3LPEN BIT(15)
+#define RCC_MP_APB1LPENSETR_UART4LPEN BIT(16)
+#define RCC_MP_APB1LPENSETR_UART5LPEN BIT(17)
+#define RCC_MP_APB1LPENSETR_UART7LPEN BIT(18)
+#define RCC_MP_APB1LPENSETR_UART8LPEN BIT(19)
+#define RCC_MP_APB1LPENSETR_I2C1LPEN BIT(21)
+#define RCC_MP_APB1LPENSETR_I2C2LPEN BIT(22)
+#define RCC_MP_APB1LPENSETR_SPDIFLPEN BIT(26)
+
+/* RCC_MP_APB1LPENCLRR register fields */
+#define RCC_MP_APB1LPENCLRR_TIM2LPEN BIT(0)
+#define RCC_MP_APB1LPENCLRR_TIM3LPEN BIT(1)
+#define RCC_MP_APB1LPENCLRR_TIM4LPEN BIT(2)
+#define RCC_MP_APB1LPENCLRR_TIM5LPEN BIT(3)
+#define RCC_MP_APB1LPENCLRR_TIM6LPEN BIT(4)
+#define RCC_MP_APB1LPENCLRR_TIM7LPEN BIT(5)
+#define RCC_MP_APB1LPENCLRR_LPTIM1LPEN BIT(9)
+#define RCC_MP_APB1LPENCLRR_SPI2LPEN BIT(11)
+#define RCC_MP_APB1LPENCLRR_SPI3LPEN BIT(12)
+#define RCC_MP_APB1LPENCLRR_USART3LPEN BIT(15)
+#define RCC_MP_APB1LPENCLRR_UART4LPEN BIT(16)
+#define RCC_MP_APB1LPENCLRR_UART5LPEN BIT(17)
+#define RCC_MP_APB1LPENCLRR_UART7LPEN BIT(18)
+#define RCC_MP_APB1LPENCLRR_UART8LPEN BIT(19)
+#define RCC_MP_APB1LPENCLRR_I2C1LPEN BIT(21)
+#define RCC_MP_APB1LPENCLRR_I2C2LPEN BIT(22)
+#define RCC_MP_APB1LPENCLRR_SPDIFLPEN BIT(26)
+
+/* RCC_MP_APB2LPENSETR register fields */
+#define RCC_MP_APB2LPENSETR_TIM1LPEN BIT(0)
+#define RCC_MP_APB2LPENSETR_TIM8LPEN BIT(1)
+#define RCC_MP_APB2LPENSETR_SPI1LPEN BIT(8)
+#define RCC_MP_APB2LPENSETR_USART6LPEN BIT(13)
+#define RCC_MP_APB2LPENSETR_SAI1LPEN BIT(16)
+#define RCC_MP_APB2LPENSETR_SAI2LPEN BIT(17)
+#define RCC_MP_APB2LPENSETR_DFSDMLPEN BIT(20)
+#define RCC_MP_APB2LPENSETR_ADFSDMLPEN BIT(21)
+#define RCC_MP_APB2LPENSETR_FDCANLPEN BIT(24)
+
+/* RCC_MP_APB2LPENCLRR register fields */
+#define RCC_MP_APB2LPENCLRR_TIM1LPEN BIT(0)
+#define RCC_MP_APB2LPENCLRR_TIM8LPEN BIT(1)
+#define RCC_MP_APB2LPENCLRR_SPI1LPEN BIT(8)
+#define RCC_MP_APB2LPENCLRR_USART6LPEN BIT(13)
+#define RCC_MP_APB2LPENCLRR_SAI1LPEN BIT(16)
+#define RCC_MP_APB2LPENCLRR_SAI2LPEN BIT(17)
+#define RCC_MP_APB2LPENCLRR_DFSDMLPEN BIT(20)
+#define RCC_MP_APB2LPENCLRR_ADFSDMLPEN BIT(21)
+#define RCC_MP_APB2LPENCLRR_FDCANLPEN BIT(24)
+
+/* RCC_MP_APB3LPENSETR register fields */
+#define RCC_MP_APB3LPENSETR_LPTIM2LPEN BIT(0)
+#define RCC_MP_APB3LPENSETR_LPTIM3LPEN BIT(1)
+#define RCC_MP_APB3LPENSETR_LPTIM4LPEN BIT(2)
+#define RCC_MP_APB3LPENSETR_LPTIM5LPEN BIT(3)
+#define RCC_MP_APB3LPENSETR_VREFLPEN BIT(13)
+#define RCC_MP_APB3LPENSETR_DTSLPEN BIT(16)
+#define RCC_MP_APB3LPENSETR_PMBCTRLLPEN BIT(17)
+
+/* RCC_MP_APB3LPENCLRR register fields */
+#define RCC_MP_APB3LPENCLRR_LPTIM2LPEN BIT(0)
+#define RCC_MP_APB3LPENCLRR_LPTIM3LPEN BIT(1)
+#define RCC_MP_APB3LPENCLRR_LPTIM4LPEN BIT(2)
+#define RCC_MP_APB3LPENCLRR_LPTIM5LPEN BIT(3)
+#define RCC_MP_APB3LPENCLRR_VREFLPEN BIT(13)
+#define RCC_MP_APB3LPENCLRR_DTSLPEN BIT(16)
+#define RCC_MP_APB3LPENCLRR_PMBCTRLLPEN BIT(17)
+
+/* RCC_MP_S_APB3LPENSETR register fields */
+#define RCC_MP_S_APB3LPENSETR_SYSCFGLPEN BIT(0)
+
+/* RCC_MP_S_APB3LPENCLRR register fields */
+#define RCC_MP_S_APB3LPENCLRR_SYSCFGLPEN BIT(0)
+
+/* RCC_MP_NS_APB3LPENSETR register fields */
+#define RCC_MP_NS_APB3LPENSETR_SYSCFGLPEN BIT(0)
+
+/* RCC_MP_NS_APB3LPENCLRR register fields */
+#define RCC_MP_NS_APB3LPENCLRR_SYSCFGLPEN BIT(0)
+
+/* RCC_MP_APB4LPENSETR register fields */
+#define RCC_MP_APB4LPENSETR_DCMIPPLPEN BIT(1)
+#define RCC_MP_APB4LPENSETR_DDRPERFMLPEN BIT(8)
+#define RCC_MP_APB4LPENSETR_IWDG2APBLPEN BIT(15)
+#define RCC_MP_APB4LPENSETR_USBPHYLPEN BIT(16)
+#define RCC_MP_APB4LPENSETR_STGENROLPEN BIT(20)
+#define RCC_MP_APB4LPENSETR_STGENROSTPEN BIT(21)
+
+/* RCC_MP_APB4LPENCLRR register fields */
+#define RCC_MP_APB4LPENCLRR_DCMIPPLPEN BIT(1)
+#define RCC_MP_APB4LPENCLRR_DDRPERFMLPEN BIT(8)
+#define RCC_MP_APB4LPENCLRR_IWDG2APBLPEN BIT(15)
+#define RCC_MP_APB4LPENCLRR_USBPHYLPEN BIT(16)
+#define RCC_MP_APB4LPENCLRR_STGENROLPEN BIT(20)
+#define RCC_MP_APB4LPENCLRR_STGENROSTPEN BIT(21)
+
+/* RCC_MP_S_APB4LPENSETR register fields */
+#define RCC_MP_S_APB4LPENSETR_LTDCLPEN BIT(0)
+
+/* RCC_MP_S_APB4LPENCLRR register fields */
+#define RCC_MP_S_APB4LPENCLRR_LTDCLPEN BIT(0)
+
+/* RCC_MP_NS_APB4LPENSETR register fields */
+#define RCC_MP_NS_APB4LPENSETR_LTDCLPEN BIT(0)
+
+/* RCC_MP_NS_APB4LPENCLRR register fields */
+#define RCC_MP_NS_APB4LPENCLRR_LTDCLPEN BIT(0)
+
+/* RCC_MP_APB5LPENSETR register fields */
+#define RCC_MP_APB5LPENSETR_RTCAPBLPEN BIT(8)
+#define RCC_MP_APB5LPENSETR_TZCLPEN BIT(11)
+#define RCC_MP_APB5LPENSETR_ETZPCLPEN BIT(13)
+#define RCC_MP_APB5LPENSETR_IWDG1APBLPEN BIT(15)
+#define RCC_MP_APB5LPENSETR_BSECLPEN BIT(16)
+#define RCC_MP_APB5LPENSETR_STGENCLPEN BIT(20)
+#define RCC_MP_APB5LPENSETR_STGENCSTPEN BIT(21)
+
+/* RCC_MP_APB5LPENCLRR register fields */
+#define RCC_MP_APB5LPENCLRR_RTCAPBLPEN BIT(8)
+#define RCC_MP_APB5LPENCLRR_TZCLPEN BIT(11)
+#define RCC_MP_APB5LPENCLRR_ETZPCLPEN BIT(13)
+#define RCC_MP_APB5LPENCLRR_IWDG1APBLPEN BIT(15)
+#define RCC_MP_APB5LPENCLRR_BSECLPEN BIT(16)
+#define RCC_MP_APB5LPENCLRR_STGENCLPEN BIT(20)
+#define RCC_MP_APB5LPENCLRR_STGENCSTPEN BIT(21)
+
+/* RCC_MP_APB6LPENSETR register fields */
+#define RCC_MP_APB6LPENSETR_USART1LPEN BIT(0)
+#define RCC_MP_APB6LPENSETR_USART2LPEN BIT(1)
+#define RCC_MP_APB6LPENSETR_SPI4LPEN BIT(2)
+#define RCC_MP_APB6LPENSETR_SPI5LPEN BIT(3)
+#define RCC_MP_APB6LPENSETR_I2C3LPEN BIT(4)
+#define RCC_MP_APB6LPENSETR_I2C4LPEN BIT(5)
+#define RCC_MP_APB6LPENSETR_I2C5LPEN BIT(6)
+#define RCC_MP_APB6LPENSETR_TIM12LPEN BIT(7)
+#define RCC_MP_APB6LPENSETR_TIM13LPEN BIT(8)
+#define RCC_MP_APB6LPENSETR_TIM14LPEN BIT(9)
+#define RCC_MP_APB6LPENSETR_TIM15LPEN BIT(10)
+#define RCC_MP_APB6LPENSETR_TIM16LPEN BIT(11)
+#define RCC_MP_APB6LPENSETR_TIM17LPEN BIT(12)
+
+/* RCC_MP_APB6LPENCLRR register fields */
+#define RCC_MP_APB6LPENCLRR_USART1LPEN BIT(0)
+#define RCC_MP_APB6LPENCLRR_USART2LPEN BIT(1)
+#define RCC_MP_APB6LPENCLRR_SPI4LPEN BIT(2)
+#define RCC_MP_APB6LPENCLRR_SPI5LPEN BIT(3)
+#define RCC_MP_APB6LPENCLRR_I2C3LPEN BIT(4)
+#define RCC_MP_APB6LPENCLRR_I2C4LPEN BIT(5)
+#define RCC_MP_APB6LPENCLRR_I2C5LPEN BIT(6)
+#define RCC_MP_APB6LPENCLRR_TIM12LPEN BIT(7)
+#define RCC_MP_APB6LPENCLRR_TIM13LPEN BIT(8)
+#define RCC_MP_APB6LPENCLRR_TIM14LPEN BIT(9)
+#define RCC_MP_APB6LPENCLRR_TIM15LPEN BIT(10)
+#define RCC_MP_APB6LPENCLRR_TIM16LPEN BIT(11)
+#define RCC_MP_APB6LPENCLRR_TIM17LPEN BIT(12)
+
+/* RCC_MP_AHB2LPENSETR register fields */
+#define RCC_MP_AHB2LPENSETR_DMA1LPEN BIT(0)
+#define RCC_MP_AHB2LPENSETR_DMA2LPEN BIT(1)
+#define RCC_MP_AHB2LPENSETR_DMAMUX1LPEN BIT(2)
+#define RCC_MP_AHB2LPENSETR_DMA3LPEN BIT(3)
+#define RCC_MP_AHB2LPENSETR_DMAMUX2LPEN BIT(4)
+#define RCC_MP_AHB2LPENSETR_ADC1LPEN BIT(5)
+#define RCC_MP_AHB2LPENSETR_ADC2LPEN BIT(6)
+#define RCC_MP_AHB2LPENSETR_USBOLPEN BIT(8)
+
+/* RCC_MP_AHB2LPENCLRR register fields */
+#define RCC_MP_AHB2LPENCLRR_DMA1LPEN BIT(0)
+#define RCC_MP_AHB2LPENCLRR_DMA2LPEN BIT(1)
+#define RCC_MP_AHB2LPENCLRR_DMAMUX1LPEN BIT(2)
+#define RCC_MP_AHB2LPENCLRR_DMA3LPEN BIT(3)
+#define RCC_MP_AHB2LPENCLRR_DMAMUX2LPEN BIT(4)
+#define RCC_MP_AHB2LPENCLRR_ADC1LPEN BIT(5)
+#define RCC_MP_AHB2LPENCLRR_ADC2LPEN BIT(6)
+#define RCC_MP_AHB2LPENCLRR_USBOLPEN BIT(8)
+
+/* RCC_MP_AHB4LPENSETR register fields */
+#define RCC_MP_AHB4LPENSETR_TSCLPEN BIT(15)
+
+/* RCC_MP_AHB4LPENCLRR register fields */
+#define RCC_MP_AHB4LPENCLRR_TSCLPEN BIT(15)
+
+/* RCC_MP_S_AHB4LPENSETR register fields */
+#define RCC_MP_S_AHB4LPENSETR_GPIOALPEN BIT(0)
+#define RCC_MP_S_AHB4LPENSETR_GPIOBLPEN BIT(1)
+#define RCC_MP_S_AHB4LPENSETR_GPIOCLPEN BIT(2)
+#define RCC_MP_S_AHB4LPENSETR_GPIODLPEN BIT(3)
+#define RCC_MP_S_AHB4LPENSETR_GPIOELPEN BIT(4)
+#define RCC_MP_S_AHB4LPENSETR_GPIOFLPEN BIT(5)
+#define RCC_MP_S_AHB4LPENSETR_GPIOGLPEN BIT(6)
+#define RCC_MP_S_AHB4LPENSETR_GPIOHLPEN BIT(7)
+#define RCC_MP_S_AHB4LPENSETR_GPIOILPEN BIT(8)
+
+/* RCC_MP_S_AHB4LPENCLRR register fields */
+#define RCC_MP_S_AHB4LPENCLRR_GPIOALPEN BIT(0)
+#define RCC_MP_S_AHB4LPENCLRR_GPIOBLPEN BIT(1)
+#define RCC_MP_S_AHB4LPENCLRR_GPIOCLPEN BIT(2)
+#define RCC_MP_S_AHB4LPENCLRR_GPIODLPEN BIT(3)
+#define RCC_MP_S_AHB4LPENCLRR_GPIOELPEN BIT(4)
+#define RCC_MP_S_AHB4LPENCLRR_GPIOFLPEN BIT(5)
+#define RCC_MP_S_AHB4LPENCLRR_GPIOGLPEN BIT(6)
+#define RCC_MP_S_AHB4LPENCLRR_GPIOHLPEN BIT(7)
+#define RCC_MP_S_AHB4LPENCLRR_GPIOILPEN BIT(8)
+
+/* RCC_MP_NS_AHB4LPENSETR register fields */
+#define RCC_MP_NS_AHB4LPENSETR_GPIOALPEN BIT(0)
+#define RCC_MP_NS_AHB4LPENSETR_GPIOBLPEN BIT(1)
+#define RCC_MP_NS_AHB4LPENSETR_GPIOCLPEN BIT(2)
+#define RCC_MP_NS_AHB4LPENSETR_GPIODLPEN BIT(3)
+#define RCC_MP_NS_AHB4LPENSETR_GPIOELPEN BIT(4)
+#define RCC_MP_NS_AHB4LPENSETR_GPIOFLPEN BIT(5)
+#define RCC_MP_NS_AHB4LPENSETR_GPIOGLPEN BIT(6)
+#define RCC_MP_NS_AHB4LPENSETR_GPIOHLPEN BIT(7)
+#define RCC_MP_NS_AHB4LPENSETR_GPIOILPEN BIT(8)
+
+/* RCC_MP_NS_AHB4LPENCLRR register fields */
+#define RCC_MP_NS_AHB4LPENCLRR_GPIOALPEN BIT(0)
+#define RCC_MP_NS_AHB4LPENCLRR_GPIOBLPEN BIT(1)
+#define RCC_MP_NS_AHB4LPENCLRR_GPIOCLPEN BIT(2)
+#define RCC_MP_NS_AHB4LPENCLRR_GPIODLPEN BIT(3)
+#define RCC_MP_NS_AHB4LPENCLRR_GPIOELPEN BIT(4)
+#define RCC_MP_NS_AHB4LPENCLRR_GPIOFLPEN BIT(5)
+#define RCC_MP_NS_AHB4LPENCLRR_GPIOGLPEN BIT(6)
+#define RCC_MP_NS_AHB4LPENCLRR_GPIOHLPEN BIT(7)
+#define RCC_MP_NS_AHB4LPENCLRR_GPIOILPEN BIT(8)
+
+/* RCC_MP_AHB5LPENSETR register fields */
+#define RCC_MP_AHB5LPENSETR_PKALPEN BIT(2)
+#define RCC_MP_AHB5LPENSETR_SAESLPEN BIT(3)
+#define RCC_MP_AHB5LPENSETR_CRYP1LPEN BIT(4)
+#define RCC_MP_AHB5LPENSETR_HASH1LPEN BIT(5)
+#define RCC_MP_AHB5LPENSETR_RNG1LPEN BIT(6)
+#define RCC_MP_AHB5LPENSETR_BKPSRAMLPEN BIT(8)
+
+/* RCC_MP_AHB5LPENCLRR register fields */
+#define RCC_MP_AHB5LPENCLRR_PKALPEN BIT(2)
+#define RCC_MP_AHB5LPENCLRR_SAESLPEN BIT(3)
+#define RCC_MP_AHB5LPENCLRR_CRYP1LPEN BIT(4)
+#define RCC_MP_AHB5LPENCLRR_HASH1LPEN BIT(5)
+#define RCC_MP_AHB5LPENCLRR_RNG1LPEN BIT(6)
+#define RCC_MP_AHB5LPENCLRR_BKPSRAMLPEN BIT(8)
+
+/* RCC_MP_AHB6LPENSETR register fields */
+#define RCC_MP_AHB6LPENSETR_MCELPEN BIT(1)
+#define RCC_MP_AHB6LPENSETR_ETH1CKLPEN BIT(7)
+#define RCC_MP_AHB6LPENSETR_ETH1TXLPEN BIT(8)
+#define RCC_MP_AHB6LPENSETR_ETH1RXLPEN BIT(9)
+#define RCC_MP_AHB6LPENSETR_ETH1MACLPEN BIT(10)
+#define RCC_MP_AHB6LPENSETR_ETH1STPEN BIT(11)
+#define RCC_MP_AHB6LPENSETR_FMCLPEN BIT(12)
+#define RCC_MP_AHB6LPENSETR_QSPILPEN BIT(14)
+#define RCC_MP_AHB6LPENSETR_SDMMC1LPEN BIT(16)
+#define RCC_MP_AHB6LPENSETR_SDMMC2LPEN BIT(17)
+#define RCC_MP_AHB6LPENSETR_CRC1LPEN BIT(20)
+#define RCC_MP_AHB6LPENSETR_USBHLPEN BIT(24)
+#define RCC_MP_AHB6LPENSETR_ETH2CKLPEN BIT(27)
+#define RCC_MP_AHB6LPENSETR_ETH2TXLPEN BIT(28)
+#define RCC_MP_AHB6LPENSETR_ETH2RXLPEN BIT(29)
+#define RCC_MP_AHB6LPENSETR_ETH2MACLPEN BIT(30)
+#define RCC_MP_AHB6LPENSETR_ETH2STPEN BIT(31)
+
+/* RCC_MP_AHB6LPENCLRR register fields */
+#define RCC_MP_AHB6LPENCLRR_MCELPEN BIT(1)
+#define RCC_MP_AHB6LPENCLRR_ETH1CKLPEN BIT(7)
+#define RCC_MP_AHB6LPENCLRR_ETH1TXLPEN BIT(8)
+#define RCC_MP_AHB6LPENCLRR_ETH1RXLPEN BIT(9)
+#define RCC_MP_AHB6LPENCLRR_ETH1MACLPEN BIT(10)
+#define RCC_MP_AHB6LPENCLRR_ETH1STPEN BIT(11)
+#define RCC_MP_AHB6LPENCLRR_FMCLPEN BIT(12)
+#define RCC_MP_AHB6LPENCLRR_QSPILPEN BIT(14)
+#define RCC_MP_AHB6LPENCLRR_SDMMC1LPEN BIT(16)
+#define RCC_MP_AHB6LPENCLRR_SDMMC2LPEN BIT(17)
+#define RCC_MP_AHB6LPENCLRR_CRC1LPEN BIT(20)
+#define RCC_MP_AHB6LPENCLRR_USBHLPEN BIT(24)
+#define RCC_MP_AHB6LPENCLRR_ETH2CKLPEN BIT(27)
+#define RCC_MP_AHB6LPENCLRR_ETH2TXLPEN BIT(28)
+#define RCC_MP_AHB6LPENCLRR_ETH2RXLPEN BIT(29)
+#define RCC_MP_AHB6LPENCLRR_ETH2MACLPEN BIT(30)
+#define RCC_MP_AHB6LPENCLRR_ETH2STPEN BIT(31)
+
+/* RCC_MP_S_AHB6LPENSETR register fields */
+#define RCC_MP_S_AHB6LPENSETR_MDMALPEN BIT(0)
+
+/* RCC_MP_S_AHB6LPENCLRR register fields */
+#define RCC_MP_S_AHB6LPENCLRR_MDMALPEN BIT(0)
+
+/* RCC_MP_NS_AHB6LPENSETR register fields */
+#define RCC_MP_NS_AHB6LPENSETR_MDMALPEN BIT(0)
+
+/* RCC_MP_NS_AHB6LPENCLRR register fields */
+#define RCC_MP_NS_AHB6LPENCLRR_MDMALPEN BIT(0)
+
+/* RCC_MP_S_AXIMLPENSETR register fields */
+#define RCC_MP_S_AXIMLPENSETR_SYSRAMLPEN BIT(0)
+
+/* RCC_MP_S_AXIMLPENCLRR register fields */
+#define RCC_MP_S_AXIMLPENCLRR_SYSRAMLPEN BIT(0)
+
+/* RCC_MP_NS_AXIMLPENSETR register fields */
+#define RCC_MP_NS_AXIMLPENSETR_SYSRAMLPEN BIT(0)
+
+/* RCC_MP_NS_AXIMLPENCLRR register fields */
+#define RCC_MP_NS_AXIMLPENCLRR_SYSRAMLPEN BIT(0)
+
+/* RCC_MP_MLAHBLPENSETR register fields */
+#define RCC_MP_MLAHBLPENSETR_SRAM1LPEN BIT(0)
+#define RCC_MP_MLAHBLPENSETR_SRAM2LPEN BIT(1)
+#define RCC_MP_MLAHBLPENSETR_SRAM3LPEN BIT(2)
+
+/* RCC_MP_MLAHBLPENCLRR register fields */
+#define RCC_MP_MLAHBLPENCLRR_SRAM1LPEN BIT(0)
+#define RCC_MP_MLAHBLPENCLRR_SRAM2LPEN BIT(1)
+#define RCC_MP_MLAHBLPENCLRR_SRAM3LPEN BIT(2)
+
+/* RCC_APB3SECSR register fields */
+#define RCC_APB3SECSR_LPTIM2SECF 0
+#define RCC_APB3SECSR_LPTIM3SECF 1
+#define RCC_APB3SECSR_VREFSECF 13
+
+/* RCC_APB4SECSR register fields */
+#define RCC_APB4SECSR_DCMIPPSECF 1
+#define RCC_APB4SECSR_USBPHYSECF 16
+
+/* RCC_APB5SECSR register fields */
+#define RCC_APB5SECSR_RTCSECF 8
+#define RCC_APB5SECSR_TZCSECF 11
+#define RCC_APB5SECSR_ETZPCSECF 13
+#define RCC_APB5SECSR_IWDG1SECF 15
+#define RCC_APB5SECSR_BSECSECF 16
+#define RCC_APB5SECSR_STGENCSECF_MASK GENMASK(21, 20)
+#define RCC_APB5SECSR_STGENCSECF 20
+#define RCC_APB5SECSR_STGENROSECF 21
+
+/* RCC_APB6SECSR register fields */
+#define RCC_APB6SECSR_USART1SECF 0
+#define RCC_APB6SECSR_USART2SECF 1
+#define RCC_APB6SECSR_SPI4SECF 2
+#define RCC_APB6SECSR_SPI5SECF 3
+#define RCC_APB6SECSR_I2C3SECF 4
+#define RCC_APB6SECSR_I2C4SECF 5
+#define RCC_APB6SECSR_I2C5SECF 6
+#define RCC_APB6SECSR_TIM12SECF 7
+#define RCC_APB6SECSR_TIM13SECF 8
+#define RCC_APB6SECSR_TIM14SECF 9
+#define RCC_APB6SECSR_TIM15SECF 10
+#define RCC_APB6SECSR_TIM16SECF 11
+#define RCC_APB6SECSR_TIM17SECF 12
+
+/* RCC_AHB2SECSR register fields */
+#define RCC_AHB2SECSR_DMA3SECF 3
+#define RCC_AHB2SECSR_DMAMUX2SECF 4
+#define RCC_AHB2SECSR_ADC1SECF 5
+#define RCC_AHB2SECSR_ADC2SECF 6
+#define RCC_AHB2SECSR_USBOSECF 8
+
+/* RCC_AHB4SECSR register fields */
+#define RCC_AHB4SECSR_TSCSECF 15
+
+/* RCC_AHB5SECSR register fields */
+#define RCC_AHB5SECSR_PKASECF 2
+#define RCC_AHB5SECSR_SAESSECF 3
+#define RCC_AHB5SECSR_CRYP1SECF 4
+#define RCC_AHB5SECSR_HASH1SECF 5
+#define RCC_AHB5SECSR_RNG1SECF 6
+#define RCC_AHB5SECSR_BKPSRAMSECF 8
+
+/* RCC_AHB6SECSR register fields */
+#define RCC_AHB6SECSR_MCESECF 1
+#define RCC_AHB6SECSR_FMCSECF 12
+#define RCC_AHB6SECSR_QSPISECF 14
+#define RCC_AHB6SECSR_SDMMC1SECF 16
+#define RCC_AHB6SECSR_SDMMC2SECF 17
+
+#define RCC_AHB6SECSR_ETH1SECF_MASK GENMASK(11, 7)
+#define RCC_AHB6SECSR_ETH2SECF_MASK GENMASK(31, 27)
+#define RCC_AHB6SECSR_ETH1SECF_SHIFT 7
+#define RCC_AHB6SECSR_ETH2SECF_SHIFT 27
+
+#define RCC_AHB6SECSR_ETH1CKSECF 7
+#define RCC_AHB6SECSR_ETH1TXSECF 8
+#define RCC_AHB6SECSR_ETH1RXSECF 9
+#define RCC_AHB6SECSR_ETH1MACSECF 10
+#define RCC_AHB6SECSR_ETH1STPSECF 11
+
+#define RCC_AHB6SECSR_ETH2CKSECF 27
+#define RCC_AHB6SECSR_ETH2TXSECF 28
+#define RCC_AHB6SECSR_ETH2RXSECF 29
+#define RCC_AHB6SECSR_ETH2MACSECF 30
+#define RCC_AHB6SECSR_ETH2STPSECF 31
+
+/* RCC_VERR register fields */
+#define RCC_VERR_MINREV_MASK GENMASK(3, 0)
+#define RCC_VERR_MAJREV_MASK GENMASK(7, 4)
+#define RCC_VERR_MINREV_SHIFT 0
+#define RCC_VERR_MAJREV_SHIFT 4
+
+/* RCC_IDR register fields */
+#define RCC_IDR_ID_MASK GENMASK(31, 0)
+#define RCC_IDR_ID_SHIFT 0
+
+/* RCC_SIDR register fields */
+#define RCC_SIDR_SID_MASK GENMASK(31, 0)
+#define RCC_SIDR_SID_SHIFT 0
+
+#endif /* STM32MP13_RCC_H */
+
diff --git a/drivers/clk/tegra/clk-divider.c b/drivers/clk/tegra/clk-divider.c
index 28a1342bbf..f1a913d983 100644
--- a/drivers/clk/tegra/clk-divider.c
+++ b/drivers/clk/tegra/clk-divider.c
@@ -8,7 +8,7 @@
#include <common.h>
#include <io.h>
#include <malloc.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <linux/clk.h>
#include <linux/err.h>
@@ -46,21 +46,22 @@ static int get_div(struct tegra_clk_frac_div *divider, unsigned long rate,
if (flags & TEGRA_DIVIDER_INT)
divider_ux1 *= mul;
- divider_ux1 -= mul;
-
- if (divider_ux1 < 0)
+ if (divider_ux1 < mul)
return 0;
+ divider_ux1 -= mul;
+
if (divider_ux1 > get_max_div(divider))
return -EINVAL;
return divider_ux1;
}
-static unsigned long clk_frac_div_recalc_rate(struct clk *hw,
+static unsigned long clk_frac_div_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct tegra_clk_frac_div *divider = to_clk_frac_div(hw);
+ struct clk *clk = clk_hw_to_clk(hw);
+ struct tegra_clk_frac_div *divider = to_clk_frac_div(clk);
u32 reg;
int div, mul;
u64 rate = parent_rate;
@@ -78,10 +79,11 @@ static unsigned long clk_frac_div_recalc_rate(struct clk *hw,
return rate;
}
-static long clk_frac_div_round_rate(struct clk *hw, unsigned long rate,
+static long clk_frac_div_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
- struct tegra_clk_frac_div *divider = to_clk_frac_div(hw);
+ struct clk *clk = clk_hw_to_clk(hw);
+ struct tegra_clk_frac_div *divider = to_clk_frac_div(clk);
int div, mul;
unsigned long output_rate = *prate;
@@ -97,10 +99,11 @@ static long clk_frac_div_round_rate(struct clk *hw, unsigned long rate,
return DIV_ROUND_UP(output_rate * mul, div + mul);
}
-static int clk_frac_div_set_rate(struct clk *hw, unsigned long rate,
+static int clk_frac_div_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct tegra_clk_frac_div *divider = to_clk_frac_div(hw);
+ struct clk *clk = clk_hw_to_clk(hw);
+ struct tegra_clk_frac_div *divider = to_clk_frac_div(clk);
int div;
u32 val;
@@ -180,7 +183,7 @@ struct clk *tegra_clk_register_divider(const char *name,
reg, flags, clk_divider_flags, shift, width,
frac_width));
- ret = clk_register(&divider->hw);
+ ret = bclk_register(&divider->hw);
if (ret) {
kfree(divider);
return ERR_PTR(ret);
diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c
index 0cd5200e84..7bfb14875d 100644
--- a/drivers/clk/tegra/clk-periph.c
+++ b/drivers/clk/tegra/clk-periph.c
@@ -16,65 +16,65 @@
#define to_clk_periph(_hw) container_of(_hw, struct tegra_clk_periph, hw)
-static int clk_periph_get_parent(struct clk *hw)
+static int clk_periph_get_parent(struct clk_hw *hw)
{
struct tegra_clk_periph *periph = to_clk_periph(hw);
- return periph->mux->ops->get_parent(periph->mux);
+ return periph->mux->ops->get_parent(clk_to_clk_hw(periph->mux));
}
-static int clk_periph_set_parent(struct clk *hw, u8 index)
+static int clk_periph_set_parent(struct clk_hw *hw, u8 index)
{
struct tegra_clk_periph *periph = to_clk_periph(hw);
- return periph->mux->ops->set_parent(periph->mux, index);
+ return periph->mux->ops->set_parent(clk_to_clk_hw(periph->mux), index);
}
-static unsigned long clk_periph_recalc_rate(struct clk *hw,
+static unsigned long clk_periph_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct tegra_clk_periph *periph = to_clk_periph(hw);
- return periph->div->ops->recalc_rate(periph->div, parent_rate);
+ return periph->div->ops->recalc_rate(clk_to_clk_hw(periph->div), parent_rate);
}
-static long clk_periph_round_rate(struct clk *hw, unsigned long rate,
+static long clk_periph_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct tegra_clk_periph *periph = to_clk_periph(hw);
- return periph->div->ops->round_rate(periph->div, rate, prate);
+ return periph->div->ops->round_rate(clk_to_clk_hw(periph->div), rate, prate);
}
-static int clk_periph_set_rate(struct clk *hw, unsigned long rate,
+static int clk_periph_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct tegra_clk_periph *periph = to_clk_periph(hw);
- return periph->div->ops->set_rate(periph->div, rate, parent_rate);
+ return periph->div->ops->set_rate(clk_to_clk_hw(periph->div), rate, parent_rate);
}
-static int clk_periph_is_enabled(struct clk *hw)
+static int clk_periph_is_enabled(struct clk_hw *hw)
{
struct tegra_clk_periph *periph = to_clk_periph(hw);
- return periph->gate->ops->is_enabled(periph->gate);
+ return periph->gate->ops->is_enabled(clk_to_clk_hw(periph->gate));
}
-static int clk_periph_enable(struct clk *hw)
+static int clk_periph_enable(struct clk_hw *hw)
{
struct tegra_clk_periph *periph = to_clk_periph(hw);
- periph->gate->ops->enable(periph->gate);
+ periph->gate->ops->enable(clk_to_clk_hw(periph->gate));
return 0;
}
-static void clk_periph_disable(struct clk *hw)
+static void clk_periph_disable(struct clk_hw *hw)
{
struct tegra_clk_periph *periph = to_clk_periph(hw);
- periph->gate->ops->disable(periph->gate);
+ periph->gate->ops->disable(clk_to_clk_hw(periph->gate));
}
const struct clk_ops tegra_clk_periph_ops = {
@@ -139,11 +139,11 @@ static struct clk *_tegra_clk_register_periph(const char *name,
goto out_div;
}
- periph->hw.name = name;
- periph->hw.ops = div ? &tegra_clk_periph_ops :
+ periph->hw.clk.name = name;
+ periph->hw.clk.ops = div ? &tegra_clk_periph_ops :
&tegra_clk_periph_nodiv_ops;
- periph->hw.parent_names = parent_names;
- periph->hw.num_parents = num_parents;
+ periph->hw.clk.parent_names = parent_names;
+ periph->hw.clk.num_parents = num_parents;
periph->flags = flags;
if (id >= 96)
@@ -153,11 +153,11 @@ static struct clk *_tegra_clk_register_periph(const char *name,
periph->rst_reg = clk_base + rst_offs;
periph->rst_shift = id & 0x1f;
- ret = clk_register(&periph->hw);
+ ret = bclk_register(&periph->hw.clk);
if (ret)
goto out_register;
- return &periph->hw;
+ return &periph->hw.clk;
out_register:
tegra_clk_divider_free(periph->div);
diff --git a/drivers/clk/tegra/clk-pll-out.c b/drivers/clk/tegra/clk-pll-out.c
index e186275563..f14b41c04a 100644
--- a/drivers/clk/tegra/clk-pll-out.c
+++ b/drivers/clk/tegra/clk-pll-out.c
@@ -18,7 +18,7 @@
#define to_clk_pll_out(_hw) container_of(_hw, struct tegra_clk_pll_out, hw)
-static int clk_pll_out_is_enabled(struct clk *hw)
+static int clk_pll_out_is_enabled(struct clk_hw *hw)
{
struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw);
u32 val = readl(pll_out->reg);
@@ -30,7 +30,7 @@ static int clk_pll_out_is_enabled(struct clk *hw)
return state;
}
-static int clk_pll_out_enable(struct clk *hw)
+static int clk_pll_out_enable(struct clk_hw *hw)
{
struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw);
u32 val;
@@ -45,7 +45,7 @@ static int clk_pll_out_enable(struct clk *hw)
return 0;
}
-static void clk_pll_out_disable(struct clk *hw)
+static void clk_pll_out_disable(struct clk_hw *hw)
{
struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw);
u32 val;
@@ -58,28 +58,28 @@ static void clk_pll_out_disable(struct clk *hw)
udelay(2);
}
-static unsigned long clk_pll_out_recalc_rate(struct clk *hw,
+static unsigned long clk_pll_out_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw);
- return pll_out->div->ops->recalc_rate(pll_out->div, parent_rate);
+ return pll_out->div->ops->recalc_rate(clk_to_clk_hw(pll_out->div), parent_rate);
}
-static long clk_pll_out_round_rate(struct clk *hw, unsigned long rate,
+static long clk_pll_out_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw);
- return pll_out->div->ops->round_rate(pll_out->div, rate, prate);
+ return pll_out->div->ops->round_rate(clk_to_clk_hw(pll_out->div), rate, prate);
}
-static int clk_pll_out_set_rate(struct clk *hw, unsigned long rate,
+static int clk_pll_out_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw);
- return pll_out->div->ops->set_rate(pll_out->div, rate, parent_rate);
+ return pll_out->div->ops->set_rate(clk_to_clk_hw(pll_out->div), rate, parent_rate);
}
const struct clk_ops tegra_clk_pll_out_ops = {
@@ -108,21 +108,21 @@ struct clk *tegra_clk_register_pll_out(const char *name,
}
pll_out->parent = parent_name;
- pll_out->hw.name = name;
- pll_out->hw.ops = &tegra_clk_pll_out_ops;
- pll_out->hw.parent_names = (pll_out->parent ? &pll_out->parent : NULL);
- pll_out->hw.num_parents = (pll_out->parent ? 1 : 0);
+ pll_out->hw.clk.name = name;
+ pll_out->hw.clk.ops = &tegra_clk_pll_out_ops;
+ pll_out->hw.clk.parent_names = (pll_out->parent ? &pll_out->parent : NULL);
+ pll_out->hw.clk.num_parents = (pll_out->parent ? 1 : 0);
pll_out->reg = reg;
pll_out->enb_bit_idx = shift + 1;
pll_out->rst_bit_idx = shift;
- ret = clk_register(&pll_out->hw);
+ ret = bclk_register(&pll_out->hw.clk);
if (ret) {
tegra_clk_divider_free(pll_out->div);
kfree(pll_out);
return ERR_PTR(ret);
}
- return &pll_out->hw;
+ return &pll_out->hw.clk;
}
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 3ac49cae47..32f57cc2e4 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -9,11 +9,11 @@
#include <clock.h>
#include <io.h>
#include <malloc.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <linux/clk.h>
#include <linux/err.h>
-#include <mach/iomap.h>
+#include <mach/tegra/iomap.h>
#include "clk.h"
@@ -144,7 +144,7 @@
#define to_clk_pll(_hw) container_of(_hw, struct tegra_clk_pll, hw)
-static int clk_pll_is_enabled(struct clk *hw)
+static int clk_pll_is_enabled(struct clk_hw *hw)
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
u32 val;
@@ -187,12 +187,12 @@ static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll,
}
pr_err("%s: Timed out waiting for pll %s lock\n", __func__,
- pll->hw.name);
+ clk_hw_get_name(&pll->hw));
return -1;
}
-static int clk_pll_enable(struct clk *hw)
+static int clk_pll_enable(struct clk_hw *hw)
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
u32 val;
@@ -210,7 +210,7 @@ static int clk_pll_enable(struct clk *hw)
return 0;
}
-static void clk_pll_disable(struct clk *hw)
+static void clk_pll_disable(struct clk_hw *hw)
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
u32 val;
@@ -220,7 +220,7 @@ static void clk_pll_disable(struct clk *hw)
pll_writel_base(val, pll);
}
-static int _get_table_rate(struct clk *hw,
+static int _get_table_rate(struct clk_hw *hw,
struct tegra_clk_pll_freq_table *cfg,
unsigned long rate, unsigned long parent_rate)
{
@@ -245,7 +245,7 @@ static int _get_table_rate(struct clk *hw,
return 0;
}
-static unsigned long clk_pll_recalc_rate(struct clk *hw,
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
@@ -260,7 +260,7 @@ static unsigned long clk_pll_recalc_rate(struct clk *hw,
struct tegra_clk_pll_freq_table sel;
if (_get_table_rate(hw, &sel, pll->fixed_rate, parent_rate)) {
pr_err("Clock %s has unknown fixed frequency\n",
- hw->name);
+ clk_hw_get_name(hw));
BUG();
}
return pll->fixed_rate;
@@ -280,7 +280,7 @@ static unsigned long clk_pll_recalc_rate(struct clk *hw,
return rate;
}
-static int _calc_rate(struct clk *hw, struct tegra_clk_pll_freq_table *cfg,
+static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
unsigned long rate, unsigned long parent_rate)
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
@@ -325,14 +325,14 @@ static int _calc_rate(struct clk *hw, struct tegra_clk_pll_freq_table *cfg,
if (cfg->m > divm_max(pll) || cfg->n > divn_max(pll) ||
cfg->p > divp_max(pll) || cfg->output_rate > pll->params->vco_max) {
pr_err("%s: Failed to set %s rate %lu\n",
- __func__, hw->name, rate);
+ __func__, clk_hw_get_name(hw), rate);
return -EINVAL;
}
return 0;
}
-static long clk_pll_round_rate(struct clk *hw, unsigned long rate,
+static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
@@ -344,7 +344,7 @@ static long clk_pll_round_rate(struct clk *hw, unsigned long rate,
/* PLLM is used for memory; we do not change rate */
if (pll->flags & TEGRA_PLLM)
- return clk_get_rate(hw);
+ return clk_get_rate(clk_hw_to_clk(hw));
if (_get_table_rate(hw, &cfg, rate, *prate) &&
_calc_rate(hw, &cfg, rate, *prate))
@@ -356,7 +356,7 @@ static long clk_pll_round_rate(struct clk *hw, unsigned long rate,
return output_rate;
}
-static int _program_pll(struct clk *hw, struct tegra_clk_pll_freq_table *cfg,
+static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
unsigned long rate)
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
@@ -411,7 +411,7 @@ static int _program_pll(struct clk *hw, struct tegra_clk_pll_freq_table *cfg,
return 0;
}
-static int clk_pll_set_rate(struct clk *hw, unsigned long rate,
+static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct tegra_clk_pll_freq_table cfg;
@@ -432,7 +432,7 @@ const struct clk_ops tegra_clk_pll_ops = {
.set_rate = clk_pll_set_rate,
};
-static unsigned long clk_plle_recalc_rate(struct clk *hw,
+static unsigned long clk_plle_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
@@ -474,10 +474,10 @@ static int clk_plle_training(struct tegra_clk_pll *pll)
(pll_readl_misc(pll) & PLLE_MISC_READY));
}
-static int clk_plle_enable(struct clk *hw)
+static int clk_plle_enable(struct clk_hw *hw)
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
- unsigned long input_rate = clk_get_rate(clk_get_parent(hw));
+ unsigned long input_rate = clk_get_rate(clk_get_parent(clk_hw_to_clk(hw)));
struct tegra_clk_pll_freq_table sel;
u32 val;
int err;
@@ -534,10 +534,10 @@ const struct clk_ops tegra_clk_plle_ops = {
.enable = clk_plle_enable,
};
-static int clk_plle_tegra114_enable(struct clk *hw)
+static int clk_plle_tegra114_enable(struct clk_hw *hw)
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
- unsigned long input_rate = clk_get_rate(clk_get_parent(hw));
+ unsigned long input_rate = clk_get_rate(clk_get_parent(clk_hw_to_clk(hw)));
struct tegra_clk_pll_freq_table sel;
u32 val;
int ret;
@@ -623,7 +623,7 @@ static int clk_plle_tegra114_enable(struct clk *hw)
return ret;
}
-static void clk_plle_tegra114_disable(struct clk *hw)
+static void clk_plle_tegra114_disable(struct clk_hw *hw)
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
u32 val;
@@ -658,11 +658,11 @@ static struct clk *_tegra_clk_register_pll(const char *name,
return NULL;
pll->parent = parent_name;
- pll->hw.name = name;
- pll->hw.ops = ops;
- pll->hw.flags = flags;
- pll->hw.parent_names = (pll->parent ? &pll->parent : NULL);
- pll->hw.num_parents = (pll->parent ? 1 : 0);
+ pll->hw.clk.name = name;
+ pll->hw.clk.ops = ops;
+ pll->hw.clk.flags = flags;
+ pll->hw.clk.parent_names = (pll->parent ? &pll->parent : NULL);
+ pll->hw.clk.num_parents = (pll->parent ? 1 : 0);
pll->clk_base = clk_base;
@@ -678,13 +678,13 @@ static struct clk *_tegra_clk_register_pll(const char *name,
pll->divm_shift = PLL_BASE_DIVM_SHIFT;
pll->divm_width = PLL_BASE_DIVM_WIDTH;
- ret = clk_register(&pll->hw);
+ ret = bclk_register(&pll->hw.clk);
if (ret) {
kfree(pll);
return ERR_PTR(ret);
}
- return &pll->hw;
+ return &pll->hw.clk;
}
struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index f5704b83c5..6c4ec06b28 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -12,9 +12,9 @@
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/err.h>
-#include <mach/lowlevel.h>
-#include <mach/tegra20-car.h>
-#include <mach/tegra30-car.h>
+#include <mach/tegra/lowlevel.h>
+#include <mach/tegra/tegra20-car.h>
+#include <mach/tegra/tegra30-car.h>
#include "clk.h"
@@ -322,7 +322,7 @@ static struct tegra_clk_init_table init_table[] = {
{TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0}, /* sentinel */
};
-static int tegra124_car_probe(struct device_d *dev)
+static int tegra124_car_probe(struct device *dev)
{
struct resource *iores;
iores = dev_request_mem_resource(dev, 0);
@@ -345,10 +345,10 @@ static int tegra124_car_probe(struct device_d *dev)
clk_data.clks = clks;
clk_data.clk_num = ARRAY_SIZE(clks);
- of_clk_add_provider(dev->device_node, of_clk_src_onecell_get,
+ of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
&clk_data);
- tegra_clk_init_rst_controller(car_base, dev->device_node, 6 * 32);
+ tegra_clk_init_rst_controller(car_base, dev->of_node, 6 * 32);
tegra_clk_reset_uarts();
return 0;
@@ -361,15 +361,12 @@ static __maybe_unused struct of_device_id tegra124_car_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, tegra124_car_dt_ids);
-static struct driver_d tegra124_car_driver = {
+static struct driver tegra124_car_driver = {
.probe = tegra124_car_probe,
.name = "tegra124-car",
.of_compatible = DRV_OF_COMPAT(tegra124_car_dt_ids),
};
-static int tegra124_car_init(void)
-{
- return platform_driver_register(&tegra124_car_driver);
-}
-postcore_initcall(tegra124_car_init);
+postcore_platform_driver(tegra124_car_driver);
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index 9fccff6136..77ba62c132 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -12,8 +12,8 @@
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/err.h>
-#include <mach/lowlevel.h>
-#include <mach/tegra20-car.h>
+#include <mach/tegra/lowlevel.h>
+#include <mach/tegra/tegra20-car.h>
#include "clk.h"
@@ -325,7 +325,7 @@ static struct tegra_clk_init_table init_table[] = {
{TEGRA20_CLK_CLK_MAX, TEGRA20_CLK_CLK_MAX, 0, 0}, /* sentinel */
};
-static int tegra20_car_probe(struct device_d *dev)
+static int tegra20_car_probe(struct device *dev)
{
struct resource *iores;
iores = dev_request_mem_resource(dev, 0);
@@ -348,10 +348,10 @@ static int tegra20_car_probe(struct device_d *dev)
clk_data.clks = clks;
clk_data.clk_num = ARRAY_SIZE(clks);
- of_clk_add_provider(dev->device_node, of_clk_src_onecell_get,
+ of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
&clk_data);
- tegra_clk_init_rst_controller(car_base, dev->device_node, 3 * 32);
+ tegra_clk_init_rst_controller(car_base, dev->of_node, 3 * 32);
tegra_clk_reset_uarts();
return 0;
@@ -364,15 +364,12 @@ static __maybe_unused struct of_device_id tegra20_car_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, tegra20_car_dt_ids);
-static struct driver_d tegra20_car_driver = {
+static struct driver tegra20_car_driver = {
.probe = tegra20_car_probe,
.name = "tegra20-car",
.of_compatible = DRV_OF_COMPAT(tegra20_car_dt_ids),
};
-static int tegra20_car_init(void)
-{
- return platform_driver_register(&tegra20_car_driver);
-}
-postcore_initcall(tegra20_car_init);
+postcore_platform_driver(tegra20_car_driver);
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index 3d3a7854ff..69cc118ff9 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -12,9 +12,9 @@
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/err.h>
-#include <mach/lowlevel.h>
-#include <mach/tegra20-car.h>
-#include <mach/tegra30-car.h>
+#include <mach/tegra/lowlevel.h>
+#include <mach/tegra/tegra20-car.h>
+#include <mach/tegra/tegra30-car.h>
#include "clk.h"
@@ -353,7 +353,7 @@ static struct tegra_clk_init_table init_table[] = {
{TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0}, /* sentinel */
};
-static int tegra30_car_probe(struct device_d *dev)
+static int tegra30_car_probe(struct device *dev)
{
struct resource *iores;
iores = dev_request_mem_resource(dev, 0);
@@ -376,10 +376,10 @@ static int tegra30_car_probe(struct device_d *dev)
clk_data.clks = clks;
clk_data.clk_num = ARRAY_SIZE(clks);
- of_clk_add_provider(dev->device_node, of_clk_src_onecell_get,
+ of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
&clk_data);
- tegra_clk_init_rst_controller(car_base, dev->device_node, 6 * 32);
+ tegra_clk_init_rst_controller(car_base, dev->of_node, 6 * 32);
tegra_clk_reset_uarts();
return 0;
@@ -392,15 +392,12 @@ static __maybe_unused struct of_device_id tegra30_car_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, tegra30_car_dt_ids);
-static struct driver_d tegra30_car_driver = {
+static struct driver tegra30_car_driver = {
.probe = tegra30_car_probe,
.name = "tegra30-car",
.of_compatible = DRV_OF_COMPAT(tegra30_car_dt_ids),
};
-static int tegra30_car_init(void)
-{
- return platform_driver_register(&tegra30_car_driver);
-}
-postcore_initcall(tegra30_car_init);
+postcore_platform_driver(tegra30_car_driver);
diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
index 26ff9f2580..ad384d8d4d 100644
--- a/drivers/clk/tegra/clk.c
+++ b/drivers/clk/tegra/clk.c
@@ -8,7 +8,7 @@
#include <common.h>
#include <linux/clk.h>
#include <linux/reset-controller.h>
-#include <mach/lowlevel.h>
+#include <mach/tegra/lowlevel.h>
#include "clk.h"
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 5195e6dba4..80a83c7865 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -61,7 +61,7 @@ struct tegra_clk_pll_params {
/* struct tegra_clk_pll - Tegra PLL clock */
struct tegra_clk_pll {
- struct clk hw;
+ struct clk_hw hw;
void __iomem *clk_base;
u8 flags;
unsigned long fixed_rate;
@@ -105,7 +105,7 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name,
/* struct tegra_clk_pll_out - PLL output divider */
struct tegra_clk_pll_out {
- struct clk hw;
+ struct clk_hw hw;
struct clk *div;
void __iomem *reg;
u8 enb_bit_idx;
@@ -119,7 +119,7 @@ struct clk *tegra_clk_register_pll_out(const char *name,
/* struct clk-periph - peripheral clock */
struct tegra_clk_periph {
- struct clk hw;
+ struct clk_hw hw;
struct clk *gate;
struct clk *mux;
struct clk *div;
diff --git a/drivers/clk/ti-sci-clk.c b/drivers/clk/ti-sci-clk.c
new file mode 100644
index 0000000000..57e0406553
--- /dev/null
+++ b/drivers/clk/ti-sci-clk.c
@@ -0,0 +1,630 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SCI Clock driver for keystone based devices
+ *
+ * Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/
+ * Tero Kristo <t-kristo@ti.com>
+ */
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <linux/clk.h>
+#include <io.h>
+#include <of.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/bsearch.h>
+#include <soc/ti/ti_sci_protocol.h>
+#include <linux/list_sort.h>
+
+#define SCI_CLK_SSC_ENABLE BIT(0)
+#define SCI_CLK_ALLOW_FREQ_CHANGE BIT(1)
+#define SCI_CLK_INPUT_TERMINATION BIT(2)
+
+/**
+ * struct sci_clk_provider - TI SCI clock provider representation
+ * @sci: Handle to the System Control Interface protocol handler
+ * @ops: Pointer to the SCI ops to be used by the clocks
+ * @dev: Device pointer for the clock provider
+ * @clocks: Clocks array for this device
+ * @num_clocks: Total number of clocks for this provider
+ */
+struct sci_clk_provider {
+ const struct ti_sci_handle *sci;
+ const struct ti_sci_clk_ops *ops;
+ struct device *dev;
+ struct sci_clk **clocks;
+ int num_clocks;
+};
+
+/**
+ * struct sci_clk - TI SCI clock representation
+ * @hw: Hardware clock cookie for common clock framework
+ * @dev_id: Device index
+ * @clk_id: Clock index
+ * @num_parents: Number of parents for this clock
+ * @provider: Master clock provider
+ * @flags: Flags for the clock
+ * @node: Link for handling clocks probed via DT
+ * @cached_req: Cached requested freq for determine rate calls
+ * @cached_res: Cached result freq for determine rate calls
+ */
+struct sci_clk {
+ struct clk_hw hw;
+ u16 dev_id;
+ u32 clk_id;
+ u32 num_parents;
+ struct sci_clk_provider *provider;
+ u8 flags;
+ struct list_head node;
+ unsigned long cached_req;
+ unsigned long cached_res;
+};
+
+#define to_sci_clk(_hw) container_of(_hw, struct sci_clk, hw)
+
+/**
+ * sci_clk_enable - enable a TI SCI clock
+ * @hw: clock to enable
+ *
+ * Enables a clock to be actively used. Returns the SCI protocol status.
+ */
+static int sci_clk_enable(struct clk_hw *hw)
+{
+ struct sci_clk *clk = to_sci_clk(hw);
+ bool enable_ssc = clk->flags & SCI_CLK_SSC_ENABLE;
+ bool allow_freq_change = clk->flags & SCI_CLK_ALLOW_FREQ_CHANGE;
+ bool input_termination = clk->flags & SCI_CLK_INPUT_TERMINATION;
+
+ return clk->provider->ops->get_clock(clk->provider->sci, clk->dev_id,
+ clk->clk_id, enable_ssc,
+ allow_freq_change,
+ input_termination);
+}
+
+/**
+ * sci_clk_disable - disables a TI SCI clock
+ * @hw: clock to disable
+ *
+ * Disables a clock from active state.
+ */
+static void sci_clk_disable(struct clk_hw *hw)
+{
+ struct sci_clk *clk = to_sci_clk(hw);
+ int ret;
+
+ ret = clk->provider->ops->put_clock(clk->provider->sci, clk->dev_id,
+ clk->clk_id);
+ if (ret)
+ dev_err(clk->provider->dev,
+ "unprepare failed for dev=%d, clk=%d, ret=%d\n",
+ clk->dev_id, clk->clk_id, ret);
+}
+
+/**
+ * sci_clk_is_enabled - Check if a TI SCI clock is enabled or not
+ * @hw: clock to check status for
+ *
+ * Checks if a clock is enabled in hardware. Returns non-zero
+ * value if clock is enabled, zero otherwise.
+ */
+static int sci_clk_is_enabled(struct clk_hw *hw)
+{
+ struct sci_clk *clk = to_sci_clk(hw);
+ bool req_state, current_state;
+ int ret;
+
+ ret = clk->provider->ops->is_on(clk->provider->sci, clk->dev_id,
+ clk->clk_id, &req_state,
+ &current_state);
+ if (ret) {
+ dev_err(clk->provider->dev,
+ "is_prepared failed for dev=%d, clk=%d, ret=%d\n",
+ clk->dev_id, clk->clk_id, ret);
+ return 0;
+ }
+
+ return req_state;
+}
+
+/**
+ * sci_clk_recalc_rate - Get clock rate for a TI SCI clock
+ * @hw: clock to get rate for
+ * @parent_rate: parent rate provided by common clock framework, not used
+ *
+ * Gets the current clock rate of a TI SCI clock. Returns the current
+ * clock rate, or zero in failure.
+ */
+static unsigned long sci_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct sci_clk *clk = to_sci_clk(hw);
+ u64 freq;
+ int ret;
+
+ ret = clk->provider->ops->get_freq(clk->provider->sci, clk->dev_id,
+ clk->clk_id, &freq);
+ if (ret) {
+ dev_err(clk->provider->dev,
+ "recalc-rate failed for dev=%d, clk=%d, ret=%d\n",
+ clk->dev_id, clk->clk_id, ret);
+ return 0;
+ }
+
+ return freq;
+}
+
+/**
+ * sci_clk_set_rate - Set rate for a TI SCI clock
+ * @hw: clock to change rate for
+ * @rate: target rate for the clock
+ * @parent_rate: rate of the clock parent, not used for TI SCI clocks
+ *
+ * Sets a clock frequency for a TI SCI clock. Returns the TI SCI
+ * protocol status.
+ */
+static int sci_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct sci_clk *clk = to_sci_clk(hw);
+
+ return clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id,
+ clk->clk_id, rate / 10 * 9, rate,
+ rate / 10 * 11);
+}
+
+/**
+ * sci_clk_get_parent - Get the current parent of a TI SCI clock
+ * @hw: clock to get parent for
+ *
+ * Returns the index of the currently selected parent for a TI SCI clock.
+ */
+static int sci_clk_get_parent(struct clk_hw *hw)
+{
+ struct sci_clk *clk = to_sci_clk(hw);
+ u32 parent_id = 0;
+ int ret;
+
+ ret = clk->provider->ops->get_parent(clk->provider->sci, clk->dev_id,
+ clk->clk_id, (void *)&parent_id);
+ if (ret) {
+ dev_err(clk->provider->dev,
+ "get-parent failed for dev=%d, clk=%d, ret=%d\n",
+ clk->dev_id, clk->clk_id, ret);
+ return 0;
+ }
+
+ parent_id = parent_id - clk->clk_id - 1;
+
+ return parent_id;
+}
+
+/**
+ * sci_clk_set_parent - Set the parent of a TI SCI clock
+ * @hw: clock to set parent for
+ * @index: new parent index for the clock
+ *
+ * Sets the parent of a TI SCI clock. Return TI SCI protocol status.
+ */
+static int sci_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct sci_clk *clk = to_sci_clk(hw);
+
+ clk->cached_req = 0;
+
+ return clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id,
+ clk->clk_id,
+ index + 1 + clk->clk_id);
+}
+
+static const struct clk_ops sci_clk_ops = {
+ .enable = sci_clk_enable,
+ .disable = sci_clk_disable,
+ .is_enabled = sci_clk_is_enabled,
+ .recalc_rate = sci_clk_recalc_rate,
+ .set_rate = sci_clk_set_rate,
+ .get_parent = sci_clk_get_parent,
+ .set_parent = sci_clk_set_parent,
+};
+
+/**
+ * _sci_clk_get - Gets a handle for an SCI clock
+ * @provider: Handle to SCI clock provider
+ * @sci_clk: Handle to the SCI clock to populate
+ *
+ * Gets a handle to an existing TI SCI hw clock, or builds a new clock
+ * entry and registers it with the common clock framework. Called from
+ * the common clock framework, when a corresponding of_clk_get call is
+ * executed, or recursively from itself when parsing parent clocks.
+ * Returns 0 on success, negative error code on failure.
+ */
+static int _sci_clk_build(struct sci_clk_provider *provider,
+ struct sci_clk *sci_clk)
+{
+ struct clk_init_data init = { NULL };
+ char *name = NULL;
+ char **parent_names = NULL;
+ int i;
+ int ret = 0;
+
+ name = basprintf("clk:%d:%d", sci_clk->dev_id, sci_clk->clk_id);
+ if (!name)
+ return -ENOMEM;
+
+ init.name = name;
+
+ /*
+ * From kernel point of view, we only care about a clocks parents,
+ * if it has more than 1 possible parent. In this case, it is going
+ * to have mux functionality. Otherwise it is going to act as a root
+ * clock.
+ */
+ if (sci_clk->num_parents < 2)
+ sci_clk->num_parents = 0;
+
+ if (sci_clk->num_parents) {
+ parent_names = kcalloc(sci_clk->num_parents, sizeof(char *),
+ GFP_KERNEL);
+
+ if (!parent_names) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ for (i = 0; i < sci_clk->num_parents; i++) {
+ char *parent_name;
+
+ parent_name = basprintf("clk:%d:%d",
+ sci_clk->dev_id,
+ sci_clk->clk_id + 1 + i);
+ if (!parent_name) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ parent_names[i] = parent_name;
+ }
+ init.parent_names = (void *)parent_names;
+ }
+
+ init.ops = &sci_clk_ops;
+ init.num_parents = sci_clk->num_parents;
+ sci_clk->hw.init = &init;
+
+ ret = clk_hw_register(provider->dev, &sci_clk->hw);
+ if (ret)
+ dev_err(provider->dev, "failed clk register with %d\n", ret);
+
+err:
+ if (parent_names) {
+ for (i = 0; i < sci_clk->num_parents; i++)
+ kfree(parent_names[i]);
+
+ kfree(parent_names);
+ }
+
+ kfree(name);
+
+ return ret;
+}
+
+static int _cmp_sci_clk(const void *a, const void *b)
+{
+ const struct sci_clk *ca = a;
+ const struct sci_clk *cb = *(struct sci_clk **)b;
+
+ if (ca->dev_id == cb->dev_id && ca->clk_id == cb->clk_id)
+ return 0;
+ if (ca->dev_id > cb->dev_id ||
+ (ca->dev_id == cb->dev_id && ca->clk_id > cb->clk_id))
+ return 1;
+ return -1;
+}
+
+/**
+ * sci_clk_get - Xlate function for getting clock handles
+ * @clkspec: device tree clock specifier
+ * @data: pointer to the clock provider
+ *
+ * Xlate function for retrieving clock TI SCI hw clock handles based on
+ * device tree clock specifier. Called from the common clock framework,
+ * when a corresponding of_clk_get call is executed. Returns a pointer
+ * to the TI SCI hw clock struct, or ERR_PTR value in failure.
+ */
+static struct clk_hw *sci_clk_get(struct of_phandle_args *clkspec, void *data)
+{
+ struct sci_clk_provider *provider = data;
+ struct sci_clk **clk;
+ struct sci_clk key;
+
+ if (clkspec->args_count != 2)
+ return ERR_PTR(-EINVAL);
+
+ key.dev_id = clkspec->args[0];
+ key.clk_id = clkspec->args[1];
+
+ clk = bsearch(&key, provider->clocks, provider->num_clocks,
+ sizeof(clk), _cmp_sci_clk);
+
+ if (!clk)
+ return ERR_PTR(-ENODEV);
+
+ return &(*clk)->hw;
+}
+
+static int ti_sci_init_clocks(struct sci_clk_provider *p)
+{
+ int i;
+ int ret;
+
+ for (i = 0; i < p->num_clocks; i++) {
+ ret = _sci_clk_build(p, p->clocks[i]);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id ti_sci_clk_of_match[] = {
+ { .compatible = "ti,k2g-sci-clk" },
+ { /* Sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, ti_sci_clk_of_match);
+
+#ifdef CONFIG_TI_SCI_CLK_PROBE_FROM_FW
+static int ti_sci_scan_clocks_from_fw(struct sci_clk_provider *provider)
+{
+ int ret;
+ int num_clks = 0;
+ struct sci_clk **clks = NULL;
+ struct sci_clk **tmp_clks;
+ struct sci_clk *sci_clk;
+ int max_clks = 0;
+ int clk_id = 0;
+ int dev_id = 0;
+ u32 num_parents = 0;
+ int gap_size = 0;
+ struct device *dev = provider->dev;
+
+ while (1) {
+ ret = provider->ops->get_num_parents(provider->sci, dev_id,
+ clk_id,
+ (void *)&num_parents);
+ if (ret) {
+ gap_size++;
+ if (!clk_id) {
+ if (gap_size >= 5)
+ break;
+ dev_id++;
+ } else {
+ if (gap_size >= 2) {
+ dev_id++;
+ clk_id = 0;
+ gap_size = 0;
+ } else {
+ clk_id++;
+ }
+ }
+ continue;
+ }
+
+ gap_size = 0;
+
+ if (num_clks == max_clks) {
+ tmp_clks = devm_kmalloc_array(dev, max_clks + 64,
+ sizeof(sci_clk),
+ GFP_KERNEL);
+ memcpy(tmp_clks, clks, max_clks * sizeof(sci_clk));
+ if (max_clks)
+ devm_kfree(dev, clks);
+ max_clks += 64;
+ clks = tmp_clks;
+ }
+
+ sci_clk = devm_kzalloc(dev, sizeof(*sci_clk), GFP_KERNEL);
+ if (!sci_clk)
+ return -ENOMEM;
+ sci_clk->dev_id = dev_id;
+ sci_clk->clk_id = clk_id;
+ sci_clk->provider = provider;
+ sci_clk->num_parents = num_parents;
+
+ clks[num_clks] = sci_clk;
+
+ clk_id++;
+ num_clks++;
+ }
+
+ provider->clocks = devm_kmalloc_array(dev, num_clks, sizeof(sci_clk),
+ GFP_KERNEL);
+ if (!provider->clocks)
+ return -ENOMEM;
+
+ memcpy(provider->clocks, clks, num_clks * sizeof(sci_clk));
+
+ provider->num_clocks = num_clks;
+
+ devm_kfree(dev, clks);
+
+ return 0;
+}
+
+#else
+
+static int _cmp_sci_clk_list(void *priv, struct list_head *a,
+ struct list_head *b)
+{
+ struct sci_clk *ca = container_of(a, struct sci_clk, node);
+ struct sci_clk *cb = container_of(b, struct sci_clk, node);
+
+ return _cmp_sci_clk(ca, &cb);
+}
+
+static int ti_sci_scan_clocks_from_dt(struct sci_clk_provider *provider)
+{
+ struct device *dev = provider->dev;
+ struct device_node *np = NULL;
+ int ret;
+ int index;
+ struct of_phandle_args args;
+ struct list_head clks;
+ struct sci_clk *sci_clk, *prev;
+ int num_clks = 0;
+ int num_parents;
+ int clk_id;
+ const char * const clk_names[] = {
+ "clocks", "assigned-clocks", "assigned-clock-parents", NULL
+ };
+ const char * const *clk_name;
+
+ INIT_LIST_HEAD(&clks);
+
+ clk_name = clk_names;
+
+ while (*clk_name) {
+ np = of_find_node_with_property(np, *clk_name);
+ if (!np) {
+ clk_name++;
+ continue;
+ }
+
+ if (!of_device_is_available(np))
+ continue;
+
+ index = 0;
+
+ do {
+ ret = of_parse_phandle_with_args(np, *clk_name,
+ "#clock-cells", index,
+ &args);
+ if (ret)
+ break;
+
+ if (args.args_count == 2 && args.np == dev->of_node) {
+ sci_clk = xzalloc(sizeof(*sci_clk));
+
+ sci_clk->dev_id = args.args[0];
+ sci_clk->clk_id = args.args[1];
+ sci_clk->provider = provider;
+ provider->ops->get_num_parents(provider->sci,
+ sci_clk->dev_id,
+ sci_clk->clk_id,
+ (void *)&sci_clk->num_parents);
+ list_add_tail(&sci_clk->node, &clks);
+
+ num_clks++;
+
+ num_parents = sci_clk->num_parents;
+ if (num_parents == 1)
+ num_parents = 0;
+
+ /*
+ * Linux kernel has inherent limitation
+ * of 255 clock parents at the moment.
+ * Right now, it is not expected that
+ * any mux clock from sci-clk driver
+ * would exceed that limit either, but
+ * the ABI basically provides that
+ * possibility. Print out a warning if
+ * this happens for any clock.
+ */
+ if (num_parents >= 255) {
+ dev_warn(dev, "too many parents for dev=%d, clk=%d (%d), cropping to 255.\n",
+ sci_clk->dev_id,
+ sci_clk->clk_id, num_parents);
+ num_parents = 255;
+ }
+
+ clk_id = args.args[1] + 1;
+
+ while (num_parents--) {
+ sci_clk = xzalloc(sizeof(*sci_clk));
+ sci_clk->dev_id = args.args[0];
+ sci_clk->clk_id = clk_id++;
+ sci_clk->provider = provider;
+ list_add_tail(&sci_clk->node, &clks);
+
+ num_clks++;
+ }
+ }
+
+ index++;
+ } while (args.np);
+ }
+
+ list_sort(NULL, &clks, _cmp_sci_clk_list);
+
+ provider->clocks = xzalloc(num_clks * sizeof(sci_clk));
+
+ num_clks = 0;
+ prev = NULL;
+
+ list_for_each_entry(sci_clk, &clks, node) {
+ if (prev && prev->dev_id == sci_clk->dev_id &&
+ prev->clk_id == sci_clk->clk_id)
+ continue;
+
+ provider->clocks[num_clks++] = sci_clk;
+ prev = sci_clk;
+ }
+
+ provider->num_clocks = num_clks;
+
+ return 0;
+}
+#endif
+
+/**
+ * ti_sci_clk_probe - Probe function for the TI SCI clock driver
+ * @pdev: platform device pointer to be probed
+ *
+ * Probes the TI SCI clock device. Allocates a new clock provider
+ * and registers this to the common clock framework. Also applies
+ * any required flags to the identified clocks via clock lists
+ * supplied from DT. Returns 0 for success, negative error value
+ * for failure.
+ */
+static int ti_sci_clk_probe(struct device *dev)
+{
+ struct device_node *np = dev->of_node;
+ struct sci_clk_provider *provider;
+ const struct ti_sci_handle *handle;
+ int ret;
+
+ handle = ti_sci_get_handle(dev);
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+
+ provider = xzalloc(sizeof(*provider));
+
+ provider->sci = handle;
+ provider->ops = &handle->ops.clk_ops;
+ provider->dev = dev;
+
+ ret = ti_sci_scan_clocks_from_dt(provider);
+ if (ret) {
+ dev_err(dev, "scan clocks from DT failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = ti_sci_init_clocks(provider);
+ if (ret) {
+ pr_err("ti-sci-init-clocks failed.\n");
+ return ret;
+ }
+
+ return of_clk_add_hw_provider(np, sci_clk_get, provider);
+}
+
+static struct driver ti_sci_clk_driver = {
+ .probe = ti_sci_clk_probe,
+ .name = "ti-sci-clk",
+ .of_compatible = DRV_OF_COMPAT(ti_sci_clk_of_match),
+};
+
+core_platform_driver(ti_sci_clk_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TI System Control Interface(SCI) Clock driver");
+MODULE_AUTHOR("Tero Kristo");
+MODULE_ALIAS("platform:ti-sci-clk");
diff --git a/drivers/clk/vexpress/clk-sp810.c b/drivers/clk/vexpress/clk-sp810.c
index 78ec67fd15..6eba0a2285 100644
--- a/drivers/clk/vexpress/clk-sp810.c
+++ b/drivers/clk/vexpress/clk-sp810.c
@@ -1,7 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2013 ARM Limited
- */
+// SPDX-FileCopyrightText: 2013 ARM Limited
#include <common.h>
#include <io.h>
@@ -17,15 +15,15 @@
struct clk_sp810;
struct clk_sp810_timerclken {
- struct clk hw;
+ struct clk_hw hw;
struct clk_sp810 *sp810;
int channel;
};
static inline struct clk_sp810_timerclken *
-to_clk_sp810_timerclken(struct clk *clk)
+to_clk_sp810_timerclken(struct clk_hw *hw)
{
- return container_of(clk, struct clk_sp810_timerclken, hw);
+ return container_of(hw, struct clk_sp810_timerclken, hw);
}
struct clk_sp810 {
@@ -34,12 +32,12 @@ struct clk_sp810 {
struct clk_sp810_timerclken timerclken[4];
};
-static int clk_sp810_timerclken_get_parent(struct clk *hw)
+static int clk_sp810_timerclken_get_parent(struct clk_hw *hw)
{
return 1;
}
-static int clk_sp810_timerclken_set_parent(struct clk *hw, u8 index)
+static int clk_sp810_timerclken_set_parent(struct clk_hw *hw, u8 index)
{
struct clk_sp810_timerclken *timerclken = to_clk_sp810_timerclken(hw);
struct clk_sp810 *sp810 = timerclken->sp810;
@@ -73,7 +71,7 @@ static struct clk *clk_sp810_timerclken_of_get(struct of_phandle_args *clkspec,
clkspec->args[0] >= ARRAY_SIZE(sp810->timerclken)))
return NULL;
- return &sp810->timerclken[clkspec->args[0]].hw;
+ return &sp810->timerclken[clkspec->args[0]].hw.clk;
}
static void clk_sp810_of_setup(struct device_node *node)
@@ -102,18 +100,18 @@ static void clk_sp810_of_setup(struct device_node *node)
sp810->timerclken[i].sp810 = sp810;
sp810->timerclken[i].channel = i;
- sp810->timerclken[i].hw.name = strdup(name);
- sp810->timerclken[i].hw.parent_names = parent_names;
- sp810->timerclken[i].hw.num_parents = num;
- sp810->timerclken[i].hw.ops = &clk_sp810_timerclken_ops;
+ sp810->timerclken[i].hw.clk.name = strdup(name);
+ sp810->timerclken[i].hw.clk.parent_names = parent_names;
+ sp810->timerclken[i].hw.clk.num_parents = num;
+ sp810->timerclken[i].hw.clk.ops = &clk_sp810_timerclken_ops;
+
+ bclk_register(&sp810->timerclken[i].hw.clk);
/*
* Always set parent to 1MHz clock to match QEMU emulation
* and satisfy requirements on real HW.
*/
clk_sp810_timerclken_set_parent(&sp810->timerclken[i].hw, 1);
-
- clk_register(&sp810->timerclken[i].hw);
}
of_clk_add_provider(node, clk_sp810_timerclken_of_get, sp810);
diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c
index 1d9d28ea14..d6de583e32 100644
--- a/drivers/clk/zynq/clkc.c
+++ b/drivers/clk/zynq/clkc.c
@@ -15,7 +15,7 @@
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/err.h>
-#include <mach/zynq7000-regs.h>
+#include <mach/zynq/zynq7000-regs.h>
#include <malloc.h>
enum zynq_clk {
@@ -50,25 +50,25 @@ static struct clk *clks[clk_max];
static struct clk_onecell_data clk_data;
struct zynq_pll_clk {
- struct clk clk;
+ struct clk_hw hw;
u32 pll_lock;
void __iomem *pll_ctrl;
};
-#define to_zynq_pll_clk(c) container_of(c, struct zynq_pll_clk, clk)
+#define to_zynq_pll_clk(c) container_of(c, struct zynq_pll_clk, hw)
#define PLL_CTRL_FDIV(x) (((x) >> 12) & 0x7F)
-static unsigned long zynq_pll_recalc_rate(struct clk *clk,
+static unsigned long zynq_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct zynq_pll_clk *pll = to_zynq_pll_clk(clk);
+ struct zynq_pll_clk *pll = to_zynq_pll_clk(hw);
return parent_rate * PLL_CTRL_FDIV(readl(pll->pll_ctrl));
}
-static int zynq_pll_enable(struct clk *clk)
+static int zynq_pll_enable(struct clk_hw *hw)
{
- struct zynq_pll_clk *pll = to_zynq_pll_clk(clk);
+ struct zynq_pll_clk *pll = to_zynq_pll_clk(hw);
u32 val;
int timeout = 10000;
@@ -87,9 +87,9 @@ static int zynq_pll_enable(struct clk *clk)
return 0;
}
-static int zynq_pll_is_enabled(struct clk *clk)
+static int zynq_pll_is_enabled(struct clk_hw *hw)
{
- struct zynq_pll_clk *pll = to_zynq_pll_clk(clk);
+ struct zynq_pll_clk *pll = to_zynq_pll_clk(hw);
u32 val = readl(pll->pll_ctrl);
return !(val & (PLL_CTRL_PWRDOWN | PLL_CTRL_RESET));
@@ -111,10 +111,10 @@ static inline struct clk *zynq_pll_clk(enum zynq_pll_type type,
pll = xzalloc(sizeof(*pll));
pll->pll_ctrl = pll_ctrl;
- pll->clk.ops = &zynq_pll_clk_ops;
- pll->clk.name = name;
- pll->clk.parent_names = &pll_parent;
- pll->clk.num_parents = 1;
+ pll->hw.clk.ops = &zynq_pll_clk_ops;
+ pll->hw.clk.name = name;
+ pll->hw.clk.parent_names = &pll_parent;
+ pll->hw.clk.num_parents = 1;
switch(type) {
case ZYNQ_PLL_ARM:
@@ -128,17 +128,17 @@ static inline struct clk *zynq_pll_clk(enum zynq_pll_type type,
break;
}
- ret = clk_register(&pll->clk);
+ ret = bclk_register(&pll->hw.clk);
if (ret) {
free(pll);
return ERR_PTR(ret);
}
- return &pll->clk;
+ return &pll->hw.clk;
}
struct zynq_periph_clk {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *clk_ctrl;
};
@@ -150,16 +150,16 @@ static const u8 periph_clk_parent_map[] = {
#define PERIPH_CLK_CTRL_SRC(x) (periph_clk_parent_map[((x) & 0x30) >> 4])
#define PERIPH_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8)
-static unsigned long zynq_periph_recalc_rate(struct clk *clk,
+static unsigned long zynq_periph_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct zynq_periph_clk *periph = to_zynq_periph_clk(clk);
+ struct zynq_periph_clk *periph = to_zynq_periph_clk(hw);
return parent_rate / PERIPH_CLK_CTRL_DIV(readl(periph->clk_ctrl));
}
-static int zynq_periph_get_parent(struct clk *clk)
+static int zynq_periph_get_parent(struct clk_hw *hw)
{
- struct zynq_periph_clk *periph = to_zynq_periph_clk(clk);
+ struct zynq_periph_clk *periph = to_zynq_periph_clk(hw);
return PERIPH_CLK_CTRL_SRC(readl(periph->clk_ctrl));
}
@@ -181,18 +181,18 @@ static struct clk *zynq_periph_clk(const char *name, void __iomem *clk_ctrl)
periph = xzalloc(sizeof(*periph));
periph->clk_ctrl = clk_ctrl;
- periph->clk.name = name;
- periph->clk.ops = &zynq_periph_clk_ops;
- periph->clk.parent_names = peripheral_parents;
- periph->clk.num_parents = ARRAY_SIZE(peripheral_parents);
+ periph->hw.clk.name = name;
+ periph->hw.clk.ops = &zynq_periph_clk_ops;
+ periph->hw.clk.parent_names = peripheral_parents;
+ periph->hw.clk.num_parents = ARRAY_SIZE(peripheral_parents);
- ret = clk_register(&periph->clk);
+ ret = bclk_register(&periph->hw.clk);
if (ret) {
free(periph);
return ERR_PTR(ret);
}
- return &periph->clk;
+ return &periph->hw.clk;
}
/* CPU Clock domain is modelled as a mux with 4 children subclks, whose
@@ -200,7 +200,7 @@ static struct clk *zynq_periph_clk(const char *name, void __iomem *clk_ctrl)
*/
struct zynq_cpu_clk {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *clk_ctrl;
};
@@ -212,16 +212,16 @@ static const u8 zynq_cpu_clk_parent_map[] = {
#define CPU_CLK_SRCSEL(x) (zynq_cpu_clk_parent_map[(((x) & 0x30) >> 4)])
#define CPU_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8)
-static unsigned long zynq_cpu_clk_recalc_rate(struct clk *clk,
+static unsigned long zynq_cpu_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(clk);
+ struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(hw);
return parent_rate / CPU_CLK_CTRL_DIV(readl(cpuclk->clk_ctrl));
}
-static int zynq_cpu_clk_get_parent(struct clk *clk)
+static int zynq_cpu_clk_get_parent(struct clk_hw *hw)
{
- struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(clk);
+ struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(hw);
return CPU_CLK_SRCSEL(readl(cpuclk->clk_ctrl));
}
@@ -243,18 +243,18 @@ static struct clk *zynq_cpu_clk(const char *name, void __iomem *clk_ctrl)
cpu = xzalloc(sizeof(*cpu));
cpu->clk_ctrl = clk_ctrl;
- cpu->clk.ops = &zynq_cpu_clk_ops;
- cpu->clk.name = name;
- cpu->clk.parent_names = cpu_parents;
- cpu->clk.num_parents = ARRAY_SIZE(cpu_parents);
+ cpu->hw.clk.ops = &zynq_cpu_clk_ops;
+ cpu->hw.clk.name = name;
+ cpu->hw.clk.parent_names = cpu_parents;
+ cpu->hw.clk.num_parents = ARRAY_SIZE(cpu_parents);
- ret = clk_register(&cpu->clk);
+ ret = bclk_register(&cpu->hw.clk);
if (ret) {
free(cpu);
return ERR_PTR(ret);
}
- return &cpu->clk;
+ return &cpu->hw.clk;
}
enum zynq_cpu_subclk_which {
@@ -265,7 +265,7 @@ enum zynq_cpu_subclk_which {
};
struct zynq_cpu_subclk {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *clk_ctrl;
void __iomem *clk_621;
enum zynq_cpu_subclk_which which;
@@ -273,16 +273,16 @@ struct zynq_cpu_subclk {
#define CLK_621_TRUE(x) ((x) & 1)
-#define to_zynq_cpu_subclk(c) container_of(c, struct zynq_cpu_subclk, c);
+#define to_zynq_cpu_subclk(c) container_of(c, struct zynq_cpu_subclk, hw);
-static unsigned long zynq_cpu_subclk_recalc_rate(struct clk *clk,
+static unsigned long zynq_cpu_subclk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
unsigned long uninitialized_var(rate);
struct zynq_cpu_subclk *subclk;
bool is_621;
- subclk = to_zynq_cpu_subclk(clk);
+ subclk = to_zynq_cpu_subclk(hw);
is_621 = CLK_621_TRUE(readl(subclk->clk_621));
switch (subclk->which) {
@@ -303,12 +303,12 @@ static unsigned long zynq_cpu_subclk_recalc_rate(struct clk *clk,
return rate;
}
-static int zynq_cpu_subclk_enable(struct clk *clk)
+static int zynq_cpu_subclk_enable(struct clk_hw *hw)
{
struct zynq_cpu_subclk *subclk;
u32 tmp;
- subclk = to_zynq_cpu_subclk(clk);
+ subclk = to_zynq_cpu_subclk(hw);
tmp = readl(subclk->clk_ctrl);
tmp |= 1 << (24 + subclk->which);
@@ -317,12 +317,12 @@ static int zynq_cpu_subclk_enable(struct clk *clk)
return 0;
}
-static void zynq_cpu_subclk_disable(struct clk *clk)
+static void zynq_cpu_subclk_disable(struct clk_hw *hw)
{
struct zynq_cpu_subclk *subclk;
u32 tmp;
- subclk = to_zynq_cpu_subclk(clk);
+ subclk = to_zynq_cpu_subclk(hw);
tmp = readl(subclk->clk_ctrl);
tmp &= ~(1 << (24 + subclk->which));
@@ -349,26 +349,26 @@ static struct clk *zynq_cpu_subclk(const char *name,
subclk->clk_ctrl = clk_ctrl;
subclk->clk_621 = clk_621;
subclk->which = which;
- subclk->clk.name = name;
- subclk->clk.ops = &zynq_cpu_subclk_ops;
+ subclk->hw.clk.name = name;
+ subclk->hw.clk.ops = &zynq_cpu_subclk_ops;
- subclk->clk.parent_names = &subclk_parent;
- subclk->clk.num_parents = 1;
+ subclk->hw.clk.parent_names = &subclk_parent;
+ subclk->hw.clk.num_parents = 1;
- ret = clk_register(&subclk->clk);
+ ret = bclk_register(&subclk->hw.clk);
if (ret) {
free(subclk);
return ERR_PTR(ret);
}
- return &subclk->clk;
+ return &subclk->hw.clk;
}
-static int zynq_clock_probe(struct device_d *dev)
+static int zynq_clock_probe(struct device *dev)
{
struct resource *iores;
void __iomem *clk_base;
- unsigned long ps_clk_rate = 33333330;
+ u32 ps_clk_rate = 33333330;
resource_size_t slcr_offset = 0;
iores = dev_get_resource(dev, IORESOURCE_MEM, 0);
@@ -380,7 +380,7 @@ static int zynq_clock_probe(struct device_d *dev)
* in the SCLR region. So we can't directly map the address we get from
* the DT, but need to add the SCLR base offset.
*/
- if (dev->device_node) {
+ if (dev->of_node) {
struct resource *parent_res;
parent_res = dev_get_resource(dev->parent, IORESOURCE_MEM, 0);
@@ -390,6 +390,8 @@ static int zynq_clock_probe(struct device_d *dev)
slcr_offset = parent_res->start;
}
+ of_property_read_u32(dev->device_node, "ps-clk-frequency", &ps_clk_rate);
+
iores = request_iomem_region(dev_name(dev), iores->start + slcr_offset,
iores->end + slcr_offset);
if (IS_ERR(iores))
@@ -470,7 +472,7 @@ static int zynq_clock_probe(struct device_d *dev)
clk_data.clks = clks;
clk_data.clk_num = ARRAY_SIZE(clks);
- of_clk_add_provider(dev->device_node, of_clk_src_onecell_get,
+ of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
&clk_data);
return 0;
@@ -483,15 +485,12 @@ static __maybe_unused struct of_device_id zynq_clock_dt_ids[] = {
/* sentinel */
}
};
+MODULE_DEVICE_TABLE(of, zynq_clock_dt_ids);
-static struct driver_d zynq_clock_driver = {
+static struct driver zynq_clock_driver = {
.probe = zynq_clock_probe,
.name = "zynq-clock",
.of_compatible = DRV_OF_COMPAT(zynq_clock_dt_ids),
};
-static int zynq_clock_init(void)
-{
- return platform_driver_register(&zynq_clock_driver);
-}
-postcore_initcall(zynq_clock_init);
+postcore_platform_driver(zynq_clock_driver);
diff --git a/drivers/clk/zynqmp/clk-divider-zynqmp.c b/drivers/clk/zynqmp/clk-divider-zynqmp.c
index 2fe65b566a..d78cda38b7 100644
--- a/drivers/clk/zynqmp/clk-divider-zynqmp.c
+++ b/drivers/clk/zynqmp/clk-divider-zynqmp.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Zynq UltraScale+ MPSoC Clock Divider
*
@@ -11,19 +11,19 @@
#include <common.h>
#include <linux/clk.h>
-#include <mach/firmware-zynqmp.h>
+#include <mach/zynqmp/firmware-zynqmp.h>
#include "clk-zynqmp.h"
struct zynqmp_clk_divider {
- struct clk clk;
+ struct clk_hw hw;
unsigned int clk_id;
enum topology_type type;
const char *parent;
const struct zynqmp_eemi_ops *ops;
};
-#define to_zynqmp_clk_divider(clk) \
- container_of(clk, struct zynqmp_clk_divider, clk)
+#define to_zynqmp_clk_divider(_hw) \
+ container_of(_hw, struct zynqmp_clk_divider, hw)
static int zynqmp_clk_divider_bestdiv(unsigned long rate,
unsigned long *best_parent_rate)
@@ -31,10 +31,10 @@ static int zynqmp_clk_divider_bestdiv(unsigned long rate,
return DIV_ROUND_CLOSEST(*best_parent_rate, rate);
}
-static unsigned long zynqmp_clk_divider_recalc_rate(struct clk *clk,
+static unsigned long zynqmp_clk_divider_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct zynqmp_clk_divider *div = to_zynqmp_clk_divider(clk);
+ struct zynqmp_clk_divider *div = to_zynqmp_clk_divider(hw);
u32 value;
div->ops->clock_getdivider(div->clk_id, &value);
@@ -46,7 +46,7 @@ static unsigned long zynqmp_clk_divider_recalc_rate(struct clk *clk,
return DIV_ROUND_UP(parent_rate, value);
}
-static long zynqmp_clk_divider_round_rate(struct clk *clk, unsigned long rate,
+static long zynqmp_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
int bestdiv;
@@ -56,10 +56,10 @@ static long zynqmp_clk_divider_round_rate(struct clk *clk, unsigned long rate,
return *parent_rate / bestdiv;
}
-static int zynqmp_clk_divider_set_rate(struct clk *clk, unsigned long rate,
+static int zynqmp_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct zynqmp_clk_divider *div = to_zynqmp_clk_divider(clk);
+ struct zynqmp_clk_divider *div = to_zynqmp_clk_divider(hw);
u32 bestdiv;
bestdiv = zynqmp_clk_divider_bestdiv(rate, &parent_rate);
@@ -95,17 +95,17 @@ struct clk *zynqmp_clk_register_divider(const char *name,
div->ops = zynqmp_pm_get_eemi_ops();
div->parent = strdup(parents[0]);
- div->clk.name = strdup(name);
- div->clk.ops = &zynqmp_clk_divider_ops;
- div->clk.flags = nodes->flag;
- div->clk.parent_names = &div->parent;
- div->clk.num_parents = 1;
+ div->hw.clk.name = strdup(name);
+ div->hw.clk.ops = &zynqmp_clk_divider_ops;
+ div->hw.clk.flags = nodes->flag;
+ div->hw.clk.parent_names = &div->parent;
+ div->hw.clk.num_parents = 1;
- ret = clk_register(&div->clk);
+ ret = bclk_register(&div->hw.clk);
if (ret) {
kfree(div);
return ERR_PTR(ret);
}
- return &div->clk;
+ return &div->hw.clk;
}
diff --git a/drivers/clk/zynqmp/clk-gate-zynqmp.c b/drivers/clk/zynqmp/clk-gate-zynqmp.c
index 6f03357768..daa17c34b8 100644
--- a/drivers/clk/zynqmp/clk-gate-zynqmp.c
+++ b/drivers/clk/zynqmp/clk-gate-zynqmp.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Zynq UltraScale+ MPSoC Clock Gate
*
@@ -11,36 +11,39 @@
#include <common.h>
#include <linux/clk.h>
-#include <mach/firmware-zynqmp.h>
+#include <mach/zynqmp/firmware-zynqmp.h>
#include "clk-zynqmp.h"
struct zynqmp_clk_gate {
- struct clk clk;
+ struct clk_hw hw;
unsigned int clk_id;
const char *parent;
const struct zynqmp_eemi_ops *ops;
};
-#define to_zynqmp_clk_gate(_hw) container_of(_hw, struct zynqmp_clk_gate, clk)
+#define to_zynqmp_clk_gate(_hw) container_of(_hw, struct zynqmp_clk_gate, hw)
-static int zynqmp_clk_gate_enable(struct clk *clk)
+static int zynqmp_clk_gate_enable(struct clk_hw *hw)
{
- struct zynqmp_clk_gate *gate = to_zynqmp_clk_gate(clk);
+ struct zynqmp_clk_gate *gate = to_zynqmp_clk_gate(hw);
+
+ if (clk_hw_is_enabled(hw))
+ return 0;
return gate->ops->clock_enable(gate->clk_id);
}
-static void zynqmp_clk_gate_disable(struct clk *clk)
+static void zynqmp_clk_gate_disable(struct clk_hw *hw)
{
- struct zynqmp_clk_gate *gate = to_zynqmp_clk_gate(clk);
+ struct zynqmp_clk_gate *gate = to_zynqmp_clk_gate(hw);
gate->ops->clock_disable(gate->clk_id);
}
-static int zynqmp_clk_gate_is_enabled(struct clk *clk)
+static int zynqmp_clk_gate_is_enabled(struct clk_hw *hw)
{
- struct zynqmp_clk_gate *gate = to_zynqmp_clk_gate(clk);
+ struct zynqmp_clk_gate *gate = to_zynqmp_clk_gate(hw);
u32 state;
int ret;
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
@@ -77,17 +80,17 @@ struct clk *zynqmp_clk_register_gate(const char *name,
gate->ops = zynqmp_pm_get_eemi_ops();
gate->parent = strdup(parents[0]);
- gate->clk.name = strdup(name);
- gate->clk.ops = &zynqmp_clk_gate_ops;
- gate->clk.flags = nodes->flag | CLK_SET_RATE_PARENT;
- gate->clk.parent_names = &gate->parent;
- gate->clk.num_parents = 1;
+ gate->hw.clk.name = strdup(name);
+ gate->hw.clk.ops = &zynqmp_clk_gate_ops;
+ gate->hw.clk.flags = nodes->flag | CLK_SET_RATE_PARENT;
+ gate->hw.clk.parent_names = &gate->parent;
+ gate->hw.clk.num_parents = 1;
- ret = clk_register(&gate->clk);
+ ret = bclk_register(&gate->hw.clk);
if (ret) {
kfree(gate);
return ERR_PTR(ret);
}
- return &gate->clk;
+ return &gate->hw.clk;
}
diff --git a/drivers/clk/zynqmp/clk-mux-zynqmp.c b/drivers/clk/zynqmp/clk-mux-zynqmp.c
index 4c15223980..fe31cff4b6 100644
--- a/drivers/clk/zynqmp/clk-mux-zynqmp.c
+++ b/drivers/clk/zynqmp/clk-mux-zynqmp.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Zynq UltraScale+ MPSoC Clock Multiplexer
*
@@ -11,24 +11,24 @@
#include <common.h>
#include <linux/clk.h>
-#include <mach/firmware-zynqmp.h>
+#include <mach/zynqmp/firmware-zynqmp.h>
#include "clk-zynqmp.h"
#define ZYNQMP_CLK_MUX_READ_ONLY BIT(3)
struct zynqmp_clk_mux {
- struct clk clk;
+ struct clk_hw hw;
u32 clk_id;
const struct zynqmp_eemi_ops *ops;
};
-#define to_zynqmp_clk_mux(clk) \
- container_of(clk, struct zynqmp_clk_mux, clk)
+#define to_zynqmp_clk_mux(_hw) \
+ container_of(_hw, struct zynqmp_clk_mux, hw)
-static int zynqmp_clk_mux_get_parent(struct clk *clk)
+static int zynqmp_clk_mux_get_parent(struct clk_hw *hw)
{
- struct zynqmp_clk_mux *mux = to_zynqmp_clk_mux(clk);
+ struct zynqmp_clk_mux *mux = to_zynqmp_clk_mux(hw);
u32 value;
mux->ops->clock_getparent(mux->clk_id, &value);
@@ -36,9 +36,9 @@ static int zynqmp_clk_mux_get_parent(struct clk *clk)
return value;
}
-static int zynqmp_clk_mux_set_parent(struct clk *clk, u8 index)
+static int zynqmp_clk_mux_set_parent(struct clk_hw *hw, u8 index)
{
- struct zynqmp_clk_mux *mux = to_zynqmp_clk_mux(clk);
+ struct zynqmp_clk_mux *mux = to_zynqmp_clk_mux(hw);
return mux->ops->clock_setparent(mux->clk_id, index);
}
@@ -82,21 +82,21 @@ struct clk *zynqmp_clk_register_mux(const char *name,
mux->clk_id = clk_id;
mux->ops = zynqmp_pm_get_eemi_ops();
- mux->clk.name = strdup(name);
+ mux->hw.clk.name = strdup(name);
if (nodes->type_flag & ZYNQMP_CLK_MUX_READ_ONLY)
- mux->clk.ops = &zynqmp_clk_mux_ro_ops;
+ mux->hw.clk.ops = &zynqmp_clk_mux_ro_ops;
else
- mux->clk.ops = &zynqmp_clk_mux_ops;
- mux->clk.flags = nodes->flag | CLK_SET_RATE_PARENT;
- mux->clk.parent_names = parent_names;
- mux->clk.num_parents = num_parents;
+ mux->hw.clk.ops = &zynqmp_clk_mux_ops;
+ mux->hw.clk.flags = nodes->flag | CLK_SET_RATE_PARENT;
+ mux->hw.clk.parent_names = parent_names;
+ mux->hw.clk.num_parents = num_parents;
- ret = clk_register(&mux->clk);
+ ret = bclk_register(&mux->hw.clk);
if (ret) {
kfree(parent_names);
kfree(mux);
return ERR_PTR(ret);
}
- return &mux->clk;
+ return &mux->hw.clk;
}
diff --git a/drivers/clk/zynqmp/clk-pll-zynqmp.c b/drivers/clk/zynqmp/clk-pll-zynqmp.c
index e4b759b73c..b386780f18 100644
--- a/drivers/clk/zynqmp/clk-pll-zynqmp.c
+++ b/drivers/clk/zynqmp/clk-pll-zynqmp.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Zynq UltraScale+ MPSoC PLL Clock
*
@@ -11,19 +11,19 @@
#include <common.h>
#include <linux/clk.h>
-#include <mach/firmware-zynqmp.h>
+#include <mach/zynqmp/firmware-zynqmp.h>
#include "clk-zynqmp.h"
struct zynqmp_pll {
- struct clk clk;
+ struct clk_hw hw;
unsigned int clk_id;
const char *parent;
const struct zynqmp_eemi_ops *ops;
};
-#define to_zynqmp_pll(clk) \
- container_of(clk, struct zynqmp_pll, clk)
+#define to_zynqmp_pll(_hw) \
+ container_of(_hw, struct zynqmp_pll, hw)
#define PLL_FBDIV_MIN 25
#define PLL_FBDIV_MAX 125
@@ -53,10 +53,10 @@ static inline void zynqmp_pll_set_mode(struct zynqmp_pll *pll, enum pll_mode mod
pll->ops->ioctl(0, IOCTL_SET_PLL_FRAC_MODE, pll->clk_id, mode, NULL);
}
-static long zynqmp_pll_round_rate(struct clk *clk, unsigned long rate,
+static long zynqmp_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
- struct zynqmp_pll *pll = to_zynqmp_pll(clk);
+ struct zynqmp_pll *pll = to_zynqmp_pll(hw);
u32 fbdiv;
long rate_div;
@@ -84,10 +84,10 @@ static long zynqmp_pll_round_rate(struct clk *clk, unsigned long rate,
return rate;
}
-static unsigned long zynqmp_pll_recalc_rate(struct clk *clk,
+static unsigned long zynqmp_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
- struct zynqmp_pll *pll = to_zynqmp_pll(clk);
+ struct zynqmp_pll *pll = to_zynqmp_pll(hw);
u32 clk_id = pll->clk_id;
u32 fbdiv, data;
unsigned long rate, frac;
@@ -109,10 +109,10 @@ static unsigned long zynqmp_pll_recalc_rate(struct clk *clk,
return rate;
}
-static int zynqmp_pll_set_rate(struct clk *clk, unsigned long rate,
+static int zynqmp_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct zynqmp_pll *pll = to_zynqmp_pll(clk);
+ struct zynqmp_pll *pll = to_zynqmp_pll(hw);
u32 clk_id = pll->clk_id;
u32 fbdiv;
long rate_div, frac, m, f;
@@ -138,9 +138,9 @@ static int zynqmp_pll_set_rate(struct clk *clk, unsigned long rate,
}
}
-static int zynqmp_pll_is_enabled(struct clk *clk)
+static int zynqmp_pll_is_enabled(struct clk_hw *hw)
{
- struct zynqmp_pll *pll = to_zynqmp_pll(clk);
+ struct zynqmp_pll *pll = to_zynqmp_pll(hw);
u32 is_enabled;
int ret;
@@ -151,21 +151,21 @@ static int zynqmp_pll_is_enabled(struct clk *clk)
return !!(is_enabled);
}
-static int zynqmp_pll_enable(struct clk *clk)
+static int zynqmp_pll_enable(struct clk_hw *hw)
{
- struct zynqmp_pll *pll = to_zynqmp_pll(clk);
+ struct zynqmp_pll *pll = to_zynqmp_pll(hw);
- if (zynqmp_pll_is_enabled(clk))
+ if (zynqmp_pll_is_enabled(hw))
return 0;
return pll->ops->clock_enable(pll->clk_id);
}
-static void zynqmp_pll_disable(struct clk *clk)
+static void zynqmp_pll_disable(struct clk_hw *hw)
{
- struct zynqmp_pll *pll = to_zynqmp_pll(clk);
+ struct zynqmp_pll *pll = to_zynqmp_pll(hw);
- if (!zynqmp_pll_is_enabled(clk))
+ if (!zynqmp_pll_is_enabled(hw))
return;
pll->ops->clock_disable(pll->clk_id);
@@ -197,17 +197,17 @@ struct clk *zynqmp_clk_register_pll(const char *name,
pll->ops = zynqmp_pm_get_eemi_ops();
pll->parent = strdup(parents[0]);
- pll->clk.name = strdup(name);
- pll->clk.ops = &zynqmp_pll_ops;
- pll->clk.flags = nodes->flag | CLK_SET_RATE_PARENT;
- pll->clk.parent_names = &pll->parent;
- pll->clk.num_parents = 1;
+ pll->hw.clk.name = strdup(name);
+ pll->hw.clk.ops = &zynqmp_pll_ops;
+ pll->hw.clk.flags = nodes->flag | CLK_SET_RATE_PARENT;
+ pll->hw.clk.parent_names = &pll->parent;
+ pll->hw.clk.num_parents = 1;
- ret = clk_register(&pll->clk);
+ ret = bclk_register(&pll->hw.clk);
if (ret) {
kfree(pll);
return ERR_PTR(ret);
}
- return &pll->clk;
+ return &pll->hw.clk;
}
diff --git a/drivers/clk/zynqmp/clk-zynqmp.h b/drivers/clk/zynqmp/clk-zynqmp.h
index eeee9d2b5a..508660e7f0 100644
--- a/drivers/clk/zynqmp/clk-zynqmp.h
+++ b/drivers/clk/zynqmp/clk-zynqmp.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2016-2018 Xilinx
*/
diff --git a/drivers/clk/zynqmp/clkc.c b/drivers/clk/zynqmp/clkc.c
index 366a12e70a..35eaf6f18e 100644
--- a/drivers/clk/zynqmp/clkc.c
+++ b/drivers/clk/zynqmp/clkc.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Zynq UltraScale+ MPSoC Clock Controller
*
@@ -14,7 +14,7 @@
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
-#include <mach/firmware-zynqmp.h>
+#include <mach/zynqmp/firmware-zynqmp.h>
#include "clk-zynqmp.h"
@@ -446,14 +446,14 @@ static struct clk *zynqmp_register_clk_topology(char *clk_name,
return clk;
}
-static int zynqmp_register_clocks(struct device_d *dev,
+static int zynqmp_register_clocks(struct device *dev,
struct clk **clks, size_t num_clocks)
{
unsigned int i;
const char *parent_names[MAX_PARENT];
char *name;
- struct device_node *node = dev->device_node;
- unsigned int num_parents;
+ struct device_node *node = dev->of_node;
+ int num_parents;
for (i = 0; i < num_clocks; i++) {
if (zynqmp_get_clock_type(i) != CLK_TYPE_OUTPUT)
@@ -518,7 +518,7 @@ static void zynqmp_fill_clock_info(struct zynqmp_clock_info *clock_info,
}
}
-static int zynqmp_clock_probe(struct device_d *dev)
+static int zynqmp_clock_probe(struct device *dev)
{
int err;
u32 api_version;
@@ -558,7 +558,7 @@ static int zynqmp_clock_probe(struct device_d *dev)
zynqmp_register_clocks(dev, clk_data->clks, num_clocks);
clk_data->clk_num = num_clocks;
- of_clk_add_provider(dev->device_node, of_clk_src_onecell_get, clk_data);
+ of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, clk_data);
/*
* We can free clock_info now, as is only used to store clock info
@@ -573,8 +573,9 @@ static struct of_device_id zynqmp_clock_of_match[] = {
{.compatible = "xlnx,zynqmp-clk"},
{},
};
+MODULE_DEVICE_TABLE(of, zynqmp_clock_of_match);
-static struct driver_d zynqmp_clock_driver = {
+static struct driver zynqmp_clock_driver = {
.probe = zynqmp_clock_probe,
.name = "zynqmp_clock",
.of_compatible = DRV_OF_COMPAT(zynqmp_clock_of_match),