aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSasha Levin <sashal@kernel.org>2024-05-07 07:49:19 -0400
committerSasha Levin <sashal@kernel.org>2024-05-07 07:49:19 -0400
commitc71ca580823804a41d6907ce4b8cad1a953149f3 (patch)
treeecc1ae7af85ea83225eb2a7e2cefc3a73b162dbe
parentbd432fd5ca9e6e60693e62e31024775be1833e4f (diff)
downloadstable-queue-c71ca580823804a41d6907ce4b8cad1a953149f3.tar.gz
Fixes for 5.10
Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--queue-5.10/clk-sunxi-ng-add-support-for-the-allwinner-h616-ccu.patch1479
-rw-r--r--queue-5.10/clk-sunxi-ng-h6-reparent-cpux-during-pll-cpux-rate-c.patch73
-rw-r--r--queue-5.10/clk-sunxi-ng-unregister-clocks-resets-when-unbinding.patch497
-rw-r--r--queue-5.10/series3
4 files changed, 2052 insertions, 0 deletions
diff --git a/queue-5.10/clk-sunxi-ng-add-support-for-the-allwinner-h616-ccu.patch b/queue-5.10/clk-sunxi-ng-add-support-for-the-allwinner-h616-ccu.patch
new file mode 100644
index 0000000000..d63c357f76
--- /dev/null
+++ b/queue-5.10/clk-sunxi-ng-add-support-for-the-allwinner-h616-ccu.patch
@@ -0,0 +1,1479 @@
+From fd42fc298293c7ce92503a76cd4c4270f5e10301 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Jan 2021 17:24:43 +0000
+Subject: clk: sunxi-ng: Add support for the Allwinner H616 CCU
+
+From: Andre Przywara <andre.przywara@arm.com>
+
+[ Upstream commit 88dde5e23da1a16fe9a417171e6c941736b8d3a6 ]
+
+While the clocks are fairly similar to the H6, many differ in tiny
+details, so a separate clock driver seems indicated.
+
+Derived from the H6 clock driver, and adjusted according to the manual.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+Acked-by: Maxime Ripard <mripard@kernel.org>
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+Link: https://lore.kernel.org/r/20210127172500.13356-4-andre.przywara@arm.com
+Stable-dep-of: 7e91ed763dc0 ("clk: sunxi-ng: h6: Reparent CPUX during PLL CPUX rate change")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/sunxi-ng/Kconfig | 5 +
+ drivers/clk/sunxi-ng/Makefile | 1 +
+ drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 1150 +++++++++++++++++++
+ drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 56 +
+ include/dt-bindings/clock/sun50i-h616-ccu.h | 115 ++
+ include/dt-bindings/reset/sun50i-h616-ccu.h | 70 ++
+ 6 files changed, 1397 insertions(+)
+ create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.c
+ create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.h
+ create mode 100644 include/dt-bindings/clock/sun50i-h616-ccu.h
+ create mode 100644 include/dt-bindings/reset/sun50i-h616-ccu.h
+
+diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
+index ce5f5847d5d39..e6d3bebb10477 100644
+--- a/drivers/clk/sunxi-ng/Kconfig
++++ b/drivers/clk/sunxi-ng/Kconfig
+@@ -32,6 +32,11 @@ config SUN50I_H6_CCU
+ default ARM64 && ARCH_SUNXI
+ depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
+
++config SUN50I_H616_CCU
++ bool "Support for the Allwinner H616 CCU"
++ default ARM64 && ARCH_SUNXI
++ depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
++
+ config SUN50I_H6_R_CCU
+ bool "Support for the Allwinner H6 PRCM CCU"
+ default ARM64 && ARCH_SUNXI
+diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
+index 3eb5cff40eac4..96c324306d97f 100644
+--- a/drivers/clk/sunxi-ng/Makefile
++++ b/drivers/clk/sunxi-ng/Makefile
+@@ -26,6 +26,7 @@ obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o
+ obj-$(CONFIG_SUN50I_A100_CCU) += ccu-sun50i-a100.o
+ obj-$(CONFIG_SUN50I_A100_R_CCU) += ccu-sun50i-a100-r.o
+ obj-$(CONFIG_SUN50I_H6_CCU) += ccu-sun50i-h6.o
++obj-$(CONFIG_SUN50I_H616_CCU) += ccu-sun50i-h616.o
+ obj-$(CONFIG_SUN50I_H6_R_CCU) += ccu-sun50i-h6-r.o
+ obj-$(CONFIG_SUN4I_A10_CCU) += ccu-sun4i-a10.o
+ obj-$(CONFIG_SUN5I_CCU) += ccu-sun5i.o
+diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
+new file mode 100644
+index 0000000000000..225307305880e
+--- /dev/null
++++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
+@@ -0,0 +1,1150 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (c) 2020 Arm Ltd.
++ * Based on the H6 CCU driver, which is:
++ * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io>
++ */
++
++#include <linux/clk-provider.h>
++#include <linux/io.h>
++#include <linux/of_address.h>
++#include <linux/platform_device.h>
++
++#include "ccu_common.h"
++#include "ccu_reset.h"
++
++#include "ccu_div.h"
++#include "ccu_gate.h"
++#include "ccu_mp.h"
++#include "ccu_mult.h"
++#include "ccu_nk.h"
++#include "ccu_nkm.h"
++#include "ccu_nkmp.h"
++#include "ccu_nm.h"
++
++#include "ccu-sun50i-h616.h"
++
++/*
++ * The CPU PLL is actually NP clock, with P being /1, /2 or /4. However
++ * P should only be used for output frequencies lower than 288 MHz.
++ *
++ * For now we can just model it as a multiplier clock, and force P to /1.
++ *
++ * The M factor is present in the register's description, but not in the
++ * frequency formula, and it's documented as "M is only used for backdoor
++ * testing", so it's not modelled and then force to 0.
++ */
++#define SUN50I_H616_PLL_CPUX_REG 0x000
++static struct ccu_mult pll_cpux_clk = {
++ .enable = BIT(31),
++ .lock = BIT(28),
++ .mult = _SUNXI_CCU_MULT_MIN(8, 8, 12),
++ .common = {
++ .reg = 0x000,
++ .hw.init = CLK_HW_INIT("pll-cpux", "osc24M",
++ &ccu_mult_ops,
++ CLK_SET_RATE_UNGATE),
++ },
++};
++
++/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
++#define SUN50I_H616_PLL_DDR0_REG 0x010
++static struct ccu_nkmp pll_ddr0_clk = {
++ .enable = BIT(31),
++ .lock = BIT(28),
++ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
++ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
++ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
++ .common = {
++ .reg = 0x010,
++ .hw.init = CLK_HW_INIT("pll-ddr0", "osc24M",
++ &ccu_nkmp_ops,
++ CLK_SET_RATE_UNGATE),
++ },
++};
++
++#define SUN50I_H616_PLL_DDR1_REG 0x018
++static struct ccu_nkmp pll_ddr1_clk = {
++ .enable = BIT(31),
++ .lock = BIT(28),
++ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
++ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
++ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
++ .common = {
++ .reg = 0x018,
++ .hw.init = CLK_HW_INIT("pll-ddr1", "osc24M",
++ &ccu_nkmp_ops,
++ CLK_SET_RATE_UNGATE),
++ },
++};
++
++#define SUN50I_H616_PLL_PERIPH0_REG 0x020
++static struct ccu_nkmp pll_periph0_clk = {
++ .enable = BIT(31),
++ .lock = BIT(28),
++ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
++ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
++ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
++ .fixed_post_div = 2,
++ .common = {
++ .reg = 0x020,
++ .features = CCU_FEATURE_FIXED_POSTDIV,
++ .hw.init = CLK_HW_INIT("pll-periph0", "osc24M",
++ &ccu_nkmp_ops,
++ CLK_SET_RATE_UNGATE),
++ },
++};
++
++#define SUN50I_H616_PLL_PERIPH1_REG 0x028
++static struct ccu_nkmp pll_periph1_clk = {
++ .enable = BIT(31),
++ .lock = BIT(28),
++ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
++ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
++ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
++ .fixed_post_div = 2,
++ .common = {
++ .reg = 0x028,
++ .features = CCU_FEATURE_FIXED_POSTDIV,
++ .hw.init = CLK_HW_INIT("pll-periph1", "osc24M",
++ &ccu_nkmp_ops,
++ CLK_SET_RATE_UNGATE),
++ },
++};
++
++#define SUN50I_H616_PLL_GPU_REG 0x030
++static struct ccu_nkmp pll_gpu_clk = {
++ .enable = BIT(31),
++ .lock = BIT(28),
++ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
++ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
++ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
++ .common = {
++ .reg = 0x030,
++ .hw.init = CLK_HW_INIT("pll-gpu", "osc24M",
++ &ccu_nkmp_ops,
++ CLK_SET_RATE_UNGATE),
++ },
++};
++
++/*
++ * For Video PLLs, the output divider is described as "used for testing"
++ * in the user manual. So it's not modelled and forced to 0.
++ */
++#define SUN50I_H616_PLL_VIDEO0_REG 0x040
++static struct ccu_nm pll_video0_clk = {
++ .enable = BIT(31),
++ .lock = BIT(28),
++ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
++ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
++ .fixed_post_div = 4,
++ .min_rate = 288000000,
++ .max_rate = 2400000000UL,
++ .common = {
++ .reg = 0x040,
++ .features = CCU_FEATURE_FIXED_POSTDIV,
++ .hw.init = CLK_HW_INIT("pll-video0", "osc24M",
++ &ccu_nm_ops,
++ CLK_SET_RATE_UNGATE),
++ },
++};
++
++#define SUN50I_H616_PLL_VIDEO1_REG 0x048
++static struct ccu_nm pll_video1_clk = {
++ .enable = BIT(31),
++ .lock = BIT(28),
++ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
++ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
++ .fixed_post_div = 4,
++ .min_rate = 288000000,
++ .max_rate = 2400000000UL,
++ .common = {
++ .reg = 0x048,
++ .features = CCU_FEATURE_FIXED_POSTDIV,
++ .hw.init = CLK_HW_INIT("pll-video1", "osc24M",
++ &ccu_nm_ops,
++ CLK_SET_RATE_UNGATE),
++ },
++};
++
++#define SUN50I_H616_PLL_VIDEO2_REG 0x050
++static struct ccu_nm pll_video2_clk = {
++ .enable = BIT(31),
++ .lock = BIT(28),
++ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
++ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
++ .fixed_post_div = 4,
++ .min_rate = 288000000,
++ .max_rate = 2400000000UL,
++ .common = {
++ .reg = 0x050,
++ .features = CCU_FEATURE_FIXED_POSTDIV,
++ .hw.init = CLK_HW_INIT("pll-video2", "osc24M",
++ &ccu_nm_ops,
++ CLK_SET_RATE_UNGATE),
++ },
++};
++
++#define SUN50I_H616_PLL_VE_REG 0x058
++static struct ccu_nkmp pll_ve_clk = {
++ .enable = BIT(31),
++ .lock = BIT(28),
++ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
++ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
++ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
++ .common = {
++ .reg = 0x058,
++ .hw.init = CLK_HW_INIT("pll-ve", "osc24M",
++ &ccu_nkmp_ops,
++ CLK_SET_RATE_UNGATE),
++ },
++};
++
++#define SUN50I_H616_PLL_DE_REG 0x060
++static struct ccu_nkmp pll_de_clk = {
++ .enable = BIT(31),
++ .lock = BIT(28),
++ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
++ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
++ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
++ .common = {
++ .reg = 0x060,
++ .hw.init = CLK_HW_INIT("pll-de", "osc24M",
++ &ccu_nkmp_ops,
++ CLK_SET_RATE_UNGATE),
++ },
++};
++
++/*
++ * TODO: Determine SDM settings for the audio PLL. The manual suggests
++ * PLL_FACTOR_N=16, PLL_POST_DIV_P=2, OUTPUT_DIV=2, pattern=0xe000c49b
++ * for 24.576 MHz, and PLL_FACTOR_N=22, PLL_POST_DIV_P=3, OUTPUT_DIV=2,
++ * pattern=0xe001288c for 22.5792 MHz.
++ * This clashes with our fixed PLL_POST_DIV_P.
++ */
++#define SUN50I_H616_PLL_AUDIO_REG 0x078
++static struct ccu_nm pll_audio_hs_clk = {
++ .enable = BIT(31),
++ .lock = BIT(28),
++ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
++ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
++ .common = {
++ .reg = 0x078,
++ .hw.init = CLK_HW_INIT("pll-audio-hs", "osc24M",
++ &ccu_nm_ops,
++ CLK_SET_RATE_UNGATE),
++ },
++};
++
++static const char * const cpux_parents[] = { "osc24M", "osc32k",
++ "iosc", "pll-cpux", "pll-periph0" };
++static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents,
++ 0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
++static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x500, 0, 2, 0);
++static SUNXI_CCU_M(cpux_apb_clk, "cpux-apb", "cpux", 0x500, 8, 2, 0);
++
++static const char * const psi_ahb1_ahb2_parents[] = { "osc24M", "osc32k",
++ "iosc", "pll-periph0" };
++static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2",
++ psi_ahb1_ahb2_parents,
++ 0x510,
++ 0, 2, /* M */
++ 8, 2, /* P */
++ 24, 2, /* mux */
++ 0);
++
++static const char * const ahb3_apb1_apb2_parents[] = { "osc24M", "osc32k",
++ "psi-ahb1-ahb2",
++ "pll-periph0" };
++static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c,
++ 0, 2, /* M */
++ 8, 2, /* P */
++ 24, 2, /* mux */
++ 0);
++
++static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520,
++ 0, 2, /* M */
++ 8, 2, /* P */
++ 24, 2, /* mux */
++ 0);
++
++static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524,
++ 0, 2, /* M */
++ 8, 2, /* P */
++ 24, 2, /* mux */
++ 0);
++
++static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x",
++ "pll-ddr0", "pll-ddr1" };
++static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, 0x540,
++ 0, 3, /* M */
++ 24, 2, /* mux */
++ BIT(31), /* gate */
++ CLK_IS_CRITICAL);
++
++static const char * const de_parents[] = { "pll-de", "pll-periph0-2x" };
++static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
++ 0, 4, /* M */
++ 24, 1, /* mux */
++ BIT(31), /* gate */
++ CLK_SET_RATE_PARENT);
++
++static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "psi-ahb1-ahb2",
++ 0x60c, BIT(0), 0);
++
++static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace",
++ de_parents,
++ 0x620,
++ 0, 4, /* M */
++ 24, 1, /* mux */
++ BIT(31), /* gate */
++ 0);
++
++static SUNXI_CCU_GATE(bus_deinterlace_clk, "bus-deinterlace", "psi-ahb1-ahb2",
++ 0x62c, BIT(0), 0);
++
++static SUNXI_CCU_M_WITH_MUX_GATE(g2d_clk, "g2d", de_parents, 0x630,
++ 0, 4, /* M */
++ 24, 1, /* mux */
++ BIT(31), /* gate */
++ 0);
++
++static SUNXI_CCU_GATE(bus_g2d_clk, "bus-g2d", "psi-ahb1-ahb2",
++ 0x63c, BIT(0), 0);
++
++static const char * const gpu0_parents[] = { "pll-gpu", "gpu1" };
++static SUNXI_CCU_M_WITH_MUX_GATE(gpu0_clk, "gpu0", gpu0_parents, 0x670,
++ 0, 2, /* M */
++ 24, 1, /* mux */
++ BIT(31), /* gate */
++ CLK_SET_RATE_PARENT);
++static SUNXI_CCU_M_WITH_GATE(gpu1_clk, "gpu1", "pll-periph0-2x", 0x674,
++ 0, 2, /* M */
++ BIT(31),/* gate */
++ 0);
++
++static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "psi-ahb1-ahb2",
++ 0x67c, BIT(0), 0);
++
++static const char * const ce_parents[] = { "osc24M", "pll-periph0-2x" };
++static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
++ 0, 4, /* M */
++ 8, 2, /* N */
++ 24, 1, /* mux */
++ BIT(31),/* gate */
++ 0);
++
++static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "psi-ahb1-ahb2",
++ 0x68c, BIT(0), 0);
++
++static const char * const ve_parents[] = { "pll-ve" };
++static SUNXI_CCU_M_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
++ 0, 3, /* M */
++ 24, 1, /* mux */
++ BIT(31), /* gate */
++ CLK_SET_RATE_PARENT);
++
++static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "psi-ahb1-ahb2",
++ 0x69c, BIT(0), 0);
++
++static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "psi-ahb1-ahb2",
++ 0x70c, BIT(0), 0);
++
++static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "psi-ahb1-ahb2",
++ 0x73c, BIT(0), 0);
++
++static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x740, BIT(31), 0);
++
++static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "psi-ahb1-ahb2",
++ 0x78c, BIT(0), 0);
++
++static SUNXI_CCU_GATE(bus_psi_clk, "bus-psi", "psi-ahb1-ahb2",
++ 0x79c, BIT(0), 0);
++
++static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x7ac, BIT(0), 0);
++
++static SUNXI_CCU_GATE(bus_iommu_clk, "bus-iommu", "apb1", 0x7bc, BIT(0), 0);
++
++static const char * const dram_parents[] = { "pll-ddr0", "pll-ddr1" };
++static struct ccu_div dram_clk = {
++ .div = _SUNXI_CCU_DIV(0, 2),
++ .mux = _SUNXI_CCU_MUX(24, 2),
++ .common = {
++ .reg = 0x800,
++ .hw.init = CLK_HW_INIT_PARENTS("dram",
++ dram_parents,
++ &ccu_div_ops,
++ CLK_IS_CRITICAL),
++ },
++};
++
++static SUNXI_CCU_GATE(mbus_dma_clk, "mbus-dma", "mbus",
++ 0x804, BIT(0), 0);
++static SUNXI_CCU_GATE(mbus_ve_clk, "mbus-ve", "mbus",
++ 0x804, BIT(1), 0);
++static SUNXI_CCU_GATE(mbus_ce_clk, "mbus-ce", "mbus",
++ 0x804, BIT(2), 0);
++static SUNXI_CCU_GATE(mbus_ts_clk, "mbus-ts", "mbus",
++ 0x804, BIT(3), 0);
++static SUNXI_CCU_GATE(mbus_nand_clk, "mbus-nand", "mbus",
++ 0x804, BIT(5), 0);
++static SUNXI_CCU_GATE(mbus_g2d_clk, "mbus-g2d", "mbus",
++ 0x804, BIT(10), 0);
++
++static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "psi-ahb1-ahb2",
++ 0x80c, BIT(0), CLK_IS_CRITICAL);
++
++static const char * const nand_spi_parents[] = { "osc24M", "pll-periph0",
++ "pll-periph1", "pll-periph0-2x",
++ "pll-periph1-2x" };
++static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_clk, "nand0", nand_spi_parents, 0x810,
++ 0, 4, /* M */
++ 8, 2, /* N */
++ 24, 3, /* mux */
++ BIT(31),/* gate */
++ 0);
++
++static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_clk, "nand1", nand_spi_parents, 0x814,
++ 0, 4, /* M */
++ 8, 2, /* N */
++ 24, 3, /* mux */
++ BIT(31),/* gate */
++ 0);
++
++static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb3", 0x82c, BIT(0), 0);
++
++static const char * const mmc_parents[] = { "osc24M", "pll-periph0-2x",
++ "pll-periph1-2x" };
++static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0", mmc_parents, 0x830,
++ 0, 4, /* M */
++ 8, 2, /* N */
++ 24, 2, /* mux */
++ BIT(31), /* gate */
++ 2, /* post-div */
++ 0);
++
++static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1", mmc_parents, 0x834,
++ 0, 4, /* M */
++ 8, 2, /* N */
++ 24, 2, /* mux */
++ BIT(31), /* gate */
++ 2, /* post-div */
++ 0);
++
++static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc2_clk, "mmc2", mmc_parents, 0x838,
++ 0, 4, /* M */
++ 8, 2, /* N */
++ 24, 2, /* mux */
++ BIT(31), /* gate */
++ 2, /* post-div */
++ 0);
++
++static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb3", 0x84c, BIT(0), 0);
++static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb3", 0x84c, BIT(1), 0);
++static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb3", 0x84c, BIT(2), 0);
++
++static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", 0x90c, BIT(0), 0);
++static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", 0x90c, BIT(1), 0);
++static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", 0x90c, BIT(2), 0);
++static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", 0x90c, BIT(3), 0);
++static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4", "apb2", 0x90c, BIT(4), 0);
++static SUNXI_CCU_GATE(bus_uart5_clk, "bus-uart5", "apb2", 0x90c, BIT(5), 0);
++
++static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", 0x91c, BIT(0), 0);
++static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", 0x91c, BIT(1), 0);
++static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", 0x91c, BIT(2), 0);
++static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3", "apb2", 0x91c, BIT(3), 0);
++static SUNXI_CCU_GATE(bus_i2c4_clk, "bus-i2c4", "apb2", 0x91c, BIT(4), 0);
++
++static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", nand_spi_parents, 0x940,
++ 0, 4, /* M */
++ 8, 2, /* N */
++ 24, 3, /* mux */
++ BIT(31),/* gate */
++ 0);
++
++static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", nand_spi_parents, 0x944,
++ 0, 4, /* M */
++ 8, 2, /* N */
++ 24, 3, /* mux */
++ BIT(31),/* gate */
++ 0);
++
++static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb3", 0x96c, BIT(0), 0);
++static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb3", 0x96c, BIT(1), 0);
++
++static SUNXI_CCU_GATE(emac_25m_clk, "emac-25m", "ahb3", 0x970,
++ BIT(31) | BIT(30), 0);
++
++static SUNXI_CCU_GATE(bus_emac0_clk, "bus-emac0", "ahb3", 0x97c, BIT(0), 0);
++static SUNXI_CCU_GATE(bus_emac1_clk, "bus-emac1", "ahb3", 0x97c, BIT(1), 0);
++
++static const char * const ts_parents[] = { "osc24M", "pll-periph0" };
++static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x9b0,
++ 0, 4, /* M */
++ 8, 2, /* N */
++ 24, 1, /* mux */
++ BIT(31),/* gate */
++ 0);
++
++static SUNXI_CCU_GATE(bus_ts_clk, "bus-ts", "ahb3", 0x9bc, BIT(0), 0);
++
++static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths", "apb1", 0x9fc, BIT(0), 0);
++
++static const char * const audio_parents[] = { "pll-audio-1x", "pll-audio-2x",
++ "pll-audio-4x", "pll-audio-hs" };
++static struct ccu_div spdif_clk = {
++ .enable = BIT(31),
++ .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
++ .mux = _SUNXI_CCU_MUX(24, 2),
++ .common = {
++ .reg = 0xa20,
++ .hw.init = CLK_HW_INIT_PARENTS("spdif",
++ audio_parents,
++ &ccu_div_ops,
++ 0),
++ },
++};
++
++static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", 0xa2c, BIT(0), 0);
++
++static struct ccu_div dmic_clk = {
++ .enable = BIT(31),
++ .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
++ .mux = _SUNXI_CCU_MUX(24, 2),
++ .common = {
++ .reg = 0xa40,
++ .hw.init = CLK_HW_INIT_PARENTS("dmic",
++ audio_parents,
++ &ccu_div_ops,
++ 0),
++ },
++};
++
++static SUNXI_CCU_GATE(bus_dmic_clk, "bus-dmic", "apb1", 0xa4c, BIT(0), 0);
++
++static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_1x_clk, "audio-codec-1x",
++ audio_parents, 0xa50,
++ 0, 4, /* M */
++ 24, 2, /* mux */
++ BIT(31), /* gate */
++ CLK_SET_RATE_PARENT);
++static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_4x_clk, "audio-codec-4x",
++ audio_parents, 0xa54,
++ 0, 4, /* M */
++ 24, 2, /* mux */
++ BIT(31), /* gate */
++ CLK_SET_RATE_PARENT);
++
++static SUNXI_CCU_GATE(bus_audio_codec_clk, "bus-audio-codec", "apb1", 0xa5c,
++ BIT(0), 0);
++
++static struct ccu_div audio_hub_clk = {
++ .enable = BIT(31),
++ .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
++ .mux = _SUNXI_CCU_MUX(24, 2),
++ .common = {
++ .reg = 0xa60,
++ .hw.init = CLK_HW_INIT_PARENTS("audio-hub",
++ audio_parents,
++ &ccu_div_ops,
++ 0),
++ },
++};
++
++static SUNXI_CCU_GATE(bus_audio_hub_clk, "bus-audio-hub", "apb1", 0xa6c, BIT(0), 0);
++
++/*
++ * There are OHCI 12M clock source selection bits for the four USB 2.0 ports.
++ * We will force them to 0 (12M divided from 48M).
++ */
++#define SUN50I_H616_USB0_CLK_REG 0xa70
++#define SUN50I_H616_USB1_CLK_REG 0xa74
++#define SUN50I_H616_USB2_CLK_REG 0xa78
++#define SUN50I_H616_USB3_CLK_REG 0xa7c
++
++static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", 0xa70, BIT(31), 0);
++static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", 0xa70, BIT(29), 0);
++
++static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "osc12M", 0xa74, BIT(31), 0);
++static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", 0xa74, BIT(29), 0);
++
++static SUNXI_CCU_GATE(usb_ohci2_clk, "usb-ohci2", "osc12M", 0xa78, BIT(31), 0);
++static SUNXI_CCU_GATE(usb_phy2_clk, "usb-phy2", "osc24M", 0xa78, BIT(29), 0);
++
++static SUNXI_CCU_GATE(usb_ohci3_clk, "usb-ohci3", "osc12M", 0xa7c, BIT(31), 0);
++static SUNXI_CCU_GATE(usb_phy3_clk, "usb-phy3", "osc24M", 0xa7c, BIT(29), 0);
++
++static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb3", 0xa8c, BIT(0), 0);
++static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb3", 0xa8c, BIT(1), 0);
++static SUNXI_CCU_GATE(bus_ohci2_clk, "bus-ohci2", "ahb3", 0xa8c, BIT(2), 0);
++static SUNXI_CCU_GATE(bus_ohci3_clk, "bus-ohci3", "ahb3", 0xa8c, BIT(3), 0);
++static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb3", 0xa8c, BIT(4), 0);
++static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1", "ahb3", 0xa8c, BIT(5), 0);
++static SUNXI_CCU_GATE(bus_ehci2_clk, "bus-ehci2", "ahb3", 0xa8c, BIT(6), 0);
++static SUNXI_CCU_GATE(bus_ehci3_clk, "bus-ehci3", "ahb3", 0xa8c, BIT(7), 0);
++static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb3", 0xa8c, BIT(8), 0);
++
++static SUNXI_CCU_GATE(bus_keyadc_clk, "bus-keyadc", "apb1", 0xa9c, BIT(0), 0);
++
++static const char * const hdmi_parents[] = { "pll-video0", "pll-video0-4x",
++ "pll-video2", "pll-video2-4x" };
++static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents, 0xb00,
++ 0, 4, /* M */
++ 24, 2, /* mux */
++ BIT(31), /* gate */
++ 0);
++
++static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow", "osc24M", 0xb04, BIT(31), 0);
++
++static const char * const hdmi_cec_parents[] = { "osc32k", "pll-periph0-2x" };
++static const struct ccu_mux_fixed_prediv hdmi_cec_predivs[] = {
++ { .index = 1, .div = 36621 },
++};
++
++#define SUN50I_H616_HDMI_CEC_CLK_REG 0xb10
++static struct ccu_mux hdmi_cec_clk = {
++ .enable = BIT(31) | BIT(30),
++
++ .mux = {
++ .shift = 24,
++ .width = 2,
++
++ .fixed_predivs = hdmi_cec_predivs,
++ .n_predivs = ARRAY_SIZE(hdmi_cec_predivs),
++ },
++
++ .common = {
++ .reg = 0xb10,
++ .features = CCU_FEATURE_FIXED_PREDIV,
++ .hw.init = CLK_HW_INIT_PARENTS("hdmi-cec",
++ hdmi_cec_parents,
++ &ccu_mux_ops,
++ 0),
++ },
++};
++
++static SUNXI_CCU_GATE(bus_hdmi_clk, "bus-hdmi", "ahb3", 0xb1c, BIT(0), 0);
++
++static SUNXI_CCU_GATE(bus_tcon_top_clk, "bus-tcon-top", "ahb3",
++ 0xb5c, BIT(0), 0);
++
++static const char * const tcon_tv_parents[] = { "pll-video0",
++ "pll-video0-4x",
++ "pll-video1",
++ "pll-video1-4x" };
++static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0",
++ tcon_tv_parents, 0xb80,
++ 0, 4, /* M */
++ 8, 2, /* P */
++ 24, 3, /* mux */
++ BIT(31), /* gate */
++ CLK_SET_RATE_PARENT);
++static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1",
++ tcon_tv_parents, 0xb84,
++ 0, 4, /* M */
++ 8, 2, /* P */
++ 24, 3, /* mux */
++ BIT(31), /* gate */
++ CLK_SET_RATE_PARENT);
++
++static SUNXI_CCU_GATE(bus_tcon_tv0_clk, "bus-tcon-tv0", "ahb3",
++ 0xb9c, BIT(0), 0);
++static SUNXI_CCU_GATE(bus_tcon_tv1_clk, "bus-tcon-tv1", "ahb3",
++ 0xb9c, BIT(1), 0);
++
++static SUNXI_CCU_MP_WITH_MUX_GATE(tve0_clk, "tve0",
++ tcon_tv_parents, 0xbb0,
++ 0, 4, /* M */
++ 8, 2, /* P */
++ 24, 3, /* mux */
++ BIT(31), /* gate */
++ CLK_SET_RATE_PARENT);
++
++static SUNXI_CCU_GATE(bus_tve_top_clk, "bus-tve-top", "ahb3",
++ 0xbbc, BIT(0), 0);
++static SUNXI_CCU_GATE(bus_tve0_clk, "bus-tve0", "ahb3",
++ 0xbbc, BIT(1), 0);
++
++static const char * const hdcp_parents[] = { "pll-periph0", "pll-periph1" };
++static SUNXI_CCU_M_WITH_MUX_GATE(hdcp_clk, "hdcp", hdcp_parents, 0xc40,
++ 0, 4, /* M */
++ 24, 2, /* mux */
++ BIT(31), /* gate */
++ 0);
++
++static SUNXI_CCU_GATE(bus_hdcp_clk, "bus-hdcp", "ahb3", 0xc4c, BIT(0), 0);
++
++/* Fixed factor clocks */
++static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0);
++
++static const struct clk_hw *clk_parent_pll_audio[] = {
++ &pll_audio_hs_clk.common.hw
++};
++
++/*
++ * The divider of pll-audio is fixed to 24 for now, so 24576000 and 22579200
++ * rates can be set exactly in conjunction with sigma-delta modulation.
++ */
++static CLK_FIXED_FACTOR_HWS(pll_audio_1x_clk, "pll-audio-1x",
++ clk_parent_pll_audio,
++ 96, 1, CLK_SET_RATE_PARENT);
++static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
++ clk_parent_pll_audio,
++ 48, 1, CLK_SET_RATE_PARENT);
++static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
++ clk_parent_pll_audio,
++ 24, 1, CLK_SET_RATE_PARENT);
++
++static const struct clk_hw *pll_periph0_parents[] = {
++ &pll_periph0_clk.common.hw
++};
++
++static CLK_FIXED_FACTOR_HWS(pll_periph0_2x_clk, "pll-periph0-2x",
++ pll_periph0_parents,
++ 1, 2, 0);
++
++static const struct clk_hw *pll_periph1_parents[] = {
++ &pll_periph1_clk.common.hw
++};
++
++static CLK_FIXED_FACTOR_HWS(pll_periph1_2x_clk, "pll-periph1-2x",
++ pll_periph1_parents,
++ 1, 2, 0);
++
++static CLK_FIXED_FACTOR_HW(pll_video0_4x_clk, "pll-video0-4x",
++ &pll_video0_clk.common.hw,
++ 1, 4, CLK_SET_RATE_PARENT);
++static CLK_FIXED_FACTOR_HW(pll_video1_4x_clk, "pll-video1-4x",
++ &pll_video1_clk.common.hw,
++ 1, 4, CLK_SET_RATE_PARENT);
++static CLK_FIXED_FACTOR_HW(pll_video2_4x_clk, "pll-video2-4x",
++ &pll_video2_clk.common.hw,
++ 1, 4, CLK_SET_RATE_PARENT);
++
++static struct ccu_common *sun50i_h616_ccu_clks[] = {
++ &pll_cpux_clk.common,
++ &pll_ddr0_clk.common,
++ &pll_ddr1_clk.common,
++ &pll_periph0_clk.common,
++ &pll_periph1_clk.common,
++ &pll_gpu_clk.common,
++ &pll_video0_clk.common,
++ &pll_video1_clk.common,
++ &pll_video2_clk.common,
++ &pll_ve_clk.common,
++ &pll_de_clk.common,
++ &pll_audio_hs_clk.common,
++ &cpux_clk.common,
++ &axi_clk.common,
++ &cpux_apb_clk.common,
++ &psi_ahb1_ahb2_clk.common,
++ &ahb3_clk.common,
++ &apb1_clk.common,
++ &apb2_clk.common,
++ &mbus_clk.common,
++ &de_clk.common,
++ &bus_de_clk.common,
++ &deinterlace_clk.common,
++ &bus_deinterlace_clk.common,
++ &g2d_clk.common,
++ &bus_g2d_clk.common,
++ &gpu0_clk.common,
++ &bus_gpu_clk.common,
++ &gpu1_clk.common,
++ &ce_clk.common,
++ &bus_ce_clk.common,
++ &ve_clk.common,
++ &bus_ve_clk.common,
++ &bus_dma_clk.common,
++ &bus_hstimer_clk.common,
++ &avs_clk.common,
++ &bus_dbg_clk.common,
++ &bus_psi_clk.common,
++ &bus_pwm_clk.common,
++ &bus_iommu_clk.common,
++ &dram_clk.common,
++ &mbus_dma_clk.common,
++ &mbus_ve_clk.common,
++ &mbus_ce_clk.common,
++ &mbus_ts_clk.common,
++ &mbus_nand_clk.common,
++ &mbus_g2d_clk.common,
++ &bus_dram_clk.common,
++ &nand0_clk.common,
++ &nand1_clk.common,
++ &bus_nand_clk.common,
++ &mmc0_clk.common,
++ &mmc1_clk.common,
++ &mmc2_clk.common,
++ &bus_mmc0_clk.common,
++ &bus_mmc1_clk.common,
++ &bus_mmc2_clk.common,
++ &bus_uart0_clk.common,
++ &bus_uart1_clk.common,
++ &bus_uart2_clk.common,
++ &bus_uart3_clk.common,
++ &bus_uart4_clk.common,
++ &bus_uart5_clk.common,
++ &bus_i2c0_clk.common,
++ &bus_i2c1_clk.common,
++ &bus_i2c2_clk.common,
++ &bus_i2c3_clk.common,
++ &bus_i2c4_clk.common,
++ &spi0_clk.common,
++ &spi1_clk.common,
++ &bus_spi0_clk.common,
++ &bus_spi1_clk.common,
++ &emac_25m_clk.common,
++ &bus_emac0_clk.common,
++ &bus_emac1_clk.common,
++ &ts_clk.common,
++ &bus_ts_clk.common,
++ &bus_ths_clk.common,
++ &spdif_clk.common,
++ &bus_spdif_clk.common,
++ &dmic_clk.common,
++ &bus_dmic_clk.common,
++ &audio_codec_1x_clk.common,
++ &audio_codec_4x_clk.common,
++ &bus_audio_codec_clk.common,
++ &audio_hub_clk.common,
++ &bus_audio_hub_clk.common,
++ &usb_ohci0_clk.common,
++ &usb_phy0_clk.common,
++ &usb_ohci1_clk.common,
++ &usb_phy1_clk.common,
++ &usb_ohci2_clk.common,
++ &usb_phy2_clk.common,
++ &usb_ohci3_clk.common,
++ &usb_phy3_clk.common,
++ &bus_ohci0_clk.common,
++ &bus_ohci1_clk.common,
++ &bus_ohci2_clk.common,
++ &bus_ohci3_clk.common,
++ &bus_ehci0_clk.common,
++ &bus_ehci1_clk.common,
++ &bus_ehci2_clk.common,
++ &bus_ehci3_clk.common,
++ &bus_otg_clk.common,
++ &bus_keyadc_clk.common,
++ &hdmi_clk.common,
++ &hdmi_slow_clk.common,
++ &hdmi_cec_clk.common,
++ &bus_hdmi_clk.common,
++ &bus_tcon_top_clk.common,
++ &tcon_tv0_clk.common,
++ &tcon_tv1_clk.common,
++ &bus_tcon_tv0_clk.common,
++ &bus_tcon_tv1_clk.common,
++ &tve0_clk.common,
++ &bus_tve_top_clk.common,
++ &bus_tve0_clk.common,
++ &hdcp_clk.common,
++ &bus_hdcp_clk.common,
++};
++
++static struct clk_hw_onecell_data sun50i_h616_hw_clks = {
++ .hws = {
++ [CLK_OSC12M] = &osc12M_clk.hw,
++ [CLK_PLL_CPUX] = &pll_cpux_clk.common.hw,
++ [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw,
++ [CLK_PLL_DDR1] = &pll_ddr1_clk.common.hw,
++ [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw,
++ [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw,
++ [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw,
++ [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw,
++ [CLK_PLL_GPU] = &pll_gpu_clk.common.hw,
++ [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw,
++ [CLK_PLL_VIDEO0_4X] = &pll_video0_4x_clk.hw,
++ [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw,
++ [CLK_PLL_VIDEO1_4X] = &pll_video1_4x_clk.hw,
++ [CLK_PLL_VIDEO2] = &pll_video2_clk.common.hw,
++ [CLK_PLL_VIDEO2_4X] = &pll_video2_4x_clk.hw,
++ [CLK_PLL_VE] = &pll_ve_clk.common.hw,
++ [CLK_PLL_DE] = &pll_de_clk.common.hw,
++ [CLK_PLL_AUDIO_HS] = &pll_audio_hs_clk.common.hw,
++ [CLK_PLL_AUDIO_1X] = &pll_audio_1x_clk.hw,
++ [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw,
++ [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw,
++ [CLK_CPUX] = &cpux_clk.common.hw,
++ [CLK_AXI] = &axi_clk.common.hw,
++ [CLK_CPUX_APB] = &cpux_apb_clk.common.hw,
++ [CLK_PSI_AHB1_AHB2] = &psi_ahb1_ahb2_clk.common.hw,
++ [CLK_AHB3] = &ahb3_clk.common.hw,
++ [CLK_APB1] = &apb1_clk.common.hw,
++ [CLK_APB2] = &apb2_clk.common.hw,
++ [CLK_MBUS] = &mbus_clk.common.hw,
++ [CLK_DE] = &de_clk.common.hw,
++ [CLK_BUS_DE] = &bus_de_clk.common.hw,
++ [CLK_DEINTERLACE] = &deinterlace_clk.common.hw,
++ [CLK_BUS_DEINTERLACE] = &bus_deinterlace_clk.common.hw,
++ [CLK_G2D] = &g2d_clk.common.hw,
++ [CLK_BUS_G2D] = &bus_g2d_clk.common.hw,
++ [CLK_GPU0] = &gpu0_clk.common.hw,
++ [CLK_BUS_GPU] = &bus_gpu_clk.common.hw,
++ [CLK_GPU1] = &gpu1_clk.common.hw,
++ [CLK_CE] = &ce_clk.common.hw,
++ [CLK_BUS_CE] = &bus_ce_clk.common.hw,
++ [CLK_VE] = &ve_clk.common.hw,
++ [CLK_BUS_VE] = &bus_ve_clk.common.hw,
++ [CLK_BUS_DMA] = &bus_dma_clk.common.hw,
++ [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw,
++ [CLK_AVS] = &avs_clk.common.hw,
++ [CLK_BUS_DBG] = &bus_dbg_clk.common.hw,
++ [CLK_BUS_PSI] = &bus_psi_clk.common.hw,
++ [CLK_BUS_PWM] = &bus_pwm_clk.common.hw,
++ [CLK_BUS_IOMMU] = &bus_iommu_clk.common.hw,
++ [CLK_DRAM] = &dram_clk.common.hw,
++ [CLK_MBUS_DMA] = &mbus_dma_clk.common.hw,
++ [CLK_MBUS_VE] = &mbus_ve_clk.common.hw,
++ [CLK_MBUS_CE] = &mbus_ce_clk.common.hw,
++ [CLK_MBUS_TS] = &mbus_ts_clk.common.hw,
++ [CLK_MBUS_NAND] = &mbus_nand_clk.common.hw,
++ [CLK_MBUS_G2D] = &mbus_g2d_clk.common.hw,
++ [CLK_BUS_DRAM] = &bus_dram_clk.common.hw,
++ [CLK_NAND0] = &nand0_clk.common.hw,
++ [CLK_NAND1] = &nand1_clk.common.hw,
++ [CLK_BUS_NAND] = &bus_nand_clk.common.hw,
++ [CLK_MMC0] = &mmc0_clk.common.hw,
++ [CLK_MMC1] = &mmc1_clk.common.hw,
++ [CLK_MMC2] = &mmc2_clk.common.hw,
++ [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw,
++ [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw,
++ [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw,
++ [CLK_BUS_UART0] = &bus_uart0_clk.common.hw,
++ [CLK_BUS_UART1] = &bus_uart1_clk.common.hw,
++ [CLK_BUS_UART2] = &bus_uart2_clk.common.hw,
++ [CLK_BUS_UART3] = &bus_uart3_clk.common.hw,
++ [CLK_BUS_UART4] = &bus_uart4_clk.common.hw,
++ [CLK_BUS_UART5] = &bus_uart5_clk.common.hw,
++ [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw,
++ [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw,
++ [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw,
++ [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw,
++ [CLK_BUS_I2C4] = &bus_i2c4_clk.common.hw,
++ [CLK_SPI0] = &spi0_clk.common.hw,
++ [CLK_SPI1] = &spi1_clk.common.hw,
++ [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
++ [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,
++ [CLK_EMAC_25M] = &emac_25m_clk.common.hw,
++ [CLK_BUS_EMAC0] = &bus_emac0_clk.common.hw,
++ [CLK_BUS_EMAC1] = &bus_emac1_clk.common.hw,
++ [CLK_TS] = &ts_clk.common.hw,
++ [CLK_BUS_TS] = &bus_ts_clk.common.hw,
++ [CLK_BUS_THS] = &bus_ths_clk.common.hw,
++ [CLK_SPDIF] = &spdif_clk.common.hw,
++ [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw,
++ [CLK_DMIC] = &dmic_clk.common.hw,
++ [CLK_BUS_DMIC] = &bus_dmic_clk.common.hw,
++ [CLK_AUDIO_CODEC_1X] = &audio_codec_1x_clk.common.hw,
++ [CLK_AUDIO_CODEC_4X] = &audio_codec_4x_clk.common.hw,
++ [CLK_BUS_AUDIO_CODEC] = &bus_audio_codec_clk.common.hw,
++ [CLK_AUDIO_HUB] = &audio_hub_clk.common.hw,
++ [CLK_BUS_AUDIO_HUB] = &bus_audio_hub_clk.common.hw,
++ [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw,
++ [CLK_USB_PHY0] = &usb_phy0_clk.common.hw,
++ [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw,
++ [CLK_USB_PHY1] = &usb_phy1_clk.common.hw,
++ [CLK_USB_OHCI2] = &usb_ohci2_clk.common.hw,
++ [CLK_USB_PHY2] = &usb_phy2_clk.common.hw,
++ [CLK_USB_OHCI3] = &usb_ohci3_clk.common.hw,
++ [CLK_USB_PHY3] = &usb_phy3_clk.common.hw,
++ [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw,
++ [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw,
++ [CLK_BUS_OHCI2] = &bus_ohci2_clk.common.hw,
++ [CLK_BUS_OHCI3] = &bus_ohci3_clk.common.hw,
++ [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw,
++ [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw,
++ [CLK_BUS_EHCI2] = &bus_ehci2_clk.common.hw,
++ [CLK_BUS_EHCI3] = &bus_ehci3_clk.common.hw,
++ [CLK_BUS_OTG] = &bus_otg_clk.common.hw,
++ [CLK_BUS_KEYADC] = &bus_keyadc_clk.common.hw,
++ [CLK_HDMI] = &hdmi_clk.common.hw,
++ [CLK_HDMI_SLOW] = &hdmi_slow_clk.common.hw,
++ [CLK_HDMI_CEC] = &hdmi_cec_clk.common.hw,
++ [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw,
++ [CLK_BUS_TCON_TOP] = &bus_tcon_top_clk.common.hw,
++ [CLK_TCON_TV0] = &tcon_tv0_clk.common.hw,
++ [CLK_TCON_TV1] = &tcon_tv1_clk.common.hw,
++ [CLK_BUS_TCON_TV0] = &bus_tcon_tv0_clk.common.hw,
++ [CLK_BUS_TCON_TV1] = &bus_tcon_tv1_clk.common.hw,
++ [CLK_TVE0] = &tve0_clk.common.hw,
++ [CLK_BUS_TVE_TOP] = &bus_tve_top_clk.common.hw,
++ [CLK_BUS_TVE0] = &bus_tve0_clk.common.hw,
++ [CLK_HDCP] = &hdcp_clk.common.hw,
++ [CLK_BUS_HDCP] = &bus_hdcp_clk.common.hw,
++ },
++ .num = CLK_NUMBER,
++};
++
++static struct ccu_reset_map sun50i_h616_ccu_resets[] = {
++ [RST_MBUS] = { 0x540, BIT(30) },
++
++ [RST_BUS_DE] = { 0x60c, BIT(16) },
++ [RST_BUS_DEINTERLACE] = { 0x62c, BIT(16) },
++ [RST_BUS_GPU] = { 0x67c, BIT(16) },
++ [RST_BUS_CE] = { 0x68c, BIT(16) },
++ [RST_BUS_VE] = { 0x69c, BIT(16) },
++ [RST_BUS_DMA] = { 0x70c, BIT(16) },
++ [RST_BUS_HSTIMER] = { 0x73c, BIT(16) },
++ [RST_BUS_DBG] = { 0x78c, BIT(16) },
++ [RST_BUS_PSI] = { 0x79c, BIT(16) },
++ [RST_BUS_PWM] = { 0x7ac, BIT(16) },
++ [RST_BUS_IOMMU] = { 0x7bc, BIT(16) },
++ [RST_BUS_DRAM] = { 0x80c, BIT(16) },
++ [RST_BUS_NAND] = { 0x82c, BIT(16) },
++ [RST_BUS_MMC0] = { 0x84c, BIT(16) },
++ [RST_BUS_MMC1] = { 0x84c, BIT(17) },
++ [RST_BUS_MMC2] = { 0x84c, BIT(18) },
++ [RST_BUS_UART0] = { 0x90c, BIT(16) },
++ [RST_BUS_UART1] = { 0x90c, BIT(17) },
++ [RST_BUS_UART2] = { 0x90c, BIT(18) },
++ [RST_BUS_UART3] = { 0x90c, BIT(19) },
++ [RST_BUS_UART4] = { 0x90c, BIT(20) },
++ [RST_BUS_UART5] = { 0x90c, BIT(21) },
++ [RST_BUS_I2C0] = { 0x91c, BIT(16) },
++ [RST_BUS_I2C1] = { 0x91c, BIT(17) },
++ [RST_BUS_I2C2] = { 0x91c, BIT(18) },
++ [RST_BUS_I2C3] = { 0x91c, BIT(19) },
++ [RST_BUS_I2C4] = { 0x91c, BIT(20) },
++ [RST_BUS_SPI0] = { 0x96c, BIT(16) },
++ [RST_BUS_SPI1] = { 0x96c, BIT(17) },
++ [RST_BUS_EMAC0] = { 0x97c, BIT(16) },
++ [RST_BUS_EMAC1] = { 0x97c, BIT(17) },
++ [RST_BUS_TS] = { 0x9bc, BIT(16) },
++ [RST_BUS_THS] = { 0x9fc, BIT(16) },
++ [RST_BUS_SPDIF] = { 0xa2c, BIT(16) },
++ [RST_BUS_DMIC] = { 0xa4c, BIT(16) },
++ [RST_BUS_AUDIO_CODEC] = { 0xa5c, BIT(16) },
++ [RST_BUS_AUDIO_HUB] = { 0xa6c, BIT(16) },
++
++ [RST_USB_PHY0] = { 0xa70, BIT(30) },
++ [RST_USB_PHY1] = { 0xa74, BIT(30) },
++ [RST_USB_PHY2] = { 0xa78, BIT(30) },
++ [RST_USB_PHY3] = { 0xa7c, BIT(30) },
++ [RST_BUS_OHCI0] = { 0xa8c, BIT(16) },
++ [RST_BUS_OHCI1] = { 0xa8c, BIT(17) },
++ [RST_BUS_OHCI2] = { 0xa8c, BIT(18) },
++ [RST_BUS_OHCI3] = { 0xa8c, BIT(19) },
++ [RST_BUS_EHCI0] = { 0xa8c, BIT(20) },
++ [RST_BUS_EHCI1] = { 0xa8c, BIT(21) },
++ [RST_BUS_EHCI2] = { 0xa8c, BIT(22) },
++ [RST_BUS_EHCI3] = { 0xa8c, BIT(23) },
++ [RST_BUS_OTG] = { 0xa8c, BIT(24) },
++ [RST_BUS_KEYADC] = { 0xa9c, BIT(16) },
++
++ [RST_BUS_HDMI] = { 0xb1c, BIT(16) },
++ [RST_BUS_HDMI_SUB] = { 0xb1c, BIT(17) },
++ [RST_BUS_TCON_TOP] = { 0xb5c, BIT(16) },
++ [RST_BUS_TCON_TV0] = { 0xb9c, BIT(16) },
++ [RST_BUS_TCON_TV1] = { 0xb9c, BIT(17) },
++ [RST_BUS_TVE_TOP] = { 0xbbc, BIT(16) },
++ [RST_BUS_TVE0] = { 0xbbc, BIT(17) },
++ [RST_BUS_HDCP] = { 0xc4c, BIT(16) },
++};
++
++static const struct sunxi_ccu_desc sun50i_h616_ccu_desc = {
++ .ccu_clks = sun50i_h616_ccu_clks,
++ .num_ccu_clks = ARRAY_SIZE(sun50i_h616_ccu_clks),
++
++ .hw_clks = &sun50i_h616_hw_clks,
++
++ .resets = sun50i_h616_ccu_resets,
++ .num_resets = ARRAY_SIZE(sun50i_h616_ccu_resets),
++};
++
++static const u32 pll_regs[] = {
++ SUN50I_H616_PLL_CPUX_REG,
++ SUN50I_H616_PLL_DDR0_REG,
++ SUN50I_H616_PLL_DDR1_REG,
++ SUN50I_H616_PLL_PERIPH0_REG,
++ SUN50I_H616_PLL_PERIPH1_REG,
++ SUN50I_H616_PLL_GPU_REG,
++ SUN50I_H616_PLL_VIDEO0_REG,
++ SUN50I_H616_PLL_VIDEO1_REG,
++ SUN50I_H616_PLL_VIDEO2_REG,
++ SUN50I_H616_PLL_VE_REG,
++ SUN50I_H616_PLL_DE_REG,
++ SUN50I_H616_PLL_AUDIO_REG,
++};
++
++static const u32 pll_video_regs[] = {
++ SUN50I_H616_PLL_VIDEO0_REG,
++ SUN50I_H616_PLL_VIDEO1_REG,
++ SUN50I_H616_PLL_VIDEO2_REG,
++};
++
++static const u32 usb2_clk_regs[] = {
++ SUN50I_H616_USB0_CLK_REG,
++ SUN50I_H616_USB1_CLK_REG,
++ SUN50I_H616_USB2_CLK_REG,
++ SUN50I_H616_USB3_CLK_REG,
++};
++
++static void __init sun50i_h616_ccu_setup(struct device_node *node)
++{
++ void __iomem *reg;
++ u32 val;
++ int i;
++
++ reg = of_io_request_and_map(node, 0, of_node_full_name(node));
++ if (IS_ERR(reg)) {
++ pr_err("%pOF: Could not map clock registers\n", node);
++ return;
++ }
++
++ /* Enable the lock bits and the output enable bits on all PLLs */
++ for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
++ val = readl(reg + pll_regs[i]);
++ val |= BIT(29) | BIT(27);
++ writel(val, reg + pll_regs[i]);
++ }
++
++ /*
++ * Force the output divider of video PLLs to 0.
++ *
++ * See the comment before pll-video0 definition for the reason.
++ */
++ for (i = 0; i < ARRAY_SIZE(pll_video_regs); i++) {
++ val = readl(reg + pll_video_regs[i]);
++ val &= ~BIT(0);
++ writel(val, reg + pll_video_regs[i]);
++ }
++
++ /*
++ * Force OHCI 12M clock sources to 00 (12MHz divided from 48MHz)
++ *
++ * This clock mux is still mysterious, and the code just enforces
++ * it to have a valid clock parent.
++ */
++ for (i = 0; i < ARRAY_SIZE(usb2_clk_regs); i++) {
++ val = readl(reg + usb2_clk_regs[i]);
++ val &= ~GENMASK(25, 24);
++ writel(val, reg + usb2_clk_regs[i]);
++ }
++
++ /*
++ * Force the post-divider of pll-audio to 12 and the output divider
++ * of it to 2, so 24576000 and 22579200 rates can be set exactly.
++ */
++ val = readl(reg + SUN50I_H616_PLL_AUDIO_REG);
++ val &= ~(GENMASK(21, 16) | BIT(0));
++ writel(val | (11 << 16) | BIT(0), reg + SUN50I_H616_PLL_AUDIO_REG);
++
++ /*
++ * First clock parent (osc32K) is unusable for CEC. But since there
++ * is no good way to force parent switch (both run with same frequency),
++ * just set second clock parent here.
++ */
++ val = readl(reg + SUN50I_H616_HDMI_CEC_CLK_REG);
++ val |= BIT(24);
++ writel(val, reg + SUN50I_H616_HDMI_CEC_CLK_REG);
++
++ i = sunxi_ccu_probe(node, reg, &sun50i_h616_ccu_desc);
++ if (i)
++ pr_err("%pOF: probing clocks fails: %d\n", node, i);
++}
++
++CLK_OF_DECLARE(sun50i_h616_ccu, "allwinner,sun50i-h616-ccu",
++ sun50i_h616_ccu_setup);
+diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.h b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h
+new file mode 100644
+index 0000000000000..dd671b413f224
+--- /dev/null
++++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h
+@@ -0,0 +1,56 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Copyright 2020 Arm Ltd.
++ */
++
++#ifndef _CCU_SUN50I_H616_H_
++#define _CCU_SUN50I_H616_H_
++
++#include <dt-bindings/clock/sun50i-h616-ccu.h>
++#include <dt-bindings/reset/sun50i-h616-ccu.h>
++
++#define CLK_OSC12M 0
++#define CLK_PLL_CPUX 1
++#define CLK_PLL_DDR0 2
++#define CLK_PLL_DDR1 3
++
++/* PLL_PERIPH0 exported for PRCM */
++
++#define CLK_PLL_PERIPH0_2X 5
++#define CLK_PLL_PERIPH1 6
++#define CLK_PLL_PERIPH1_2X 7
++#define CLK_PLL_GPU 8
++#define CLK_PLL_VIDEO0 9
++#define CLK_PLL_VIDEO0_4X 10
++#define CLK_PLL_VIDEO1 11
++#define CLK_PLL_VIDEO1_4X 12
++#define CLK_PLL_VIDEO2 13
++#define CLK_PLL_VIDEO2_4X 14
++#define CLK_PLL_VE 15
++#define CLK_PLL_DE 16
++#define CLK_PLL_AUDIO_HS 17
++#define CLK_PLL_AUDIO_1X 18
++#define CLK_PLL_AUDIO_2X 19
++#define CLK_PLL_AUDIO_4X 20
++
++/* CPUX clock exported for DVFS */
++
++#define CLK_AXI 22
++#define CLK_CPUX_APB 23
++#define CLK_PSI_AHB1_AHB2 24
++#define CLK_AHB3 25
++
++/* APB1 clock exported for PIO */
++
++#define CLK_APB2 27
++#define CLK_MBUS 28
++
++/* All module clocks and bus gates are exported except DRAM */
++
++#define CLK_DRAM 49
++
++#define CLK_BUS_DRAM 56
++
++#define CLK_NUMBER (CLK_BUS_HDCP + 1)
++
++#endif /* _CCU_SUN50I_H616_H_ */
+diff --git a/include/dt-bindings/clock/sun50i-h616-ccu.h b/include/dt-bindings/clock/sun50i-h616-ccu.h
+new file mode 100644
+index 0000000000000..4fc08b0df2f3c
+--- /dev/null
++++ b/include/dt-bindings/clock/sun50i-h616-ccu.h
+@@ -0,0 +1,115 @@
++/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
++/*
++ * Copyright (C) 2020 Arm Ltd.
++ */
++
++#ifndef _DT_BINDINGS_CLK_SUN50I_H616_H_
++#define _DT_BINDINGS_CLK_SUN50I_H616_H_
++
++#define CLK_PLL_PERIPH0 4
++
++#define CLK_CPUX 21
++
++#define CLK_APB1 26
++
++#define CLK_DE 29
++#define CLK_BUS_DE 30
++#define CLK_DEINTERLACE 31
++#define CLK_BUS_DEINTERLACE 32
++#define CLK_G2D 33
++#define CLK_BUS_G2D 34
++#define CLK_GPU0 35
++#define CLK_BUS_GPU 36
++#define CLK_GPU1 37
++#define CLK_CE 38
++#define CLK_BUS_CE 39
++#define CLK_VE 40
++#define CLK_BUS_VE 41
++#define CLK_BUS_DMA 42
++#define CLK_BUS_HSTIMER 43
++#define CLK_AVS 44
++#define CLK_BUS_DBG 45
++#define CLK_BUS_PSI 46
++#define CLK_BUS_PWM 47
++#define CLK_BUS_IOMMU 48
++
++#define CLK_MBUS_DMA 50
++#define CLK_MBUS_VE 51
++#define CLK_MBUS_CE 52
++#define CLK_MBUS_TS 53
++#define CLK_MBUS_NAND 54
++#define CLK_MBUS_G2D 55
++
++#define CLK_NAND0 57
++#define CLK_NAND1 58
++#define CLK_BUS_NAND 59
++#define CLK_MMC0 60
++#define CLK_MMC1 61
++#define CLK_MMC2 62
++#define CLK_BUS_MMC0 63
++#define CLK_BUS_MMC1 64
++#define CLK_BUS_MMC2 65
++#define CLK_BUS_UART0 66
++#define CLK_BUS_UART1 67
++#define CLK_BUS_UART2 68
++#define CLK_BUS_UART3 69
++#define CLK_BUS_UART4 70
++#define CLK_BUS_UART5 71
++#define CLK_BUS_I2C0 72
++#define CLK_BUS_I2C1 73
++#define CLK_BUS_I2C2 74
++#define CLK_BUS_I2C3 75
++#define CLK_BUS_I2C4 76
++#define CLK_SPI0 77
++#define CLK_SPI1 78
++#define CLK_BUS_SPI0 79
++#define CLK_BUS_SPI1 80
++#define CLK_EMAC_25M 81
++#define CLK_BUS_EMAC0 82
++#define CLK_BUS_EMAC1 83
++#define CLK_TS 84
++#define CLK_BUS_TS 85
++#define CLK_BUS_THS 86
++#define CLK_SPDIF 87
++#define CLK_BUS_SPDIF 88
++#define CLK_DMIC 89
++#define CLK_BUS_DMIC 90
++#define CLK_AUDIO_CODEC_1X 91
++#define CLK_AUDIO_CODEC_4X 92
++#define CLK_BUS_AUDIO_CODEC 93
++#define CLK_AUDIO_HUB 94
++#define CLK_BUS_AUDIO_HUB 95
++#define CLK_USB_OHCI0 96
++#define CLK_USB_PHY0 97
++#define CLK_USB_OHCI1 98
++#define CLK_USB_PHY1 99
++#define CLK_USB_OHCI2 100
++#define CLK_USB_PHY2 101
++#define CLK_USB_OHCI3 102
++#define CLK_USB_PHY3 103
++#define CLK_BUS_OHCI0 104
++#define CLK_BUS_OHCI1 105
++#define CLK_BUS_OHCI2 106
++#define CLK_BUS_OHCI3 107
++#define CLK_BUS_EHCI0 108
++#define CLK_BUS_EHCI1 109
++#define CLK_BUS_EHCI2 110
++#define CLK_BUS_EHCI3 111
++#define CLK_BUS_OTG 112
++#define CLK_BUS_KEYADC 113
++#define CLK_HDMI 114
++#define CLK_HDMI_SLOW 115
++#define CLK_HDMI_CEC 116
++#define CLK_BUS_HDMI 117
++#define CLK_BUS_TCON_TOP 118
++#define CLK_TCON_TV0 119
++#define CLK_TCON_TV1 120
++#define CLK_BUS_TCON_TV0 121
++#define CLK_BUS_TCON_TV1 122
++#define CLK_TVE0 123
++#define CLK_BUS_TVE_TOP 124
++#define CLK_BUS_TVE0 125
++#define CLK_HDCP 126
++#define CLK_BUS_HDCP 127
++
++#endif /* _DT_BINDINGS_CLK_SUN50I_H616_H_ */
+diff --git a/include/dt-bindings/reset/sun50i-h616-ccu.h b/include/dt-bindings/reset/sun50i-h616-ccu.h
+new file mode 100644
+index 0000000000000..cb6285a8d1285
+--- /dev/null
++++ b/include/dt-bindings/reset/sun50i-h616-ccu.h
+@@ -0,0 +1,70 @@
++/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
++/*
++ * Copyright (C) 2020 Arm Ltd.
++ */
++
++#ifndef _DT_BINDINGS_RESET_SUN50I_H616_H_
++#define _DT_BINDINGS_RESET_SUN50I_H616_H_
++
++#define RST_MBUS 0
++#define RST_BUS_DE 1
++#define RST_BUS_DEINTERLACE 2
++#define RST_BUS_GPU 3
++#define RST_BUS_CE 4
++#define RST_BUS_VE 5
++#define RST_BUS_DMA 6
++#define RST_BUS_HSTIMER 7
++#define RST_BUS_DBG 8
++#define RST_BUS_PSI 9
++#define RST_BUS_PWM 10
++#define RST_BUS_IOMMU 11
++#define RST_BUS_DRAM 12
++#define RST_BUS_NAND 13
++#define RST_BUS_MMC0 14
++#define RST_BUS_MMC1 15
++#define RST_BUS_MMC2 16
++#define RST_BUS_UART0 17
++#define RST_BUS_UART1 18
++#define RST_BUS_UART2 19
++#define RST_BUS_UART3 20
++#define RST_BUS_UART4 21
++#define RST_BUS_UART5 22
++#define RST_BUS_I2C0 23
++#define RST_BUS_I2C1 24
++#define RST_BUS_I2C2 25
++#define RST_BUS_I2C3 26
++#define RST_BUS_I2C4 27
++#define RST_BUS_SPI0 28
++#define RST_BUS_SPI1 29
++#define RST_BUS_EMAC0 30
++#define RST_BUS_EMAC1 31
++#define RST_BUS_TS 32
++#define RST_BUS_THS 33
++#define RST_BUS_SPDIF 34
++#define RST_BUS_DMIC 35
++#define RST_BUS_AUDIO_CODEC 36
++#define RST_BUS_AUDIO_HUB 37
++#define RST_USB_PHY0 38
++#define RST_USB_PHY1 39
++#define RST_USB_PHY2 40
++#define RST_USB_PHY3 41
++#define RST_BUS_OHCI0 42
++#define RST_BUS_OHCI1 43
++#define RST_BUS_OHCI2 44
++#define RST_BUS_OHCI3 45
++#define RST_BUS_EHCI0 46
++#define RST_BUS_EHCI1 47
++#define RST_BUS_EHCI2 48
++#define RST_BUS_EHCI3 49
++#define RST_BUS_OTG 50
++#define RST_BUS_HDMI 51
++#define RST_BUS_HDMI_SUB 52
++#define RST_BUS_TCON_TOP 53
++#define RST_BUS_TCON_TV0 54
++#define RST_BUS_TCON_TV1 55
++#define RST_BUS_TVE_TOP 56
++#define RST_BUS_TVE0 57
++#define RST_BUS_HDCP 58
++#define RST_BUS_KEYADC 59
++
++#endif /* _DT_BINDINGS_RESET_SUN50I_H616_H_ */
+--
+2.43.0
+
diff --git a/queue-5.10/clk-sunxi-ng-h6-reparent-cpux-during-pll-cpux-rate-c.patch b/queue-5.10/clk-sunxi-ng-h6-reparent-cpux-during-pll-cpux-rate-c.patch
new file mode 100644
index 0000000000..134ecbe5af
--- /dev/null
+++ b/queue-5.10/clk-sunxi-ng-h6-reparent-cpux-during-pll-cpux-rate-c.patch
@@ -0,0 +1,73 @@
+From 41ef4ccd6a352a5527659e2f7936459da63fc4ba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Oct 2023 20:17:12 +0200
+Subject: clk: sunxi-ng: h6: Reparent CPUX during PLL CPUX rate change
+
+From: Jernej Skrabec <jernej.skrabec@gmail.com>
+
+[ Upstream commit 7e91ed763dc07437777bd012af7a2bd4493731ff ]
+
+While PLL CPUX clock rate change when CPU is running from it works in
+vast majority of cases, now and then it causes instability. This leads
+to system crashes and other undefined behaviour. After a lot of testing
+(30+ hours) while also doing a lot of frequency switches, we can't
+observe any instability issues anymore when doing reparenting to stable
+clock like 24 MHz oscillator.
+
+Fixes: 524353ea480b ("clk: sunxi-ng: add support for the Allwinner H6 CCU")
+Reported-by: Chad Wagner <wagnerch42@gmail.com>
+Link: https://forum.libreelec.tv/thread/27295-orange-pi-3-lts-freezes/
+Tested-by: Chad Wagner <wagnerch42@gmail.com>
+Reviewed-by: Chen-Yu Tsai <wens@csie.org>
+Link: https://lore.kernel.org/r/20231013181712.2128037-1-jernej.skrabec@gmail.com
+Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 19 +++++++++++++++++--
+ 1 file changed, 17 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
+index c0800da2fa3d7..736a781e4007a 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
++++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
+@@ -1181,12 +1181,19 @@ static const u32 usb2_clk_regs[] = {
+ SUN50I_H6_USB3_CLK_REG,
+ };
+
++static struct ccu_mux_nb sun50i_h6_cpu_nb = {
++ .common = &cpux_clk.common,
++ .cm = &cpux_clk.mux,
++ .delay_us = 1,
++ .bypass_index = 0, /* index of 24 MHz oscillator */
++};
++
+ static int sun50i_h6_ccu_probe(struct platform_device *pdev)
+ {
+ struct resource *res;
+ void __iomem *reg;
++ int i, ret;
+ u32 val;
+- int i;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ reg = devm_ioremap_resource(&pdev->dev, res);
+@@ -1240,7 +1247,15 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev)
+ val |= BIT(24);
+ writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG);
+
+- return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc);
++ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc);
++ if (ret)
++ return ret;
++
++ /* Reparent CPU during PLL CPUX rate changes */
++ ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk,
++ &sun50i_h6_cpu_nb);
++
++ return 0;
+ }
+
+ static const struct of_device_id sun50i_h6_ccu_ids[] = {
+--
+2.43.0
+
diff --git a/queue-5.10/clk-sunxi-ng-unregister-clocks-resets-when-unbinding.patch b/queue-5.10/clk-sunxi-ng-unregister-clocks-resets-when-unbinding.patch
new file mode 100644
index 0000000000..fca0d431f1
--- /dev/null
+++ b/queue-5.10/clk-sunxi-ng-unregister-clocks-resets-when-unbinding.patch
@@ -0,0 +1,497 @@
+From a0849685cfc81ddf8d37cc034cabebd0741cead2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 1 Sep 2021 00:05:19 -0500
+Subject: clk: sunxi-ng: Unregister clocks/resets when unbinding
+
+From: Samuel Holland <samuel@sholland.org>
+
+[ Upstream commit 9bec2b9c6134052994115d2d3374e96f2ccb9b9d ]
+
+Currently, unbinding a CCU driver unmaps the device's MMIO region, while
+leaving its clocks/resets and their providers registered. This can cause
+a page fault later when some clock operation tries to perform MMIO. Fix
+this by separating the CCU initialization from the memory allocation,
+and then using a devres callback to unregister the clocks and resets.
+
+This also fixes a memory leak of the `struct ccu_reset`, and uses the
+correct owner (the specific platform driver) for the clocks and resets.
+
+Early OF clock providers are never unregistered, and limited error
+handling is possible, so they are mostly unchanged. The error reporting
+is made more consistent by moving the message inside of_sunxi_ccu_probe.
+
+Signed-off-by: Samuel Holland <samuel@sholland.org>
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+Link: https://lore.kernel.org/r/20210901050526.45673-2-samuel@sholland.org
+Stable-dep-of: 7e91ed763dc0 ("clk: sunxi-ng: h6: Reparent CPUX during PLL CPUX rate change")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/sunxi-ng/ccu-sun4i-a10.c | 2 +-
+ drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c | 2 +-
+ drivers/clk/sunxi-ng/ccu-sun50i-a100.c | 2 +-
+ drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 2 +-
+ drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c | 2 +-
+ drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 2 +-
+ drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 4 +-
+ drivers/clk/sunxi-ng/ccu-sun5i.c | 2 +-
+ drivers/clk/sunxi-ng/ccu-sun6i-a31.c | 2 +-
+ drivers/clk/sunxi-ng/ccu-sun8i-a23.c | 2 +-
+ drivers/clk/sunxi-ng/ccu-sun8i-a33.c | 2 +-
+ drivers/clk/sunxi-ng/ccu-sun8i-a83t.c | 2 +-
+ drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 2 +-
+ drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 2 +-
+ drivers/clk/sunxi-ng/ccu-sun8i-r.c | 2 +-
+ drivers/clk/sunxi-ng/ccu-sun8i-r40.c | 2 +-
+ drivers/clk/sunxi-ng/ccu-sun8i-v3s.c | 2 +-
+ drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c | 3 +-
+ drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c | 3 +-
+ drivers/clk/sunxi-ng/ccu-sun9i-a80.c | 2 +-
+ drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c | 2 +-
+ drivers/clk/sunxi-ng/ccu_common.c | 89 ++++++++++++++++++++----
+ drivers/clk/sunxi-ng/ccu_common.h | 6 +-
+ 23 files changed, 100 insertions(+), 41 deletions(-)
+
+diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c
+index f32366d9336e7..bd9a8782fec3d 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c
++++ b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c
+@@ -1464,7 +1464,7 @@ static void __init sun4i_ccu_init(struct device_node *node,
+ val &= ~GENMASK(7, 6);
+ writel(val | (2 << 6), reg + SUN4I_AHB_REG);
+
+- sunxi_ccu_probe(node, reg, desc);
++ of_sunxi_ccu_probe(node, reg, desc);
+ }
+
+ static void __init sun4i_a10_ccu_setup(struct device_node *node)
+diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c
+index a56142b909938..6f2a589705561 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c
++++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c
+@@ -196,7 +196,7 @@ static int sun50i_a100_r_ccu_probe(struct platform_device *pdev)
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+- return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a100_r_ccu_desc);
++ return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a100_r_ccu_desc);
+ }
+
+ static const struct of_device_id sun50i_a100_r_ccu_ids[] = {
+diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c
+index 81b48c73d389f..913bb08e6dee8 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c
++++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c
+@@ -1247,7 +1247,7 @@ static int sun50i_a100_ccu_probe(struct platform_device *pdev)
+ writel(val, reg + sun50i_a100_usb2_clk_regs[i]);
+ }
+
+- ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a100_ccu_desc);
++ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a100_ccu_desc);
+ if (ret)
+ return ret;
+
+diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+index 149cfde817cba..54f25c624f020 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
++++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+@@ -955,7 +955,7 @@ static int sun50i_a64_ccu_probe(struct platform_device *pdev)
+
+ writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG);
+
+- ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a64_ccu_desc);
++ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_a64_ccu_desc);
+ if (ret)
+ return ret;
+
+diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
+index 50f8d1bc70465..aee096c6be195 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
++++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
+@@ -186,7 +186,7 @@ static void __init sunxi_r_ccu_init(struct device_node *node,
+ return;
+ }
+
+- sunxi_ccu_probe(node, reg, desc);
++ of_sunxi_ccu_probe(node, reg, desc);
+ }
+
+ static void __init sun50i_h6_r_ccu_setup(struct device_node *node)
+diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
+index bff446b782907..c0800da2fa3d7 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
++++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
+@@ -1240,7 +1240,7 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev)
+ val |= BIT(24);
+ writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG);
+
+- return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_h6_ccu_desc);
++ return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc);
+ }
+
+ static const struct of_device_id sun50i_h6_ccu_ids[] = {
+diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
+index 225307305880e..22eb18079a154 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
++++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
+@@ -1141,9 +1141,7 @@ static void __init sun50i_h616_ccu_setup(struct device_node *node)
+ val |= BIT(24);
+ writel(val, reg + SUN50I_H616_HDMI_CEC_CLK_REG);
+
+- i = sunxi_ccu_probe(node, reg, &sun50i_h616_ccu_desc);
+- if (i)
+- pr_err("%pOF: probing clocks fails: %d\n", node, i);
++ of_sunxi_ccu_probe(node, reg, &sun50i_h616_ccu_desc);
+ }
+
+ CLK_OF_DECLARE(sun50i_h616_ccu, "allwinner,sun50i-h616-ccu",
+diff --git a/drivers/clk/sunxi-ng/ccu-sun5i.c b/drivers/clk/sunxi-ng/ccu-sun5i.c
+index b78e9b507c1c6..1f4bc0e773a7e 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun5i.c
++++ b/drivers/clk/sunxi-ng/ccu-sun5i.c
+@@ -1012,7 +1012,7 @@ static void __init sun5i_ccu_init(struct device_node *node,
+ val &= ~GENMASK(7, 6);
+ writel(val | (2 << 6), reg + SUN5I_AHB_REG);
+
+- sunxi_ccu_probe(node, reg, desc);
++ of_sunxi_ccu_probe(node, reg, desc);
+ }
+
+ static void __init sun5i_a10s_ccu_setup(struct device_node *node)
+diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c
+index 9b40d53266a3f..3df5c0b415804 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c
++++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c
+@@ -1257,7 +1257,7 @@ static void __init sun6i_a31_ccu_setup(struct device_node *node)
+ val |= 0x3 << 12;
+ writel(val, reg + SUN6I_A31_AHB1_REG);
+
+- sunxi_ccu_probe(node, reg, &sun6i_a31_ccu_desc);
++ of_sunxi_ccu_probe(node, reg, &sun6i_a31_ccu_desc);
+
+ ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk,
+ &sun6i_a31_cpu_nb);
+diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c
+index 103aa504f6c8a..577bb235d6584 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c
++++ b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c
+@@ -745,7 +745,7 @@ static void __init sun8i_a23_ccu_setup(struct device_node *node)
+ val &= ~BIT(16);
+ writel(val, reg + SUN8I_A23_PLL_MIPI_REG);
+
+- sunxi_ccu_probe(node, reg, &sun8i_a23_ccu_desc);
++ of_sunxi_ccu_probe(node, reg, &sun8i_a23_ccu_desc);
+ }
+ CLK_OF_DECLARE(sun8i_a23_ccu, "allwinner,sun8i-a23-ccu",
+ sun8i_a23_ccu_setup);
+diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
+index 91838cd110377..8f65cd03f5acc 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
++++ b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
+@@ -805,7 +805,7 @@ static void __init sun8i_a33_ccu_setup(struct device_node *node)
+ val &= ~BIT(16);
+ writel(val, reg + SUN8I_A33_PLL_MIPI_REG);
+
+- sunxi_ccu_probe(node, reg, &sun8i_a33_ccu_desc);
++ of_sunxi_ccu_probe(node, reg, &sun8i_a33_ccu_desc);
+
+ /* Gate then ungate PLL CPU after any rate changes */
+ ccu_pll_notifier_register(&sun8i_a33_pll_cpu_nb);
+diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
+index 2b434521c5ccf..c2ddcd2ddab4e 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
++++ b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
+@@ -906,7 +906,7 @@ static int sun8i_a83t_ccu_probe(struct platform_device *pdev)
+ sun8i_a83t_cpu_pll_fixup(reg + SUN8I_A83T_PLL_C0CPUX_REG);
+ sun8i_a83t_cpu_pll_fixup(reg + SUN8I_A83T_PLL_C1CPUX_REG);
+
+- return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun8i_a83t_ccu_desc);
++ return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_a83t_ccu_desc);
+ }
+
+ static const struct of_device_id sun8i_a83t_ccu_ids[] = {
+diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
+index 524f33275bc73..4b94b6041b271 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
++++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
+@@ -342,7 +342,7 @@ static int sunxi_de2_clk_probe(struct platform_device *pdev)
+ goto err_disable_mod_clk;
+ }
+
+- ret = sunxi_ccu_probe(pdev->dev.of_node, reg, ccu_desc);
++ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, ccu_desc);
+ if (ret)
+ goto err_assert_reset;
+
+diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
+index 7e629a4493afd..d2fc2903787d8 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
++++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
+@@ -1154,7 +1154,7 @@ static void __init sunxi_h3_h5_ccu_init(struct device_node *node,
+ val &= ~GENMASK(19, 16);
+ writel(val | (0 << 16), reg + SUN8I_H3_PLL_AUDIO_REG);
+
+- sunxi_ccu_probe(node, reg, desc);
++ of_sunxi_ccu_probe(node, reg, desc);
+
+ /* Gate then ungate PLL CPU after any rate changes */
+ ccu_pll_notifier_register(&sun8i_h3_pll_cpu_nb);
+diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r.c b/drivers/clk/sunxi-ng/ccu-sun8i-r.c
+index 4c8c491b87c27..9e754d1f754a1 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun8i-r.c
++++ b/drivers/clk/sunxi-ng/ccu-sun8i-r.c
+@@ -265,7 +265,7 @@ static void __init sunxi_r_ccu_init(struct device_node *node,
+ return;
+ }
+
+- sunxi_ccu_probe(node, reg, desc);
++ of_sunxi_ccu_probe(node, reg, desc);
+ }
+
+ static void __init sun8i_a83t_r_ccu_setup(struct device_node *node)
+diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
+index 84153418453f4..002e0c3a04dbe 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
++++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
+@@ -1346,7 +1346,7 @@ static int sun8i_r40_ccu_probe(struct platform_device *pdev)
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+- ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun8i_r40_ccu_desc);
++ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_r40_ccu_desc);
+ if (ret)
+ return ret;
+
+diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
+index 0e36ca3bf3d52..8f27b2203726d 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
++++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
+@@ -811,7 +811,7 @@ static void __init sun8i_v3_v3s_ccu_init(struct device_node *node,
+ val &= ~GENMASK(19, 16);
+ writel(val | (3 << 16), reg + SUN8I_V3S_PLL_AUDIO_REG);
+
+- sunxi_ccu_probe(node, reg, ccu_desc);
++ of_sunxi_ccu_probe(node, reg, ccu_desc);
+ }
+
+ static void __init sun8i_v3s_ccu_setup(struct device_node *node)
+diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c
+index 6616e8114f623..261e64416f26a 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c
++++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c
+@@ -246,8 +246,7 @@ static int sun9i_a80_de_clk_probe(struct platform_device *pdev)
+ goto err_disable_clk;
+ }
+
+- ret = sunxi_ccu_probe(pdev->dev.of_node, reg,
+- &sun9i_a80_de_clk_desc);
++ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_de_clk_desc);
+ if (ret)
+ goto err_assert_reset;
+
+diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c
+index 4b4a507d04edf..596243b3e0fa3 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c
++++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c
+@@ -117,8 +117,7 @@ static int sun9i_a80_usb_clk_probe(struct platform_device *pdev)
+ return ret;
+ }
+
+- ret = sunxi_ccu_probe(pdev->dev.of_node, reg,
+- &sun9i_a80_usb_clk_desc);
++ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_usb_clk_desc);
+ if (ret)
+ goto err_disable_clk;
+
+diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c
+index ef29582676f6e..97aaed0e68500 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c
++++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c
+@@ -1231,7 +1231,7 @@ static int sun9i_a80_ccu_probe(struct platform_device *pdev)
+ sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C0CPUX_REG);
+ sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C1CPUX_REG);
+
+- return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun9i_a80_ccu_desc);
++ return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_ccu_desc);
+ }
+
+ static const struct of_device_id sun9i_a80_ccu_ids[] = {
+diff --git a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c
+index 7ecc3a5a5b5e1..61ad7ee91c114 100644
+--- a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c
++++ b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c
+@@ -538,7 +538,7 @@ static void __init suniv_f1c100s_ccu_setup(struct device_node *node)
+ val &= ~GENMASK(19, 16);
+ writel(val | (3 << 16), reg + SUNIV_PLL_AUDIO_REG);
+
+- sunxi_ccu_probe(node, reg, &suniv_ccu_desc);
++ of_sunxi_ccu_probe(node, reg, &suniv_ccu_desc);
+
+ /* Gate then ungate PLL CPU after any rate changes */
+ ccu_pll_notifier_register(&suniv_pll_cpu_nb);
+diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c
+index 2e20e650b6c01..88cb569e58358 100644
+--- a/drivers/clk/sunxi-ng/ccu_common.c
++++ b/drivers/clk/sunxi-ng/ccu_common.c
+@@ -7,6 +7,7 @@
+
+ #include <linux/clk.h>
+ #include <linux/clk-provider.h>
++#include <linux/device.h>
+ #include <linux/iopoll.h>
+ #include <linux/slab.h>
+
+@@ -14,6 +15,11 @@
+ #include "ccu_gate.h"
+ #include "ccu_reset.h"
+
++struct sunxi_ccu {
++ const struct sunxi_ccu_desc *desc;
++ struct ccu_reset reset;
++};
++
+ static DEFINE_SPINLOCK(ccu_lock);
+
+ void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock)
+@@ -79,12 +85,15 @@ int ccu_pll_notifier_register(struct ccu_pll_nb *pll_nb)
+ &pll_nb->clk_nb);
+ }
+
+-int sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
+- const struct sunxi_ccu_desc *desc)
++static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev,
++ struct device_node *node, void __iomem *reg,
++ const struct sunxi_ccu_desc *desc)
+ {
+ struct ccu_reset *reset;
+ int i, ret;
+
++ ccu->desc = desc;
++
+ for (i = 0; i < desc->num_ccu_clks; i++) {
+ struct ccu_common *cclk = desc->ccu_clks[i];
+
+@@ -103,7 +112,10 @@ int sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
+ continue;
+
+ name = hw->init->name;
+- ret = of_clk_hw_register(node, hw);
++ if (dev)
++ ret = clk_hw_register(dev, hw);
++ else
++ ret = of_clk_hw_register(node, hw);
+ if (ret) {
+ pr_err("Couldn't register clock %d - %s\n", i, name);
+ goto err_clk_unreg;
+@@ -115,15 +127,10 @@ int sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
+ if (ret)
+ goto err_clk_unreg;
+
+- reset = kzalloc(sizeof(*reset), GFP_KERNEL);
+- if (!reset) {
+- ret = -ENOMEM;
+- goto err_alloc_reset;
+- }
+-
++ reset = &ccu->reset;
+ reset->rcdev.of_node = node;
+ reset->rcdev.ops = &ccu_reset_ops;
+- reset->rcdev.owner = THIS_MODULE;
++ reset->rcdev.owner = dev ? dev->driver->owner : THIS_MODULE;
+ reset->rcdev.nr_resets = desc->num_resets;
+ reset->base = reg;
+ reset->lock = &ccu_lock;
+@@ -131,13 +138,11 @@ int sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
+
+ ret = reset_controller_register(&reset->rcdev);
+ if (ret)
+- goto err_of_clk_unreg;
++ goto err_del_provider;
+
+ return 0;
+
+-err_of_clk_unreg:
+- kfree(reset);
+-err_alloc_reset:
++err_del_provider:
+ of_clk_del_provider(node);
+ err_clk_unreg:
+ while (--i >= 0) {
+@@ -149,3 +154,59 @@ int sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
+ }
+ return ret;
+ }
++
++static void devm_sunxi_ccu_release(struct device *dev, void *res)
++{
++ struct sunxi_ccu *ccu = res;
++ const struct sunxi_ccu_desc *desc = ccu->desc;
++ int i;
++
++ reset_controller_unregister(&ccu->reset.rcdev);
++ of_clk_del_provider(dev->of_node);
++
++ for (i = 0; i < desc->hw_clks->num; i++) {
++ struct clk_hw *hw = desc->hw_clks->hws[i];
++
++ if (!hw)
++ continue;
++ clk_hw_unregister(hw);
++ }
++}
++
++int devm_sunxi_ccu_probe(struct device *dev, void __iomem *reg,
++ const struct sunxi_ccu_desc *desc)
++{
++ struct sunxi_ccu *ccu;
++ int ret;
++
++ ccu = devres_alloc(devm_sunxi_ccu_release, sizeof(*ccu), GFP_KERNEL);
++ if (!ccu)
++ return -ENOMEM;
++
++ ret = sunxi_ccu_probe(ccu, dev, dev->of_node, reg, desc);
++ if (ret) {
++ devres_free(ccu);
++ return ret;
++ }
++
++ devres_add(dev, ccu);
++
++ return 0;
++}
++
++void of_sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
++ const struct sunxi_ccu_desc *desc)
++{
++ struct sunxi_ccu *ccu;
++ int ret;
++
++ ccu = kzalloc(sizeof(*ccu), GFP_KERNEL);
++ if (!ccu)
++ return;
++
++ ret = sunxi_ccu_probe(ccu, NULL, node, reg, desc);
++ if (ret) {
++ pr_err("%pOF: probing clocks failed: %d\n", node, ret);
++ kfree(ccu);
++ }
++}
+diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
+index 04e7a12200a21..98a1834b58bb4 100644
+--- a/drivers/clk/sunxi-ng/ccu_common.h
++++ b/drivers/clk/sunxi-ng/ccu_common.h
+@@ -63,7 +63,9 @@ struct ccu_pll_nb {
+
+ int ccu_pll_notifier_register(struct ccu_pll_nb *pll_nb);
+
+-int sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
+- const struct sunxi_ccu_desc *desc);
++int devm_sunxi_ccu_probe(struct device *dev, void __iomem *reg,
++ const struct sunxi_ccu_desc *desc);
++void of_sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
++ const struct sunxi_ccu_desc *desc);
+
+ #endif /* _COMMON_H_ */
+--
+2.43.0
+
diff --git a/queue-5.10/series b/queue-5.10/series
index e90cf119f8..9f4654c0d5 100644
--- a/queue-5.10/series
+++ b/queue-5.10/series
@@ -38,3 +38,6 @@ net-bridge-fix-multicast-to-unicast-with-fraglist-gs.patch
net-core-reject-skb_copy-_expand-for-fraglist-gso-sk.patch
tipc-fix-a-possible-memleak-in-tipc_buf_append.patch
net-gro-add-flush-check-in-udp_gro_receive_segment.patch
+clk-sunxi-ng-add-support-for-the-allwinner-h616-ccu.patch
+clk-sunxi-ng-unregister-clocks-resets-when-unbinding.patch
+clk-sunxi-ng-h6-reparent-cpux-during-pll-cpux-rate-c.patch