* Re: (subset) [PATCH 0/8] arm64: Implement support for 2025 dpISA extensions
From: Catalin Marinas @ 2026-04-09 18:39 UTC (permalink / raw)
To: Will Deacon, Jonathan Corbet, Shuah Khan, Mark Brown
Cc: linux-arm-kernel, linux-kernel, linux-doc, linux-kselftest
In-Reply-To: <177575970227.3883927.939712260390088306.b4-ty@arm.com>
On Thu, Apr 09, 2026 at 07:35:02PM +0100, Catalin Marinas wrote:
> On Mon, 02 Mar 2026 22:53:15 +0000, Mark Brown wrote:
> > The 2025 dpISA extensions introduce a number of architecture features
> > all of which are fairly straightforward from a kernel point of view
> > since they only introduce new instructions, not any architecture state.
> >
> > All the relevant newly added ID registers are already exported by KVM,
> > all non-RES0 bits in ID_AA64ZFR0_EL1 and ID_AA64FPFR0_EL1 are writable
> > and the updates to ID_AA64ISARx_EL1 are all additional values in already
> > exported bitfields.
> >
> > [...]
>
> Applied to arm64 (for-next/sysreg), thanks! That's only the sysreg
> definitions as these are stable. I also applied the KERNEL_HWCAP_*
> generation on a different branch.
>
> [2/8] arm64/sysreg: Update ID_AA64ISAR0_EL1 description to DDI0601 2025-12
> https://git.kernel.org/arm64/c/b964aa8d68f7
> [3/8] arm64/sysreg: Update ID_AA64ISAR2_EL1 description to DDI0601 2025-12
> https://git.kernel.org/arm64/c/bb5e1e540501
> [4/8] arm64/sysreg: Update ID_AA64FPFR0_EL1 description to DDI0601 2025-12
> https://git.kernel.org/arm64/c/d74576b51ba6
> [5/8] arm64/sysreg: Update ID_AA64ZFR0_EL1 description to DDI0601 2025-12
> https://git.kernel.org/arm64/c/bf56250f34a4
> [6/8] arm64/sysreg: Update ID_AA64SMFR0_EL1 description to DDI0601 2025-12
> https://git.kernel.org/arm64/c/306736fd5155
b4 ty got confused with two emails for the same series, so only one went
out. The first patch is on for-next/misc:
[1/8] arm64/hwcap: Generate the KERNEL_HWCAP_ definitions for the hwcaps
https://git.kernel.org/arm64/c/abed23c3c44f
--
Catalin
^ permalink raw reply
* Re: (subset) [PATCH 0/8] arm64: Implement support for 2025 dpISA extensions
From: Catalin Marinas @ 2026-04-09 18:35 UTC (permalink / raw)
To: Will Deacon, Jonathan Corbet, Shuah Khan, Mark Brown
Cc: linux-arm-kernel, linux-kernel, linux-doc, linux-kselftest
In-Reply-To: <20260302-arm64-dpisa-2025-v1-0-0855e7f41689@kernel.org>
On Mon, 02 Mar 2026 22:53:15 +0000, Mark Brown wrote:
> The 2025 dpISA extensions introduce a number of architecture features
> all of which are fairly straightforward from a kernel point of view
> since they only introduce new instructions, not any architecture state.
>
> All the relevant newly added ID registers are already exported by KVM,
> all non-RES0 bits in ID_AA64ZFR0_EL1 and ID_AA64FPFR0_EL1 are writable
> and the updates to ID_AA64ISARx_EL1 are all additional values in already
> exported bitfields.
>
> [...]
Applied to arm64 (for-next/sysreg), thanks! That's only the sysreg
definitions as these are stable. I also applied the KERNEL_HWCAP_*
generation on a different branch.
[2/8] arm64/sysreg: Update ID_AA64ISAR0_EL1 description to DDI0601 2025-12
https://git.kernel.org/arm64/c/b964aa8d68f7
[3/8] arm64/sysreg: Update ID_AA64ISAR2_EL1 description to DDI0601 2025-12
https://git.kernel.org/arm64/c/bb5e1e540501
[4/8] arm64/sysreg: Update ID_AA64FPFR0_EL1 description to DDI0601 2025-12
https://git.kernel.org/arm64/c/d74576b51ba6
[5/8] arm64/sysreg: Update ID_AA64ZFR0_EL1 description to DDI0601 2025-12
https://git.kernel.org/arm64/c/bf56250f34a4
[6/8] arm64/sysreg: Update ID_AA64SMFR0_EL1 description to DDI0601 2025-12
https://git.kernel.org/arm64/c/306736fd5155
^ permalink raw reply
* Re: [PATCH] arm64: mte: Skip TFSR_EL1 checks and barriers in synchronous tag check mode
From: Catalin Marinas @ 2026-04-09 18:34 UTC (permalink / raw)
To: Will Deacon, Matthew Wilcox (Oracle), Thomas Huth, Andrew Morton,
Lance Yang, Yeoreum Yun, David Hildenbrand, Muhammad Usama Anjum
Cc: linux-arm-kernel, linux-kernel
In-Reply-To: <20260311175054.3889093-1-usama.anjum@arm.com>
On Wed, 11 Mar 2026 17:50:50 +0000, Muhammad Usama Anjum wrote:
> In MTE synchronous mode, tag check faults are reported as immediate
> Data Abort exceptions. The TFSR_EL1.TF1 bit is never set, since faults
> never go through the asynchronous path. Therefore, reading TFSR_EL1
> and executing data and instruction barriers on kernel entry, exit,
> context switch, and suspend is unnecessary overhead in sync mode.
>
> The exit path (mte_check_tfsr_exit) and the assembly paths
> (check_mte_async_tcf / clear_mte_async_tcf in entry.S) already had this
> check. Extend the same optimization on kernel entry/exit, context
> switch and suspend.
>
> [...]
Applied to arm64 (for-next/misc), thanks!
[1/1] arm64: mte: Skip TFSR_EL1 checks and barriers in synchronous tag check mode
https://git.kernel.org/arm64/c/249bf9733198
^ permalink raw reply
* Re: [PATCH v2 1/3] arm64: mm: Fix rodata=full block mapping support for realm guests
From: Catalin Marinas @ 2026-04-09 18:33 UTC (permalink / raw)
To: Yang Shi
Cc: Kevin Brodsky, Ryan Roberts, Will Deacon, David Hildenbrand (Arm),
Dev Jain, Suzuki K Poulose, Jinjiang Tu, linux-arm-kernel,
linux-kernel, stable
In-Reply-To: <07054475-6b07-4b19-a393-cbe037adef8b@os.amperecomputing.com>
On Thu, Apr 09, 2026 at 09:48:58AM -0700, Yang Shi wrote:
> On 4/9/26 8:20 AM, Catalin Marinas wrote:
> > On Thu, Apr 09, 2026 at 11:53:41AM +0200, Kevin Brodsky wrote:
> > > What would make more sense to me is to enable the use of BBML2-noabort
> > > unconditionally if !force_pte_mapping(). We can then have
> > > can_set_direct_map() return true if we have BBML2-noabort, and we no
> > > longer need to check it in map_mem().
> >
> > Indeed.
>
> I'm trying to wrap up my head for this discussion. IIUC, if none of the
> features is enabled, it means we don't need do anything because the direct
> map is not changed. For example, if vmalloc doesn't change direct map
> permission when rodata != full, there is no need to call
> set_direct_map_*_noflush(). So unconditionally checking BBML2_NOABORT will
> change the behavior unnecessarily. Did I miss something?
>
> I think the only exception is secretmem if I don't miss something.
> Currently, secretmem is actually not supported if none of the features is
> enabled. But BBML2_NOABORT allows to lift the restriction.
Yes, it's secretmem only AFAICT. I think execmem will only change the
linear map if rodata_full anyway.
--
Catalin
^ permalink raw reply
* Re: [PATCH] KVM: arm64: Add KVM_CAP_ARM_NATIVE_CACHE_CONFIG vcpu capability
From: Marc Zyngier @ 2026-04-09 18:12 UTC (permalink / raw)
To: David Woodhouse
Cc: Gutierrez Cantu, Bernardo, alexandru.elisei, alyssa, asahi,
broonie, catalin.marinas, james.morse, kvmarm, linux-arm-kernel,
linux-kernel, marcan, mathieu.poirier, oliver.upton,
suzuki.poulose, sven, will
In-Reply-To: <584931abfa8c6f6c9c8a1379d26ef6beb58db1cd.camel@infradead.org>
On Thu, 09 Apr 2026 18:49:09 +0100,
David Woodhouse <dwmw2@infradead.org> wrote:
>
> [1 <text/plain; UTF-8 (quoted-printable)>]
> On Thu, 2026-04-09 at 18:07 +0100, Marc Zyngier wrote:
> > On Thu, 09 Apr 2026 16:29:06 +0100,
> > David Woodhouse <dwmw2@infradead.org> wrote:
> > >
> > > [1 <text/plain; UTF-8 (quoted-printable)>]
> > > From: David Woodhouse <dwmw@amazon.co.uk>
> > >
> > > Commit 7af0c2534f4c5 ("KVM: arm64: Normalize cache configuration")
> > > fabricates CLIDR_EL1 and CCSIDR_EL1 values instead of using the real
> > > hardware values. While this provides consistent values across
> > > heterogeneous CPUs, it does cause visible changes in the CPU model
> > > exposed to guests.
> > >
> > > The commit claims that userspace can restore the original values, but
> > > there is no way for userspace to obtain the real CLIDR_EL1 register
> > > value — it is not fully reconstructible from sysfs, which lacks the
> > > LoC, LoUU, and LoUIS fields.
> > >
> > > Add a per-vcpu KVM_CAP_ARM_NATIVE_CACHE_CONFIG capability that reads
> > > the real CLIDR_EL1 and all CCSIDR_EL1 values from the current physical
> > > CPU and sets them on the vcpu.
> > >
> > > This allows hypervisors to present the real hardware cache configuration
> > > to guests, which is important for consistency of the environment across
> > > kernel versions and for migration compatibility with hosts running
> > > older kernels that exposed the real values.
> > >
> > > Fixes: 7af0c2534f4c ("KVM: arm64: Normalize cache configuration")
> > > Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> > > ---
> > > Documentation/virt/kvm/api.rst | 23 ++++++++
> > > arch/arm64/include/asm/kvm_host.h | 1 +
> > > arch/arm64/kvm/arm.c | 17 ++++++
> > > arch/arm64/kvm/sys_regs.c | 26 ++++++++++
> > > include/uapi/linux/kvm.h | 1 +
> > > tools/testing/selftests/kvm/Makefile.kvm | 1 +
> > > .../selftests/kvm/arm64/native_cache_config.c | 52 +++++++++++++++++++
> > > 7 files changed, 121 insertions(+)
> > > create mode 100644 tools/testing/selftests/kvm/arm64/native_cache_config.c
> > >
> > > diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> > > index e3b3bd9edeec..ee47dc07ceac 100644
> > > --- a/Documentation/virt/kvm/api.rst
> > > +++ b/Documentation/virt/kvm/api.rst
> > > @@ -8930,6 +8930,29 @@ no-op.
> > >
> > > ``KVM_CHECK_EXTENSION`` returns the bitmask of exits that can be disabled.
> > >
> > > +7.48 KVM_CAP_ARM_NATIVE_CACHE_CONFIG
> > > +-------------------------------------
> > > +
> > > +:Architecture: arm64
> > > +:Target: vcpu
> > > +:Parameters: none
> > > +:Returns: 0 on success, -ENOMEM on allocation failure, -EINVAL if
> > > + args[0] or flags are non-zero.
> > > +
> > > +This per-vcpu capability reads the real CLIDR_EL1 and CCSIDR_EL1 values
> > > +from the physical CPU on which the ioctl is executed, and sets them on
> > > +the vcpu. This replaces the fabricated cache configuration that KVM
> > > +provides by default.
> > > +
> > > +The caller should ensure the vcpu thread is pinned to the desired
> > > +physical CPU before invoking this capability, so that the correct cache
> > > +topology is captured. On heterogeneous systems, different physical CPUs
> > > +may have different cache configurations.
> > > +
> > > +After this capability is enabled, the vcpu's CLIDR_EL1 and CCSIDR_EL1
> > > +values can still be overridden individually via ``KVM_SET_ONE_REG`` and
> > > +the ``KVM_REG_ARM_DEMUX`` interface.
> > > +
> > > 8. Other capabilities.
> > > ======================
> > >
> > > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> > > index a1bb025c641f..c9713a472c47 100644
> > > --- a/arch/arm64/include/asm/kvm_host.h
> > > +++ b/arch/arm64/include/asm/kvm_host.h
> > > @@ -1296,6 +1296,7 @@ void kvm_sys_regs_create_debugfs(struct kvm *kvm);
> > > void kvm_reset_sys_regs(struct kvm_vcpu *vcpu);
> > >
> > > int __init kvm_sys_reg_table_init(void);
> > > +int kvm_vcpu_set_native_cache_config(struct kvm_vcpu *vcpu);
> > > struct sys_reg_desc;
> > > int __init populate_sysreg_config(const struct sys_reg_desc *sr,
> > > unsigned int idx);
> > > diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> > > index 326a99fea753..579583e8dc5c 100644
> > > --- a/arch/arm64/kvm/arm.c
> > > +++ b/arch/arm64/kvm/arm.c
> > > @@ -393,6 +393,10 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
> > > case KVM_CAP_ARM_DISABLE_EXITS:
> > > r = KVM_ARM_DISABLE_VALID_EXITS;
> > > break;
> > > + case KVM_CAP_ARM_NATIVE_CACHE_CONFIG:
> > > + case KVM_CAP_ENABLE_CAP:
> > > + r = 1;
> > > + break;
> > > case KVM_CAP_SET_GUEST_DEBUG2:
> > > return KVM_GUESTDBG_VALID_MASK;
> > > case KVM_CAP_ARM_SET_DEVICE_ADDR:
> > > @@ -1793,6 +1797,19 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
> > > r = kvm_arch_vcpu_ioctl_vcpu_init(vcpu, &init);
> > > break;
> > > }
> > > + case KVM_ENABLE_CAP: {
> > > + struct kvm_enable_cap cap;
> > > +
> > > + r = -EFAULT;
> > > + if (copy_from_user(&cap, argp, sizeof(cap)))
> > > + break;
> > > +
> > > + r = -EINVAL;
> > > + if (cap.cap == KVM_CAP_ARM_NATIVE_CACHE_CONFIG &&
> > > + !cap.args[0] && !cap.flags)
> > > + r = kvm_vcpu_set_native_cache_config(vcpu);
> > > + break;
> > > + }
> > > case KVM_SET_ONE_REG:
> > > case KVM_GET_ONE_REG: {
> > > struct kvm_one_reg reg;
> > > diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> > > index 1b4cacb6e918..c19d84e48f8b 100644
> > > --- a/arch/arm64/kvm/sys_regs.c
> > > +++ b/arch/arm64/kvm/sys_regs.c
> > > @@ -484,6 +484,32 @@ static int set_ccsidr(struct kvm_vcpu *vcpu, u32 csselr, u32 val)
> > > return 0;
> > > }
> > >
> > > +int kvm_vcpu_set_native_cache_config(struct kvm_vcpu *vcpu)
> > > +{
> > > + u32 csselr;
> > > +
> > > + if (!vcpu->arch.ccsidr) {
> > > + vcpu->arch.ccsidr = kmalloc_array(CSSELR_MAX, sizeof(u32),
> > > + GFP_KERNEL_ACCOUNT);
> > > + if (!vcpu->arch.ccsidr)
> > > + return -ENOMEM;
> > > + }
> >
> > Well, no.
> >
> > The moment you decide to expose all of the host's crap, you really
> > need to put everything on the table. It means fully handling
> > FEAT_CCIDX, which we were careful not to expose anywhere because it is
> > a terrible idea.
>
> The intent here is not to "expose all of the host's crap", but to
> maintain compatibility with what the kernel did before commit
> 7af0c2534f4c. No need to expose FEAT_CCIDX.
That's not optional. Without FEAT_CCIDX, the guest cannot interpret
the correct cache geometry.
>
> > > + for (csselr = 0; csselr < CSSELR_MAX; csselr++) {
> > > + write_sysreg(csselr, csselr_el1);
> > > + isb();
> > > + vcpu->arch.ccsidr[csselr] = read_sysreg(ccsidr_el1);
> >
> > That's not how the selection register works. CLIDR_EL1 tells you what
> > each cache level is (Instructions, Data, Unified, Tags), and that must
> > be combined with the index (which doesn't start at bit 0).
>
> Ack, thanks. I'll rework that based on the old is_valid_cache()
> function.
>
> > I also wonder how you reconcile not exposing MTE when the cache
> > hierarchy indicate support for tags. That clearly contradicts "report
> > what the HW has".
>
> If that was an issue then it would already have been an issue before
> commit 7af0c2534f4 (and in kernels with that commit reverted), hosting
> millions of guests today.
That only means you are doing a pretty bad job at supporting
guests. And yes, this is an issue for anything that expects to see
something meaningful in CCSIDR[]. The fact that none of your guests
hit that problem only means you're lacking coverage.
From what I can read, anything from Neoverse V1 is affected.
>
> This isn't about introducing *new* behaviour; it's about allowing the
> existing established behaviour to be maintained so that we can have a
> *managed* transition to the new model (for new launches) rather than an
> unconditional uncontrolled change as the kernel gets upgraded.
Then fully implement "show me the cache hierarchy", read it out, and
write it back with whatever level of brokenness you intend to inflict
on your guests.
But I'm not reintroducing this particular bug.
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* [PATCH v2 6/8] clk: qcom: camcc: Add support for camera clock controller for Eliza
From: Taniya Das @ 2026-04-09 18:10 UTC (permalink / raw)
To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio, Maxime Coquelin,
Alexandre Torgue
Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm,
linux-clk, devicetree, linux-kernel, linux-stm32,
linux-arm-kernel, Taniya Das, Konrad Dybcio
In-Reply-To: <20260409-eliza_mm_cc_v2-v2-0-bc0c6dd77bc5@oss.qualcomm.com>
Add support for the Camera Clock Controller (CAMCC) on the Eliza
platform.
The CAMCC block on Eliza includes both the primary camera clock
controller and the Camera BIST clock controller, which provides the
functional MCLK required for camera operations.
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
---
drivers/clk/qcom/Kconfig | 10 +
drivers/clk/qcom/Makefile | 1 +
drivers/clk/qcom/cambistmclkcc-eliza.c | 465 ++++++
drivers/clk/qcom/camcc-eliza.c | 2803 ++++++++++++++++++++++++++++++++
4 files changed, 3279 insertions(+)
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 7626dfa536ece08e88ad198d8fa60972f06f14d5..3a8b4922ee3745f172922faa3e0316972ec7052f 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -19,6 +19,16 @@ menuconfig COMMON_CLK_QCOM
if COMMON_CLK_QCOM
+config CLK_ELIZA_CAMCC
+ tristate "Eliza Camera Clock Controller"
+ depends on ARM64 || COMPILE_TEST
+ select CLK_ELIZA_GCC
+ help
+ Support for the camera clock controller on Qualcomm Technologies, Inc
+ Eliza devices.
+ Say Y if you want to support camera devices and functionality such as
+ capturing pictures.
+
config CLK_ELIZA_DISPCC
tristate "Eliza Display Clock Controller"
depends on ARM64 || COMPILE_TEST
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 1c34797eb385963110614ba43eb9bbc9653699fb..12574157b7c8a82c890996502f79da03f25cfaa2 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -20,6 +20,7 @@ clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o
# Keep alphabetically sorted by config
obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
+obj-$(CONFIG_CLK_ELIZA_CAMCC) += cambistmclkcc-eliza.o camcc-eliza.o
obj-$(CONFIG_CLK_ELIZA_DISPCC) += dispcc-eliza.o
obj-$(CONFIG_CLK_ELIZA_GCC) += gcc-eliza.o
obj-$(CONFIG_CLK_ELIZA_GPUCC) += gpucc-eliza.o
diff --git a/drivers/clk/qcom/cambistmclkcc-eliza.c b/drivers/clk/qcom/cambistmclkcc-eliza.c
new file mode 100644
index 0000000000000000000000000000000000000000..3fda22ad13c91aeff68947d4f68154c263a8e321
--- /dev/null
+++ b/drivers/clk/qcom/cambistmclkcc-eliza.c
@@ -0,0 +1,465 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,eliza-cambistmclkcc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+#include "common.h"
+#include "reset.h"
+
+enum {
+ DT_AHB_CLK,
+ DT_BI_TCXO,
+ DT_SLEEP_CLK,
+};
+
+enum {
+ P_BI_TCXO,
+ P_CAM_BIST_MCLK_CC_PLL0_OUT_EVEN,
+ P_CAM_BIST_MCLK_CC_PLL0_OUT_MAIN,
+ P_SLEEP_CLK,
+};
+
+static const struct pll_vco rivian_ole_vco[] = {
+ { 777000000, 1285000000, 0 },
+};
+
+/* 960.0 MHz Configuration */
+static const struct alpha_pll_config cam_bist_mclk_cc_pll0_config = {
+ .l = 0x32,
+ .cal_l = 0x32,
+ .alpha = 0x0,
+ .config_ctl_val = 0x10000030,
+ .config_ctl_hi_val = 0x80890263,
+ .config_ctl_hi1_val = 0x00000217,
+ .user_ctl_val = 0x00000001,
+ .user_ctl_hi_val = 0x00000000,
+};
+
+static struct clk_alpha_pll cam_bist_mclk_cc_pll0 = {
+ .offset = 0x0,
+ .config = &cam_bist_mclk_cc_pll0_config,
+ .vco_table = rivian_ole_vco,
+ .num_vco = ARRAY_SIZE(rivian_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_RIVIAN_EVO],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_bist_mclk_cc_pll0",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_rivian_evo_ops,
+ },
+ },
+};
+
+static const struct parent_map cam_bist_mclk_cc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_BIST_MCLK_CC_PLL0_OUT_EVEN, 3 },
+ { P_CAM_BIST_MCLK_CC_PLL0_OUT_MAIN, 5 },
+};
+
+static const struct clk_parent_data cam_bist_mclk_cc_parent_data_0[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_bist_mclk_cc_pll0.clkr.hw },
+ { .hw = &cam_bist_mclk_cc_pll0.clkr.hw },
+};
+
+static const struct parent_map cam_bist_mclk_cc_parent_map_1[] = {
+ { P_SLEEP_CLK, 0 },
+};
+
+static const struct clk_parent_data cam_bist_mclk_cc_parent_data_1[] = {
+ { .index = DT_SLEEP_CLK },
+};
+
+static const struct freq_tbl ftbl_cam_bist_mclk_cc_mclk0_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(24000000, P_CAM_BIST_MCLK_CC_PLL0_OUT_EVEN, 10, 1, 4),
+ F(68571429, P_CAM_BIST_MCLK_CC_PLL0_OUT_MAIN, 14, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_bist_mclk_cc_mclk0_clk_src = {
+ .cmd_rcgr = 0x4000,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_bist_mclk_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_bist_mclk_cc_mclk0_clk_src",
+ .parent_data = cam_bist_mclk_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_bist_mclk_cc_mclk1_clk_src = {
+ .cmd_rcgr = 0x401c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_bist_mclk_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_bist_mclk_cc_mclk1_clk_src",
+ .parent_data = cam_bist_mclk_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_bist_mclk_cc_mclk2_clk_src = {
+ .cmd_rcgr = 0x4038,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_bist_mclk_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_bist_mclk_cc_mclk2_clk_src",
+ .parent_data = cam_bist_mclk_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_bist_mclk_cc_mclk3_clk_src = {
+ .cmd_rcgr = 0x4054,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_bist_mclk_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_bist_mclk_cc_mclk3_clk_src",
+ .parent_data = cam_bist_mclk_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_bist_mclk_cc_mclk4_clk_src = {
+ .cmd_rcgr = 0x4070,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_bist_mclk_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_bist_mclk_cc_mclk4_clk_src",
+ .parent_data = cam_bist_mclk_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_bist_mclk_cc_mclk5_clk_src = {
+ .cmd_rcgr = 0x408c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_bist_mclk_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_bist_mclk_cc_mclk5_clk_src",
+ .parent_data = cam_bist_mclk_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_bist_mclk_cc_mclk6_clk_src = {
+ .cmd_rcgr = 0x40a8,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_bist_mclk_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_bist_mclk_cc_mclk6_clk_src",
+ .parent_data = cam_bist_mclk_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_bist_mclk_cc_mclk7_clk_src = {
+ .cmd_rcgr = 0x40c4,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_bist_mclk_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_bist_mclk_cc_mclk0_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_bist_mclk_cc_mclk7_clk_src",
+ .parent_data = cam_bist_mclk_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_bist_mclk_cc_sleep_clk_src[] = {
+ F(32000, P_SLEEP_CLK, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_bist_mclk_cc_sleep_clk_src = {
+ .cmd_rcgr = 0x40e0,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_bist_mclk_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_bist_mclk_cc_sleep_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_bist_mclk_cc_sleep_clk_src",
+ .parent_data = cam_bist_mclk_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_bist_mclk_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_branch cam_bist_mclk_cc_mclk0_clk = {
+ .halt_reg = 0x4018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_bist_mclk_cc_mclk0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_bist_mclk_cc_mclk0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_bist_mclk_cc_mclk1_clk = {
+ .halt_reg = 0x4034,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4034,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_bist_mclk_cc_mclk1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_bist_mclk_cc_mclk1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_bist_mclk_cc_mclk2_clk = {
+ .halt_reg = 0x4050,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4050,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_bist_mclk_cc_mclk2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_bist_mclk_cc_mclk2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_bist_mclk_cc_mclk3_clk = {
+ .halt_reg = 0x406c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x406c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_bist_mclk_cc_mclk3_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_bist_mclk_cc_mclk3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_bist_mclk_cc_mclk4_clk = {
+ .halt_reg = 0x4088,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4088,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_bist_mclk_cc_mclk4_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_bist_mclk_cc_mclk4_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_bist_mclk_cc_mclk5_clk = {
+ .halt_reg = 0x40a4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x40a4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_bist_mclk_cc_mclk5_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_bist_mclk_cc_mclk5_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_bist_mclk_cc_mclk6_clk = {
+ .halt_reg = 0x40c0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x40c0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_bist_mclk_cc_mclk6_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_bist_mclk_cc_mclk6_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_bist_mclk_cc_mclk7_clk = {
+ .halt_reg = 0x40dc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x40dc,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_bist_mclk_cc_mclk7_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_bist_mclk_cc_mclk7_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_regmap *cam_bist_mclk_cc_eliza_clocks[] = {
+ [CAM_BIST_MCLK_CC_MCLK0_CLK] = &cam_bist_mclk_cc_mclk0_clk.clkr,
+ [CAM_BIST_MCLK_CC_MCLK0_CLK_SRC] = &cam_bist_mclk_cc_mclk0_clk_src.clkr,
+ [CAM_BIST_MCLK_CC_MCLK1_CLK] = &cam_bist_mclk_cc_mclk1_clk.clkr,
+ [CAM_BIST_MCLK_CC_MCLK1_CLK_SRC] = &cam_bist_mclk_cc_mclk1_clk_src.clkr,
+ [CAM_BIST_MCLK_CC_MCLK2_CLK] = &cam_bist_mclk_cc_mclk2_clk.clkr,
+ [CAM_BIST_MCLK_CC_MCLK2_CLK_SRC] = &cam_bist_mclk_cc_mclk2_clk_src.clkr,
+ [CAM_BIST_MCLK_CC_MCLK3_CLK] = &cam_bist_mclk_cc_mclk3_clk.clkr,
+ [CAM_BIST_MCLK_CC_MCLK3_CLK_SRC] = &cam_bist_mclk_cc_mclk3_clk_src.clkr,
+ [CAM_BIST_MCLK_CC_MCLK4_CLK] = &cam_bist_mclk_cc_mclk4_clk.clkr,
+ [CAM_BIST_MCLK_CC_MCLK4_CLK_SRC] = &cam_bist_mclk_cc_mclk4_clk_src.clkr,
+ [CAM_BIST_MCLK_CC_MCLK5_CLK] = &cam_bist_mclk_cc_mclk5_clk.clkr,
+ [CAM_BIST_MCLK_CC_MCLK5_CLK_SRC] = &cam_bist_mclk_cc_mclk5_clk_src.clkr,
+ [CAM_BIST_MCLK_CC_MCLK6_CLK] = &cam_bist_mclk_cc_mclk6_clk.clkr,
+ [CAM_BIST_MCLK_CC_MCLK6_CLK_SRC] = &cam_bist_mclk_cc_mclk6_clk_src.clkr,
+ [CAM_BIST_MCLK_CC_MCLK7_CLK] = &cam_bist_mclk_cc_mclk7_clk.clkr,
+ [CAM_BIST_MCLK_CC_MCLK7_CLK_SRC] = &cam_bist_mclk_cc_mclk7_clk_src.clkr,
+ [CAM_BIST_MCLK_CC_PLL0] = &cam_bist_mclk_cc_pll0.clkr,
+ [CAM_BIST_MCLK_CC_SLEEP_CLK_SRC] = &cam_bist_mclk_cc_sleep_clk_src.clkr,
+};
+
+static struct clk_alpha_pll *cam_bist_mclk_cc_eliza_plls[] = {
+ &cam_bist_mclk_cc_pll0,
+};
+
+static u32 cam_bist_mclk_cc_eliza_critical_cbcrs[] = {
+ 0x40f8, /* CAM_BIST_MCLK_CC_SLEEP_CLK */
+};
+
+static const struct regmap_config cam_bist_mclk_cc_eliza_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x5010,
+ .fast_io = true,
+};
+
+static struct qcom_cc_driver_data cam_bist_mclk_cc_eliza_driver_data = {
+ .alpha_plls = cam_bist_mclk_cc_eliza_plls,
+ .num_alpha_plls = ARRAY_SIZE(cam_bist_mclk_cc_eliza_plls),
+ .clk_cbcrs = cam_bist_mclk_cc_eliza_critical_cbcrs,
+ .num_clk_cbcrs = ARRAY_SIZE(cam_bist_mclk_cc_eliza_critical_cbcrs),
+};
+
+static const struct qcom_cc_desc cam_bist_mclk_cc_eliza_desc = {
+ .config = &cam_bist_mclk_cc_eliza_regmap_config,
+ .clks = cam_bist_mclk_cc_eliza_clocks,
+ .num_clks = ARRAY_SIZE(cam_bist_mclk_cc_eliza_clocks),
+ .use_rpm = true,
+ .driver_data = &cam_bist_mclk_cc_eliza_driver_data,
+};
+
+static const struct of_device_id cam_bist_mclk_cc_eliza_match_table[] = {
+ { .compatible = "qcom,eliza-cambistmclkcc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, cam_bist_mclk_cc_eliza_match_table);
+
+static int cam_bist_mclk_cc_eliza_probe(struct platform_device *pdev)
+{
+ return qcom_cc_probe(pdev, &cam_bist_mclk_cc_eliza_desc);
+}
+
+static struct platform_driver cam_bist_mclk_cc_eliza_driver = {
+ .probe = cam_bist_mclk_cc_eliza_probe,
+ .driver = {
+ .name = "cambistmclkcc-eliza",
+ .of_match_table = cam_bist_mclk_cc_eliza_match_table,
+ },
+};
+
+module_platform_driver(cam_bist_mclk_cc_eliza_driver);
+
+MODULE_DESCRIPTION("QTI CAMBISTMCLKCC Eliza Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/camcc-eliza.c b/drivers/clk/qcom/camcc-eliza.c
new file mode 100644
index 0000000000000000000000000000000000000000..52cef1827ffb43b82c68234349baa1988d7a1527
--- /dev/null
+++ b/drivers/clk/qcom/camcc-eliza.c
@@ -0,0 +1,2803 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,eliza-camcc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ DT_AHB_CLK,
+ DT_BI_TCXO,
+ DT_SLEEP_CLK,
+};
+
+enum {
+ P_BI_TCXO,
+ P_CAM_CC_PLL0_OUT_EVEN,
+ P_CAM_CC_PLL0_OUT_MAIN,
+ P_CAM_CC_PLL0_OUT_ODD,
+ P_CAM_CC_PLL1_OUT_EVEN,
+ P_CAM_CC_PLL2_OUT_EVEN,
+ P_CAM_CC_PLL3_OUT_EVEN,
+ P_CAM_CC_PLL4_OUT_EVEN,
+ P_CAM_CC_PLL5_OUT_EVEN,
+ P_CAM_CC_PLL6_OUT_EVEN,
+ P_CAM_CC_PLL6_OUT_ODD,
+ P_SLEEP_CLK,
+};
+
+static const struct pll_vco lucid_ole_vco[] = {
+ { 249600000, 2300000000, 0 },
+};
+
+/* 1200.0 MHz Configuration */
+static const struct alpha_pll_config cam_cc_pll0_config = {
+ .l = 0x3e,
+ .cal_l = 0x44,
+ .alpha = 0x8000,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00008400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll0 = {
+ .offset = 0x0,
+ .config = &cam_cc_pll0_config,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll0",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll0_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll0_out_even = {
+ .offset = 0x0,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll0_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll0_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll0_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll0_out_odd[] = {
+ { 0x2, 3 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll0_out_odd = {
+ .offset = 0x0,
+ .post_div_shift = 14,
+ .post_div_table = post_div_table_cam_cc_pll0_out_odd,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll0_out_odd),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll0_out_odd",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+/* 900.0 MHz Configuration */
+static const struct alpha_pll_config cam_cc_pll1_config = {
+ .l = 0x2e,
+ .cal_l = 0x44,
+ .alpha = 0xe000,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll1 = {
+ .offset = 0x1000,
+ .config = &cam_cc_pll1_config,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll1",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll1_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll1_out_even = {
+ .offset = 0x1000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll1_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll1_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll1_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll1.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+/* 872.0 MHz Configuration */
+static const struct alpha_pll_config cam_cc_pll2_config = {
+ .l = 0x2d,
+ .cal_l = 0x44,
+ .alpha = 0x6aaa,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll2 = {
+ .offset = 0x2000,
+ .config = &cam_cc_pll2_config,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll2",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll2_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll2_out_even = {
+ .offset = 0x2000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll2_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll2_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll2_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll2.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+/* 890.0 MHz Configuration */
+static const struct alpha_pll_config cam_cc_pll3_config = {
+ .l = 0x2e,
+ .cal_l = 0x44,
+ .alpha = 0x5aaa,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll3 = {
+ .offset = 0x3000,
+ .config = &cam_cc_pll3_config,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll3",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll3_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll3_out_even = {
+ .offset = 0x3000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll3_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll3_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll3_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll3.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+/* 890.0 MHz Configuration */
+static const struct alpha_pll_config cam_cc_pll4_config = {
+ .l = 0x2e,
+ .cal_l = 0x44,
+ .alpha = 0x5aaa,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll4 = {
+ .offset = 0x4000,
+ .config = &cam_cc_pll4_config,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll4",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll4_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll4_out_even = {
+ .offset = 0x4000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll4_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll4_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll4_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll4.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+/* 890.0 MHz Configuration */
+static const struct alpha_pll_config cam_cc_pll5_config = {
+ .l = 0x2e,
+ .cal_l = 0x44,
+ .alpha = 0x5aaa,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll5 = {
+ .offset = 0x5000,
+ .config = &cam_cc_pll5_config,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll5",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll5_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll5_out_even = {
+ .offset = 0x5000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll5_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll5_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll5_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll5.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+/* 960.0 MHz Configuration */
+static const struct alpha_pll_config cam_cc_pll6_config = {
+ .l = 0x32,
+ .cal_l = 0x44,
+ .alpha = 0x0,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00008400,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll cam_cc_pll6 = {
+ .offset = 0x6000,
+ .config = &cam_cc_pll6_config,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll6",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll6_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll6_out_even = {
+ .offset = 0x6000,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_cam_cc_pll6_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll6_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll6_out_even",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll6.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static const struct clk_div_table post_div_table_cam_cc_pll6_out_odd[] = {
+ { 0x2, 3 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv cam_cc_pll6_out_odd = {
+ .offset = 0x6000,
+ .post_div_shift = 14,
+ .post_div_table = post_div_table_cam_cc_pll6_out_odd,
+ .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll6_out_odd),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_pll6_out_odd",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_pll6.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static const struct parent_map cam_cc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL0_OUT_MAIN, 1 },
+ { P_CAM_CC_PLL0_OUT_EVEN, 2 },
+ { P_CAM_CC_PLL0_OUT_ODD, 3 },
+ { P_CAM_CC_PLL6_OUT_ODD, 4 },
+ { P_CAM_CC_PLL6_OUT_EVEN, 5 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_0[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll0.clkr.hw },
+ { .hw = &cam_cc_pll0_out_even.clkr.hw },
+ { .hw = &cam_cc_pll0_out_odd.clkr.hw },
+ { .hw = &cam_cc_pll6_out_odd.clkr.hw },
+ { .hw = &cam_cc_pll6_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL0_OUT_MAIN, 1 },
+ { P_CAM_CC_PLL0_OUT_EVEN, 2 },
+ { P_CAM_CC_PLL0_OUT_ODD, 3 },
+ { P_CAM_CC_PLL6_OUT_ODD, 4 },
+ { P_CAM_CC_PLL6_OUT_EVEN, 5 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_1[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll0.clkr.hw },
+ { .hw = &cam_cc_pll0_out_even.clkr.hw },
+ { .hw = &cam_cc_pll0_out_odd.clkr.hw },
+ { .hw = &cam_cc_pll6_out_odd.clkr.hw },
+ { .hw = &cam_cc_pll6_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL1_OUT_EVEN, 4 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_2[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll1_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_3[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL2_OUT_EVEN, 5 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_3[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll2_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_4[] = {
+ { P_SLEEP_CLK, 0 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_4[] = {
+ { .index = DT_SLEEP_CLK },
+};
+
+static const struct parent_map cam_cc_parent_map_5[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL3_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_5[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll3_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_6[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL4_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_6[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll4_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_7[] = {
+ { P_BI_TCXO, 0 },
+ { P_CAM_CC_PLL5_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_7[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &cam_cc_pll5_out_even.clkr.hw },
+};
+
+static const struct parent_map cam_cc_parent_map_8[] = {
+ { P_BI_TCXO, 0 },
+};
+
+static const struct clk_parent_data cam_cc_parent_data_8[] = {
+ { .index = DT_BI_TCXO },
+};
+
+static const struct freq_tbl ftbl_cam_cc_camnoc_rt_axi_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0),
+ F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_camnoc_rt_axi_clk_src = {
+ .cmd_rcgr = 0x112e8,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_camnoc_rt_axi_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_rt_axi_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_cci_0_clk_src[] = {
+ F(37500000, P_CAM_CC_PLL0_OUT_EVEN, 16, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_cci_0_clk_src = {
+ .cmd_rcgr = 0x1126c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cci_0_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_0_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_cci_1_clk_src = {
+ .cmd_rcgr = 0x11288,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cci_0_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_1_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_cci_2_clk_src = {
+ .cmd_rcgr = 0x112a4,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cci_0_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_2_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_cphy_rx_clk_src[] = {
+ F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ F(480000000, P_CAM_CC_PLL0_OUT_MAIN, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_cphy_rx_clk_src = {
+ .cmd_rcgr = 0x11068,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cphy_rx_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_cre_clk_src[] = {
+ F(200000000, P_CAM_CC_PLL0_OUT_ODD, 2, 0, 0),
+ F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0),
+ F(480000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0),
+ F(600000000, P_CAM_CC_PLL0_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_cre_clk_src = {
+ .cmd_rcgr = 0x111ac,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cre_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cre_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_csi0phytimer_clk_src[] = {
+ F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_csi0phytimer_clk_src = {
+ .cmd_rcgr = 0x10000,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi0phytimer_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_csi1phytimer_clk_src = {
+ .cmd_rcgr = 0x10024,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi1phytimer_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_csi2phytimer_clk_src = {
+ .cmd_rcgr = 0x10044,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi2phytimer_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_csi3phytimer_clk_src = {
+ .cmd_rcgr = 0x10064,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi3phytimer_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_csi4phytimer_clk_src = {
+ .cmd_rcgr = 0x10084,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi4phytimer_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_csi5phytimer_clk_src = {
+ .cmd_rcgr = 0x100a4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi5phytimer_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_csid_clk_src = {
+ .cmd_rcgr = 0x112c0,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csid_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_fast_ahb_clk_src[] = {
+ F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0),
+ F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_fast_ahb_clk_src = {
+ .cmd_rcgr = 0x100dc,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_fast_ahb_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_fast_ahb_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_icp_0_clk_src[] = {
+ F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0),
+ F(480000000, P_CAM_CC_PLL6_OUT_EVEN, 1, 0, 0),
+ F(600000000, P_CAM_CC_PLL0_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_icp_0_clk_src = {
+ .cmd_rcgr = 0x11214,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_icp_0_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_icp_0_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_icp_1_clk_src = {
+ .cmd_rcgr = 0x1123c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_icp_0_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_icp_1_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_ife_lite_clk_src = {
+ .cmd_rcgr = 0x11150,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_lite_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_ife_lite_csid_clk_src = {
+ .cmd_rcgr = 0x1117c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_1,
+ .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_lite_csid_clk_src",
+ .parent_data = cam_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_ipe_nps_clk_src[] = {
+ F(450000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0),
+ F(575000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0),
+ F(675000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0),
+ F(825000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_ipe_nps_clk_src = {
+ .cmd_rcgr = 0x10190,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_2,
+ .freq_tbl = ftbl_cam_cc_ipe_nps_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_nps_clk_src",
+ .parent_data = cam_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 cam_cc_jpeg_clk_src = {
+ .cmd_rcgr = 0x111d0,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_cre_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_jpeg_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_ofe_clk_src[] = {
+ F(436000000, P_CAM_CC_PLL2_OUT_EVEN, 1, 0, 0),
+ F(570000000, P_CAM_CC_PLL2_OUT_EVEN, 1, 0, 0),
+ F(675000000, P_CAM_CC_PLL2_OUT_EVEN, 1, 0, 0),
+ F(757000000, P_CAM_CC_PLL2_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_ofe_clk_src = {
+ .cmd_rcgr = 0x1011c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_3,
+ .freq_tbl = ftbl_cam_cc_ofe_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ofe_clk_src",
+ .parent_data = cam_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_qdss_debug_clk_src[] = {
+ F(60000000, P_CAM_CC_PLL6_OUT_EVEN, 8, 0, 0),
+ F(120000000, P_CAM_CC_PLL0_OUT_EVEN, 5, 0, 0),
+ F(240000000, P_CAM_CC_PLL0_OUT_MAIN, 5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_qdss_debug_clk_src = {
+ .cmd_rcgr = 0x1132c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_qdss_debug_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_qdss_debug_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_sleep_clk_src[] = {
+ F(32000, P_SLEEP_CLK, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_sleep_clk_src = {
+ .cmd_rcgr = 0x11380,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_4,
+ .freq_tbl = ftbl_cam_cc_sleep_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_sleep_clk_src",
+ .parent_data = cam_cc_parent_data_4,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_4),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_slow_ahb_clk_src[] = {
+ F(80000000, P_CAM_CC_PLL0_OUT_EVEN, 7.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_slow_ahb_clk_src = {
+ .cmd_rcgr = 0x10100,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_0,
+ .freq_tbl = ftbl_cam_cc_slow_ahb_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_slow_ahb_clk_src",
+ .parent_data = cam_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_tfe_0_clk_src[] = {
+ F(445000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0),
+ F(567000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0),
+ F(644000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0),
+ F(785000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_tfe_0_clk_src = {
+ .cmd_rcgr = 0x11018,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_5,
+ .freq_tbl = ftbl_cam_cc_tfe_0_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_tfe_0_clk_src",
+ .parent_data = cam_cc_parent_data_5,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_5),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_tfe_1_clk_src[] = {
+ F(445000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0),
+ F(567000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0),
+ F(644000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0),
+ F(785000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_tfe_1_clk_src = {
+ .cmd_rcgr = 0x11098,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_6,
+ .freq_tbl = ftbl_cam_cc_tfe_1_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_tfe_1_clk_src",
+ .parent_data = cam_cc_parent_data_6,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_6),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_tfe_2_clk_src[] = {
+ F(445000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0),
+ F(567000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0),
+ F(644000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0),
+ F(785000000, P_CAM_CC_PLL5_OUT_EVEN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_tfe_2_clk_src = {
+ .cmd_rcgr = 0x11100,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_7,
+ .freq_tbl = ftbl_cam_cc_tfe_2_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_tfe_2_clk_src",
+ .parent_data = cam_cc_parent_data_7,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_7),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_cam_cc_xo_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 cam_cc_xo_clk_src = {
+ .cmd_rcgr = 0x11364,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = cam_cc_parent_map_8,
+ .freq_tbl = ftbl_cam_cc_xo_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_xo_clk_src",
+ .parent_data = cam_cc_parent_data_8,
+ .num_parents = ARRAY_SIZE(cam_cc_parent_data_8),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_branch cam_cc_cam_top_ahb_clk = {
+ .halt_reg = 0x113ac,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x113ac,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cam_top_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cam_top_fast_ahb_clk = {
+ .halt_reg = 0x1139c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1139c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cam_top_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_dcd_xo_clk = {
+ .halt_reg = 0x11320,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11320,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_dcd_xo_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_nrt_axi_clk = {
+ .halt_reg = 0x11310,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x11310,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x11310,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_nrt_axi_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_camnoc_rt_axi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_nrt_cre_clk = {
+ .halt_reg = 0x111c8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x111c8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_nrt_cre_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cre_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_nrt_ipe_nps_clk = {
+ .halt_reg = 0x101b8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x101b8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_nrt_ipe_nps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ipe_nps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_nrt_ofe_anchor_clk = {
+ .halt_reg = 0x10158,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10158,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_nrt_ofe_anchor_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ofe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_nrt_ofe_hdr_clk = {
+ .halt_reg = 0x1016c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1016c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_nrt_ofe_hdr_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ofe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_nrt_ofe_main_clk = {
+ .halt_reg = 0x10144,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10144,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_nrt_ofe_main_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ofe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_rt_axi_clk = {
+ .halt_reg = 0x11300,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11300,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_rt_axi_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_camnoc_rt_axi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_rt_ife_lite_clk = {
+ .halt_reg = 0x11178,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11178,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_rt_ife_lite_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_lite_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_rt_tfe_0_bayer_clk = {
+ .halt_reg = 0x11054,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11054,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_rt_tfe_0_bayer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_tfe_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_rt_tfe_0_main_clk = {
+ .halt_reg = 0x11040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11040,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_rt_tfe_0_main_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_tfe_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_rt_tfe_1_bayer_clk = {
+ .halt_reg = 0x110d4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x110d4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_rt_tfe_1_bayer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_tfe_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_rt_tfe_1_main_clk = {
+ .halt_reg = 0x110c0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x110c0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_rt_tfe_1_main_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_tfe_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_rt_tfe_2_bayer_clk = {
+ .halt_reg = 0x1113c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1113c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_rt_tfe_2_bayer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_tfe_2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_rt_tfe_2_main_clk = {
+ .halt_reg = 0x11128,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11128,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_rt_tfe_2_main_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_tfe_2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_camnoc_xo_clk = {
+ .halt_reg = 0x11324,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11324,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_camnoc_xo_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cci_0_clk = {
+ .halt_reg = 0x11284,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11284,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cci_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cci_1_clk = {
+ .halt_reg = 0x112a0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x112a0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cci_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cci_2_clk = {
+ .halt_reg = 0x112bc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x112bc,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cci_2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cci_2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_core_ahb_clk = {
+ .halt_reg = 0x11360,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x11360,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_core_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cre_ahb_clk = {
+ .halt_reg = 0x111cc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x111cc,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cre_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_cre_clk = {
+ .halt_reg = 0x111c4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x111c4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_cre_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cre_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi0phytimer_clk = {
+ .halt_reg = 0x10018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10018,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi0phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi0phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi1phytimer_clk = {
+ .halt_reg = 0x1003c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1003c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi1phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi1phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi2phytimer_clk = {
+ .halt_reg = 0x1005c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1005c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi2phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi2phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi3phytimer_clk = {
+ .halt_reg = 0x1007c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1007c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi3phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi3phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi4phytimer_clk = {
+ .halt_reg = 0x1009c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1009c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi4phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi4phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csi5phytimer_clk = {
+ .halt_reg = 0x100bc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x100bc,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csi5phytimer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csi5phytimer_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csid_clk = {
+ .halt_reg = 0x112d8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x112d8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csid_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_csid_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csid_csiphy_rx_clk = {
+ .halt_reg = 0x10020,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10020,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csid_csiphy_rx_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csiphy0_clk = {
+ .halt_reg = 0x1001c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1001c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csiphy1_clk = {
+ .halt_reg = 0x10040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10040,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csiphy2_clk = {
+ .halt_reg = 0x10060,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10060,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy2_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csiphy3_clk = {
+ .halt_reg = 0x10080,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10080,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy3_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csiphy4_clk = {
+ .halt_reg = 0x100a0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x100a0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy4_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_csiphy5_clk = {
+ .halt_reg = 0x100c0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x100c0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_csiphy5_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_drv_ahb_clk = {
+ .halt_reg = 0x113c4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x113c4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_drv_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_drv_xo_clk = {
+ .halt_reg = 0x113c0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x113c0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_drv_xo_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_icp_0_ahb_clk = {
+ .halt_reg = 0x11264,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11264,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_icp_0_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_icp_0_clk = {
+ .halt_reg = 0x1122c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1122c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_icp_0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_icp_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_icp_1_ahb_clk = {
+ .halt_reg = 0x11268,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11268,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_icp_1_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_icp_1_clk = {
+ .halt_reg = 0x11254,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11254,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_icp_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_icp_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_lite_ahb_clk = {
+ .halt_reg = 0x111a8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x111a8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_lite_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_lite_clk = {
+ .halt_reg = 0x11168,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11168,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_lite_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_lite_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_lite_cphy_rx_clk = {
+ .halt_reg = 0x111a4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x111a4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_lite_cphy_rx_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_cphy_rx_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ife_lite_csid_clk = {
+ .halt_reg = 0x11194,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11194,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ife_lite_csid_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ife_lite_csid_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ipe_nps_ahb_clk = {
+ .halt_reg = 0x101d4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x101d4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_nps_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ipe_nps_clk = {
+ .halt_reg = 0x101a8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x101a8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_nps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ipe_nps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ipe_nps_fast_ahb_clk = {
+ .halt_reg = 0x101d8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x101d8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_nps_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ipe_pps_clk = {
+ .halt_reg = 0x101bc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x101bc,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_pps_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ipe_nps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ipe_pps_fast_ahb_clk = {
+ .halt_reg = 0x101dc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x101dc,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ipe_pps_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_jpeg_0_clk = {
+ .halt_reg = 0x111e8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x111e8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_jpeg_0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_jpeg_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_jpeg_1_clk = {
+ .halt_reg = 0x111f8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x111f8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_jpeg_1_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_jpeg_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ofe_ahb_clk = {
+ .halt_reg = 0x10118,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10118,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ofe_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_slow_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ofe_anchor_clk = {
+ .halt_reg = 0x10148,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10148,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ofe_anchor_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ofe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ofe_anchor_fast_ahb_clk = {
+ .halt_reg = 0x100f8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x100f8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ofe_anchor_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ofe_hdr_clk = {
+ .halt_reg = 0x1015c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1015c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ofe_hdr_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ofe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ofe_hdr_fast_ahb_clk = {
+ .halt_reg = 0x100fc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x100fc,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ofe_hdr_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ofe_main_clk = {
+ .halt_reg = 0x10134,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x10134,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ofe_main_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_ofe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_ofe_main_fast_ahb_clk = {
+ .halt_reg = 0x100f4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x100f4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_ofe_main_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_qdss_debug_clk = {
+ .halt_reg = 0x11344,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11344,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_qdss_debug_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_qdss_debug_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_qdss_debug_xo_clk = {
+ .halt_reg = 0x11348,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11348,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_qdss_debug_xo_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_tfe_0_bayer_clk = {
+ .halt_reg = 0x11044,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11044,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_tfe_0_bayer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_tfe_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_tfe_0_bayer_fast_ahb_clk = {
+ .halt_reg = 0x11064,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11064,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_tfe_0_bayer_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_tfe_0_main_clk = {
+ .halt_reg = 0x11030,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11030,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_tfe_0_main_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_tfe_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_tfe_0_main_fast_ahb_clk = {
+ .halt_reg = 0x11060,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11060,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_tfe_0_main_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_tfe_1_bayer_clk = {
+ .halt_reg = 0x110c4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x110c4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_tfe_1_bayer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_tfe_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_tfe_1_bayer_fast_ahb_clk = {
+ .halt_reg = 0x110e4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x110e4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_tfe_1_bayer_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_tfe_1_main_clk = {
+ .halt_reg = 0x110b0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x110b0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_tfe_1_main_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_tfe_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_tfe_1_main_fast_ahb_clk = {
+ .halt_reg = 0x110e0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x110e0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_tfe_1_main_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_tfe_2_bayer_clk = {
+ .halt_reg = 0x1112c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1112c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_tfe_2_bayer_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_tfe_2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_tfe_2_bayer_fast_ahb_clk = {
+ .halt_reg = 0x1114c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1114c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_tfe_2_bayer_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_tfe_2_main_clk = {
+ .halt_reg = 0x11118,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11118,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_tfe_2_main_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_tfe_2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch cam_cc_tfe_2_main_fast_ahb_clk = {
+ .halt_reg = 0x11148,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x11148,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "cam_cc_tfe_2_main_fast_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &cam_cc_fast_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc cam_cc_titan_top_gdsc = {
+ .gdscr = 0x1134c,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_titan_top_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_ipe_0_gdsc = {
+ .gdscr = 0x1017c,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_ipe_0_gdsc",
+ },
+ .parent = &cam_cc_titan_top_gdsc.pd,
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_ofe_gdsc = {
+ .gdscr = 0x100c8,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_ofe_gdsc",
+ },
+ .parent = &cam_cc_titan_top_gdsc.pd,
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = HW_CTRL_TRIGGER | POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_tfe_0_gdsc = {
+ .gdscr = 0x11004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_tfe_0_gdsc",
+ },
+ .parent = &cam_cc_titan_top_gdsc.pd,
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_tfe_1_gdsc = {
+ .gdscr = 0x11084,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_tfe_1_gdsc",
+ },
+ .parent = &cam_cc_titan_top_gdsc.pd,
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc cam_cc_tfe_2_gdsc = {
+ .gdscr = 0x110ec,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "cam_cc_tfe_2_gdsc",
+ },
+ .parent = &cam_cc_titan_top_gdsc.pd,
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct clk_regmap *cam_cc_eliza_clocks[] = {
+ [CAM_CC_CAM_TOP_AHB_CLK] = &cam_cc_cam_top_ahb_clk.clkr,
+ [CAM_CC_CAM_TOP_FAST_AHB_CLK] = &cam_cc_cam_top_fast_ahb_clk.clkr,
+ [CAM_CC_CAMNOC_DCD_XO_CLK] = &cam_cc_camnoc_dcd_xo_clk.clkr,
+ [CAM_CC_CAMNOC_NRT_AXI_CLK] = &cam_cc_camnoc_nrt_axi_clk.clkr,
+ [CAM_CC_CAMNOC_NRT_CRE_CLK] = &cam_cc_camnoc_nrt_cre_clk.clkr,
+ [CAM_CC_CAMNOC_NRT_IPE_NPS_CLK] = &cam_cc_camnoc_nrt_ipe_nps_clk.clkr,
+ [CAM_CC_CAMNOC_NRT_OFE_ANCHOR_CLK] = &cam_cc_camnoc_nrt_ofe_anchor_clk.clkr,
+ [CAM_CC_CAMNOC_NRT_OFE_HDR_CLK] = &cam_cc_camnoc_nrt_ofe_hdr_clk.clkr,
+ [CAM_CC_CAMNOC_NRT_OFE_MAIN_CLK] = &cam_cc_camnoc_nrt_ofe_main_clk.clkr,
+ [CAM_CC_CAMNOC_RT_AXI_CLK] = &cam_cc_camnoc_rt_axi_clk.clkr,
+ [CAM_CC_CAMNOC_RT_AXI_CLK_SRC] = &cam_cc_camnoc_rt_axi_clk_src.clkr,
+ [CAM_CC_CAMNOC_RT_IFE_LITE_CLK] = &cam_cc_camnoc_rt_ife_lite_clk.clkr,
+ [CAM_CC_CAMNOC_RT_TFE_0_BAYER_CLK] = &cam_cc_camnoc_rt_tfe_0_bayer_clk.clkr,
+ [CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK] = &cam_cc_camnoc_rt_tfe_0_main_clk.clkr,
+ [CAM_CC_CAMNOC_RT_TFE_1_BAYER_CLK] = &cam_cc_camnoc_rt_tfe_1_bayer_clk.clkr,
+ [CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK] = &cam_cc_camnoc_rt_tfe_1_main_clk.clkr,
+ [CAM_CC_CAMNOC_RT_TFE_2_BAYER_CLK] = &cam_cc_camnoc_rt_tfe_2_bayer_clk.clkr,
+ [CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK] = &cam_cc_camnoc_rt_tfe_2_main_clk.clkr,
+ [CAM_CC_CAMNOC_XO_CLK] = &cam_cc_camnoc_xo_clk.clkr,
+ [CAM_CC_CCI_0_CLK] = &cam_cc_cci_0_clk.clkr,
+ [CAM_CC_CCI_0_CLK_SRC] = &cam_cc_cci_0_clk_src.clkr,
+ [CAM_CC_CCI_1_CLK] = &cam_cc_cci_1_clk.clkr,
+ [CAM_CC_CCI_1_CLK_SRC] = &cam_cc_cci_1_clk_src.clkr,
+ [CAM_CC_CCI_2_CLK] = &cam_cc_cci_2_clk.clkr,
+ [CAM_CC_CCI_2_CLK_SRC] = &cam_cc_cci_2_clk_src.clkr,
+ [CAM_CC_CORE_AHB_CLK] = &cam_cc_core_ahb_clk.clkr,
+ [CAM_CC_CPHY_RX_CLK_SRC] = &cam_cc_cphy_rx_clk_src.clkr,
+ [CAM_CC_CRE_AHB_CLK] = &cam_cc_cre_ahb_clk.clkr,
+ [CAM_CC_CRE_CLK] = &cam_cc_cre_clk.clkr,
+ [CAM_CC_CRE_CLK_SRC] = &cam_cc_cre_clk_src.clkr,
+ [CAM_CC_CSI0PHYTIMER_CLK] = &cam_cc_csi0phytimer_clk.clkr,
+ [CAM_CC_CSI0PHYTIMER_CLK_SRC] = &cam_cc_csi0phytimer_clk_src.clkr,
+ [CAM_CC_CSI1PHYTIMER_CLK] = &cam_cc_csi1phytimer_clk.clkr,
+ [CAM_CC_CSI1PHYTIMER_CLK_SRC] = &cam_cc_csi1phytimer_clk_src.clkr,
+ [CAM_CC_CSI2PHYTIMER_CLK] = &cam_cc_csi2phytimer_clk.clkr,
+ [CAM_CC_CSI2PHYTIMER_CLK_SRC] = &cam_cc_csi2phytimer_clk_src.clkr,
+ [CAM_CC_CSI3PHYTIMER_CLK] = &cam_cc_csi3phytimer_clk.clkr,
+ [CAM_CC_CSI3PHYTIMER_CLK_SRC] = &cam_cc_csi3phytimer_clk_src.clkr,
+ [CAM_CC_CSI4PHYTIMER_CLK] = &cam_cc_csi4phytimer_clk.clkr,
+ [CAM_CC_CSI4PHYTIMER_CLK_SRC] = &cam_cc_csi4phytimer_clk_src.clkr,
+ [CAM_CC_CSI5PHYTIMER_CLK] = &cam_cc_csi5phytimer_clk.clkr,
+ [CAM_CC_CSI5PHYTIMER_CLK_SRC] = &cam_cc_csi5phytimer_clk_src.clkr,
+ [CAM_CC_CSID_CLK] = &cam_cc_csid_clk.clkr,
+ [CAM_CC_CSID_CLK_SRC] = &cam_cc_csid_clk_src.clkr,
+ [CAM_CC_CSID_CSIPHY_RX_CLK] = &cam_cc_csid_csiphy_rx_clk.clkr,
+ [CAM_CC_CSIPHY0_CLK] = &cam_cc_csiphy0_clk.clkr,
+ [CAM_CC_CSIPHY1_CLK] = &cam_cc_csiphy1_clk.clkr,
+ [CAM_CC_CSIPHY2_CLK] = &cam_cc_csiphy2_clk.clkr,
+ [CAM_CC_CSIPHY3_CLK] = &cam_cc_csiphy3_clk.clkr,
+ [CAM_CC_CSIPHY4_CLK] = &cam_cc_csiphy4_clk.clkr,
+ [CAM_CC_CSIPHY5_CLK] = &cam_cc_csiphy5_clk.clkr,
+ [CAM_CC_DRV_AHB_CLK] = &cam_cc_drv_ahb_clk.clkr,
+ [CAM_CC_DRV_XO_CLK] = &cam_cc_drv_xo_clk.clkr,
+ [CAM_CC_FAST_AHB_CLK_SRC] = &cam_cc_fast_ahb_clk_src.clkr,
+ [CAM_CC_ICP_0_AHB_CLK] = &cam_cc_icp_0_ahb_clk.clkr,
+ [CAM_CC_ICP_0_CLK] = &cam_cc_icp_0_clk.clkr,
+ [CAM_CC_ICP_0_CLK_SRC] = &cam_cc_icp_0_clk_src.clkr,
+ [CAM_CC_ICP_1_AHB_CLK] = &cam_cc_icp_1_ahb_clk.clkr,
+ [CAM_CC_ICP_1_CLK] = &cam_cc_icp_1_clk.clkr,
+ [CAM_CC_ICP_1_CLK_SRC] = &cam_cc_icp_1_clk_src.clkr,
+ [CAM_CC_IFE_LITE_AHB_CLK] = &cam_cc_ife_lite_ahb_clk.clkr,
+ [CAM_CC_IFE_LITE_CLK] = &cam_cc_ife_lite_clk.clkr,
+ [CAM_CC_IFE_LITE_CLK_SRC] = &cam_cc_ife_lite_clk_src.clkr,
+ [CAM_CC_IFE_LITE_CPHY_RX_CLK] = &cam_cc_ife_lite_cphy_rx_clk.clkr,
+ [CAM_CC_IFE_LITE_CSID_CLK] = &cam_cc_ife_lite_csid_clk.clkr,
+ [CAM_CC_IFE_LITE_CSID_CLK_SRC] = &cam_cc_ife_lite_csid_clk_src.clkr,
+ [CAM_CC_IPE_NPS_AHB_CLK] = &cam_cc_ipe_nps_ahb_clk.clkr,
+ [CAM_CC_IPE_NPS_CLK] = &cam_cc_ipe_nps_clk.clkr,
+ [CAM_CC_IPE_NPS_CLK_SRC] = &cam_cc_ipe_nps_clk_src.clkr,
+ [CAM_CC_IPE_NPS_FAST_AHB_CLK] = &cam_cc_ipe_nps_fast_ahb_clk.clkr,
+ [CAM_CC_IPE_PPS_CLK] = &cam_cc_ipe_pps_clk.clkr,
+ [CAM_CC_IPE_PPS_FAST_AHB_CLK] = &cam_cc_ipe_pps_fast_ahb_clk.clkr,
+ [CAM_CC_JPEG_0_CLK] = &cam_cc_jpeg_0_clk.clkr,
+ [CAM_CC_JPEG_1_CLK] = &cam_cc_jpeg_1_clk.clkr,
+ [CAM_CC_JPEG_CLK_SRC] = &cam_cc_jpeg_clk_src.clkr,
+ [CAM_CC_OFE_AHB_CLK] = &cam_cc_ofe_ahb_clk.clkr,
+ [CAM_CC_OFE_ANCHOR_CLK] = &cam_cc_ofe_anchor_clk.clkr,
+ [CAM_CC_OFE_ANCHOR_FAST_AHB_CLK] = &cam_cc_ofe_anchor_fast_ahb_clk.clkr,
+ [CAM_CC_OFE_CLK_SRC] = &cam_cc_ofe_clk_src.clkr,
+ [CAM_CC_OFE_HDR_CLK] = &cam_cc_ofe_hdr_clk.clkr,
+ [CAM_CC_OFE_HDR_FAST_AHB_CLK] = &cam_cc_ofe_hdr_fast_ahb_clk.clkr,
+ [CAM_CC_OFE_MAIN_CLK] = &cam_cc_ofe_main_clk.clkr,
+ [CAM_CC_OFE_MAIN_FAST_AHB_CLK] = &cam_cc_ofe_main_fast_ahb_clk.clkr,
+ [CAM_CC_PLL0] = &cam_cc_pll0.clkr,
+ [CAM_CC_PLL0_OUT_EVEN] = &cam_cc_pll0_out_even.clkr,
+ [CAM_CC_PLL0_OUT_ODD] = &cam_cc_pll0_out_odd.clkr,
+ [CAM_CC_PLL1] = &cam_cc_pll1.clkr,
+ [CAM_CC_PLL1_OUT_EVEN] = &cam_cc_pll1_out_even.clkr,
+ [CAM_CC_PLL2] = &cam_cc_pll2.clkr,
+ [CAM_CC_PLL2_OUT_EVEN] = &cam_cc_pll2_out_even.clkr,
+ [CAM_CC_PLL3] = &cam_cc_pll3.clkr,
+ [CAM_CC_PLL3_OUT_EVEN] = &cam_cc_pll3_out_even.clkr,
+ [CAM_CC_PLL4] = &cam_cc_pll4.clkr,
+ [CAM_CC_PLL4_OUT_EVEN] = &cam_cc_pll4_out_even.clkr,
+ [CAM_CC_PLL5] = &cam_cc_pll5.clkr,
+ [CAM_CC_PLL5_OUT_EVEN] = &cam_cc_pll5_out_even.clkr,
+ [CAM_CC_PLL6] = &cam_cc_pll6.clkr,
+ [CAM_CC_PLL6_OUT_EVEN] = &cam_cc_pll6_out_even.clkr,
+ [CAM_CC_PLL6_OUT_ODD] = &cam_cc_pll6_out_odd.clkr,
+ [CAM_CC_QDSS_DEBUG_CLK] = &cam_cc_qdss_debug_clk.clkr,
+ [CAM_CC_QDSS_DEBUG_CLK_SRC] = &cam_cc_qdss_debug_clk_src.clkr,
+ [CAM_CC_QDSS_DEBUG_XO_CLK] = &cam_cc_qdss_debug_xo_clk.clkr,
+ [CAM_CC_SLEEP_CLK_SRC] = &cam_cc_sleep_clk_src.clkr,
+ [CAM_CC_SLOW_AHB_CLK_SRC] = &cam_cc_slow_ahb_clk_src.clkr,
+ [CAM_CC_TFE_0_BAYER_CLK] = &cam_cc_tfe_0_bayer_clk.clkr,
+ [CAM_CC_TFE_0_BAYER_FAST_AHB_CLK] = &cam_cc_tfe_0_bayer_fast_ahb_clk.clkr,
+ [CAM_CC_TFE_0_CLK_SRC] = &cam_cc_tfe_0_clk_src.clkr,
+ [CAM_CC_TFE_0_MAIN_CLK] = &cam_cc_tfe_0_main_clk.clkr,
+ [CAM_CC_TFE_0_MAIN_FAST_AHB_CLK] = &cam_cc_tfe_0_main_fast_ahb_clk.clkr,
+ [CAM_CC_TFE_1_BAYER_CLK] = &cam_cc_tfe_1_bayer_clk.clkr,
+ [CAM_CC_TFE_1_BAYER_FAST_AHB_CLK] = &cam_cc_tfe_1_bayer_fast_ahb_clk.clkr,
+ [CAM_CC_TFE_1_CLK_SRC] = &cam_cc_tfe_1_clk_src.clkr,
+ [CAM_CC_TFE_1_MAIN_CLK] = &cam_cc_tfe_1_main_clk.clkr,
+ [CAM_CC_TFE_1_MAIN_FAST_AHB_CLK] = &cam_cc_tfe_1_main_fast_ahb_clk.clkr,
+ [CAM_CC_TFE_2_BAYER_CLK] = &cam_cc_tfe_2_bayer_clk.clkr,
+ [CAM_CC_TFE_2_BAYER_FAST_AHB_CLK] = &cam_cc_tfe_2_bayer_fast_ahb_clk.clkr,
+ [CAM_CC_TFE_2_CLK_SRC] = &cam_cc_tfe_2_clk_src.clkr,
+ [CAM_CC_TFE_2_MAIN_CLK] = &cam_cc_tfe_2_main_clk.clkr,
+ [CAM_CC_TFE_2_MAIN_FAST_AHB_CLK] = &cam_cc_tfe_2_main_fast_ahb_clk.clkr,
+ [CAM_CC_XO_CLK_SRC] = &cam_cc_xo_clk_src.clkr,
+};
+
+static struct gdsc *cam_cc_eliza_gdscs[] = {
+ [CAM_CC_IPE_0_GDSC] = &cam_cc_ipe_0_gdsc,
+ [CAM_CC_OFE_GDSC] = &cam_cc_ofe_gdsc,
+ [CAM_CC_TFE_0_GDSC] = &cam_cc_tfe_0_gdsc,
+ [CAM_CC_TFE_1_GDSC] = &cam_cc_tfe_1_gdsc,
+ [CAM_CC_TFE_2_GDSC] = &cam_cc_tfe_2_gdsc,
+ [CAM_CC_TITAN_TOP_GDSC] = &cam_cc_titan_top_gdsc,
+};
+
+static const struct qcom_reset_map cam_cc_eliza_resets[] = {
+ [CAM_CC_DRV_BCR] = { 0x113bc },
+ [CAM_CC_ICP_BCR] = { 0x11210 },
+ [CAM_CC_IPE_0_BCR] = { 0x10178 },
+ [CAM_CC_OFE_BCR] = { 0x100c4 },
+ [CAM_CC_QDSS_DEBUG_BCR] = { 0x11328 },
+ [CAM_CC_TFE_0_BCR] = { 0x11000 },
+ [CAM_CC_TFE_1_BCR] = { 0x11080 },
+ [CAM_CC_TFE_2_BCR] = { 0x110e8 },
+};
+
+static struct clk_alpha_pll *cam_cc_eliza_plls[] = {
+ &cam_cc_pll0,
+ &cam_cc_pll1,
+ &cam_cc_pll2,
+ &cam_cc_pll3,
+ &cam_cc_pll4,
+ &cam_cc_pll5,
+ &cam_cc_pll6,
+};
+
+static u32 cam_cc_eliza_critical_cbcrs[] = {
+ 0x1137c, /* CAM_CC_GDSC_CLK */
+ 0x11398, /* CAM_CC_SLEEP_CLK */
+};
+
+static const struct regmap_config cam_cc_eliza_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x1601c,
+ .fast_io = true,
+};
+
+static struct qcom_cc_driver_data cam_cc_eliza_driver_data = {
+ .alpha_plls = cam_cc_eliza_plls,
+ .num_alpha_plls = ARRAY_SIZE(cam_cc_eliza_plls),
+ .clk_cbcrs = cam_cc_eliza_critical_cbcrs,
+ .num_clk_cbcrs = ARRAY_SIZE(cam_cc_eliza_critical_cbcrs),
+};
+
+static const struct qcom_cc_desc cam_cc_eliza_desc = {
+ .config = &cam_cc_eliza_regmap_config,
+ .clks = cam_cc_eliza_clocks,
+ .num_clks = ARRAY_SIZE(cam_cc_eliza_clocks),
+ .resets = cam_cc_eliza_resets,
+ .num_resets = ARRAY_SIZE(cam_cc_eliza_resets),
+ .gdscs = cam_cc_eliza_gdscs,
+ .num_gdscs = ARRAY_SIZE(cam_cc_eliza_gdscs),
+ .driver_data = &cam_cc_eliza_driver_data,
+};
+
+static const struct of_device_id cam_cc_eliza_match_table[] = {
+ { .compatible = "qcom,eliza-camcc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, cam_cc_eliza_match_table);
+
+static int cam_cc_eliza_probe(struct platform_device *pdev)
+{
+ return qcom_cc_probe(pdev, &cam_cc_eliza_desc);
+}
+
+static struct platform_driver cam_cc_eliza_driver = {
+ .probe = cam_cc_eliza_probe,
+ .driver = {
+ .name = "camcc-eliza",
+ .of_match_table = cam_cc_eliza_match_table,
+ },
+};
+
+module_platform_driver(cam_cc_eliza_driver);
+
+MODULE_DESCRIPTION("QTI CAMCC Eliza Driver");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related
* [PATCH v2 8/8] arm64: dts: qcom: eliza: Add support for MM clock controllers
From: Taniya Das @ 2026-04-09 18:10 UTC (permalink / raw)
To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio, Maxime Coquelin,
Alexandre Torgue
Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm,
linux-clk, devicetree, linux-kernel, linux-stm32,
linux-arm-kernel, Taniya Das
In-Reply-To: <20260409-eliza_mm_cc_v2-v2-0-bc0c6dd77bc5@oss.qualcomm.com>
Add the device nodes for the multimedia clock controllers (cambistmclkcc,
camcc, videocc, gpucc) for Qualcomm Eliza SoC.
Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/eliza.dtsi | 54 +++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/eliza.dtsi b/arch/arm64/boot/dts/qcom/eliza.dtsi
index 4a7a0ac40ce6252a138bed06c7c190ada3ea61a3..7a2a3dba86b9395743781cdf724e81733140ecd0 100644
--- a/arch/arm64/boot/dts/qcom/eliza.dtsi
+++ b/arch/arm64/boot/dts/qcom/eliza.dtsi
@@ -709,6 +709,18 @@ aggre2_noc: interconnect@1700000 {
#interconnect-cells = <2>;
};
+ cambistmclkcc: clock-controller@1760000 {
+ compatible = "qcom,eliza-cambistmclkcc";
+ reg = <0x0 0x01760000 0x0 0x6000>;
+
+ clocks = <&gcc GCC_CAM_BIST_MCLK_AHB_CLK>,
+ <&bi_tcxo_div2>,
+ <&sleep_clk>;
+
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
mmss_noc: interconnect@1780000 {
compatible = "qcom,eliza-mmss-noc";
reg = <0x0 0x01780000 0x0 0x7d800>;
@@ -862,6 +874,23 @@ tcsr: clock-controller@1fbf000 {
#reset-cells = <1>;
};
+ gpucc: clock-controller@3d90000 {
+ compatible = "qcom,eliza-gpucc";
+ reg = <0x0 0x03d90000 0x0 0xa000>;
+
+ clocks = <&bi_tcxo_div2>,
+ <&gcc GCC_GPU_GPLL0_CPH_CLK_SRC>,
+ <&gcc GCC_GPU_GPLL0_DIV_CPH_CLK_SRC>;
+
+ power-domains = <&rpmhpd RPMHPD_MX>,
+ <&rpmhpd RPMHPD_CX>;
+ required-opps = <&rpmhpd_opp_low_svs>,
+ <&rpmhpd_opp_low_svs>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
lpass_ag_noc: interconnect@7e40000 {
compatible = "qcom,eliza-lpass-ag-noc";
reg = <0x0 0x07e40000 0x0 0xe080>;
@@ -883,6 +912,31 @@ lpass_lpicx_noc: interconnect@7420000 {
#interconnect-cells = <2>;
};
+ videocc: clock-controller@aaf0000 {
+ compatible = "qcom,eliza-videocc";
+ reg = <0x0 0xaaf0000 0x0 0x10000>;
+
+ clocks = <&bi_tcxo_div2>,
+ <&sleep_clk>,
+ <&gcc GCC_VIDEO_AHB_CLK>;
+
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
+ camcc: clock-controller@ade0000 {
+ compatible = "qcom,eliza-camcc";
+ reg = <0x0 0x0ade0000 0x0 0x20000>;
+
+ clocks = <&gcc GCC_CAMERA_AHB_CLK>,
+ <&bi_tcxo_div2>,
+ <&sleep_clk>;
+
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
pdc: interrupt-controller@b220000 {
compatible = "qcom,eliza-pdc", "qcom,pdc";
reg = <0x0 0x0b220000 0x0 0x40000>,
--
2.34.1
^ permalink raw reply related
* [PATCH v2 5/8] clk: qcom: gpucc: Add GPU Clock Controller driver for Eliza
From: Taniya Das @ 2026-04-09 18:10 UTC (permalink / raw)
To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio, Maxime Coquelin,
Alexandre Torgue
Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm,
linux-clk, devicetree, linux-kernel, linux-stm32,
linux-arm-kernel, Taniya Das
In-Reply-To: <20260409-eliza_mm_cc_v2-v2-0-bc0c6dd77bc5@oss.qualcomm.com>
Add Graphics Clock Controller (GPUCC) support for Eliza platform.
Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
---
drivers/clk/qcom/Kconfig | 9 +
drivers/clk/qcom/Makefile | 1 +
drivers/clk/qcom/gpucc-eliza.c | 621 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 631 insertions(+)
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 4b0d40a38a6328fe9c41ebb15ae6821012223920..7626dfa536ece08e88ad198d8fa60972f06f14d5 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -37,6 +37,15 @@ config CLK_ELIZA_GCC
Say Y if you want to use peripheral devices such as UART, SPI,
I2C, USB, UFS, SDCC, etc.
+config CLK_ELIZA_GPUCC
+ tristate "Eliza Graphics Clock Controller"
+ depends on ARM64 || COMPILE_TEST
+ select CLK_ELIZA_GCC
+ help
+ Support for the graphics clock controller on Eliza devices.
+ Say Y if you want to support graphics controller devices and
+ functionality such as 3D graphics.
+
config CLK_ELIZA_TCSRCC
tristate "Eliza TCSR Clock Controller"
depends on ARM64 || COMPILE_TEST
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index e7e239c5a0d088b2e78354bf421d871a4e4e6d9d..1c34797eb385963110614ba43eb9bbc9653699fb 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
obj-$(CONFIG_CLK_ELIZA_DISPCC) += dispcc-eliza.o
obj-$(CONFIG_CLK_ELIZA_GCC) += gcc-eliza.o
+obj-$(CONFIG_CLK_ELIZA_GPUCC) += gpucc-eliza.o
obj-$(CONFIG_CLK_ELIZA_TCSRCC) += tcsrcc-eliza.o
obj-$(CONFIG_CLK_ELIZA_VIDEOCC) += videocc-eliza.o
obj-$(CONFIG_CLK_GFM_LPASS_SM8250) += lpass-gfm-sm8250.o
diff --git a/drivers/clk/qcom/gpucc-eliza.c b/drivers/clk/qcom/gpucc-eliza.c
new file mode 100644
index 0000000000000000000000000000000000000000..85ae0ab1184053ce03809176a64f5d47d3a411b9
--- /dev/null
+++ b/drivers/clk/qcom/gpucc-eliza.c
@@ -0,0 +1,621 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,eliza-gpucc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ DT_BI_TCXO,
+ DT_GPLL0_OUT_MAIN,
+ DT_GPLL0_OUT_MAIN_DIV,
+};
+
+enum {
+ P_BI_TCXO,
+ P_BI_TCXO_AO,
+ P_GPLL0_OUT_MAIN,
+ P_GPLL0_OUT_MAIN_DIV,
+ P_GPU_CC_PLL0_OUT_MAIN,
+ P_GPU_CC_PLL1_OUT_MAIN,
+};
+
+static const struct pll_vco lucid_ole_vco[] = {
+ { 249600000, 2300000000, 0 },
+};
+
+/* 518.0 MHz Configuration */
+static const struct alpha_pll_config gpu_cc_pll0_config = {
+ .l = 0x1a,
+ .alpha = 0xfaaa,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll gpu_cc_pll0 = {
+ .offset = 0x0,
+ .config = &gpu_cc_pll0_config,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_pll0",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+/* 440.0 MHz Configuration */
+static const struct alpha_pll_config gpu_cc_pll1_config = {
+ .l = 0x16,
+ .alpha = 0xeaaa,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll gpu_cc_pll1 = {
+ .offset = 0x1000,
+ .config = &gpu_cc_pll1_config,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_pll1",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct parent_map gpu_cc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPLL0_OUT_MAIN, 5 },
+ { P_GPLL0_OUT_MAIN_DIV, 6 },
+};
+
+static const struct clk_parent_data gpu_cc_parent_data_0[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_GPLL0_OUT_MAIN },
+ { .index = DT_GPLL0_OUT_MAIN_DIV },
+};
+
+static const struct parent_map gpu_cc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPU_CC_PLL0_OUT_MAIN, 1 },
+ { P_GPU_CC_PLL1_OUT_MAIN, 3 },
+ { P_GPLL0_OUT_MAIN, 5 },
+ { P_GPLL0_OUT_MAIN_DIV, 6 },
+};
+
+static const struct clk_parent_data gpu_cc_parent_data_1[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gpu_cc_pll0.clkr.hw },
+ { .hw = &gpu_cc_pll1.clkr.hw },
+ { .index = DT_GPLL0_OUT_MAIN },
+ { .index = DT_GPLL0_OUT_MAIN_DIV },
+};
+
+static const struct parent_map gpu_cc_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+ { P_GPU_CC_PLL1_OUT_MAIN, 3 },
+ { P_GPLL0_OUT_MAIN, 5 },
+ { P_GPLL0_OUT_MAIN_DIV, 6 },
+};
+
+static const struct clk_parent_data gpu_cc_parent_data_2[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gpu_cc_pll1.clkr.hw },
+ { .index = DT_GPLL0_OUT_MAIN },
+ { .index = DT_GPLL0_OUT_MAIN_DIV },
+};
+
+static const struct parent_map gpu_cc_parent_map_3[] = {
+ { P_BI_TCXO, 0 },
+};
+
+static const struct clk_parent_data gpu_cc_parent_data_3[] = {
+ { .index = DT_BI_TCXO },
+};
+
+static const struct freq_tbl ftbl_gpu_cc_ff_clk_src[] = {
+ F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gpu_cc_ff_clk_src = {
+ .cmd_rcgr = 0x94b8,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gpu_cc_parent_map_0,
+ .freq_tbl = ftbl_gpu_cc_ff_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_ff_clk_src",
+ .parent_data = gpu_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = {
+ F(220000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0),
+ F(550000000, P_GPU_CC_PLL1_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gpu_cc_gmu_clk_src = {
+ .cmd_rcgr = 0x935c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gpu_cc_parent_map_1,
+ .freq_tbl = ftbl_gpu_cc_gmu_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_gmu_clk_src",
+ .parent_data = gpu_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 gpu_cc_hub_clk_src = {
+ .cmd_rcgr = 0x9430,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gpu_cc_parent_map_2,
+ .freq_tbl = ftbl_gpu_cc_ff_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_hub_clk_src",
+ .parent_data = gpu_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gpu_cc_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gpu_cc_xo_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gpu_cc_xo_clk_src = {
+ .cmd_rcgr = 0x9010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gpu_cc_parent_map_3,
+ .freq_tbl = ftbl_gpu_cc_xo_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_xo_clk_src",
+ .parent_data = gpu_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(gpu_cc_parent_data_3),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_regmap_div gpu_cc_xo_div_clk_src = {
+ .reg = 0x9050,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_xo_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_branch gpu_cc_ahb_clk = {
+ .halt_reg = 0x914c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x914c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_hub_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_crc_ahb_clk = {
+ .halt_reg = 0x9150,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x9150,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_crc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_hub_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cx_accu_shift_clk = {
+ .halt_reg = 0x9480,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x9480,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_cx_accu_shift_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cx_ff_clk = {
+ .halt_reg = 0x9184,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x9184,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_cx_ff_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_ff_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cx_gmu_clk = {
+ .halt_reg = 0x916c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x916c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_cx_gmu_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_gmu_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_cxo_clk = {
+ .halt_reg = 0x917c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x917c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_cxo_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_freq_measure_clk = {
+ .halt_reg = 0x9008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x9008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_freq_measure_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_xo_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_gpu_smmu_vote_clk = {
+ .halt_reg = 0x7000,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_gpu_smmu_vote_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = {
+ .halt_reg = 0x7000,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x7000,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_hlos1_vote_gpu_smmu_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_hub_aon_clk = {
+ .halt_reg = 0x942c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x942c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_hub_aon_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_hub_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_hub_cx_int_clk = {
+ .halt_reg = 0x9180,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x9180,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_hub_cx_int_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &gpu_cc_hub_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_memnoc_gfx_clk = {
+ .halt_reg = 0x9188,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x9188,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_memnoc_gfx_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_mnd1x_0_gfx3d_clk = {
+ .halt_reg = 0x92cc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x92cc,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_mnd1x_0_gfx3d_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_mnd1x_1_gfx3d_clk = {
+ .halt_reg = 0x92d0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x92d0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_mnd1x_1_gfx3d_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gpu_cc_sleep_clk = {
+ .halt_reg = 0x9164,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x9164,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "gpu_cc_sleep_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc gpu_cc_cx_gdsc = {
+ .gdscr = 0x9110,
+ .gds_hw_ctrl = 0x9124,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0x8,
+ .pd = {
+ .name = "gpu_cc_cx_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = VOTABLE | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc gpu_cc_gx_gdsc = {
+ .gdscr = 0x905c,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "gpu_cc_gx_gdsc",
+ .power_on = gdsc_gx_do_nothing_enable,
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct clk_regmap *gpu_cc_eliza_clocks[] = {
+ [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr,
+ [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr,
+ [GPU_CC_CX_ACCU_SHIFT_CLK] = &gpu_cc_cx_accu_shift_clk.clkr,
+ [GPU_CC_CX_FF_CLK] = &gpu_cc_cx_ff_clk.clkr,
+ [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr,
+ [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
+ [GPU_CC_FF_CLK_SRC] = &gpu_cc_ff_clk_src.clkr,
+ [GPU_CC_FREQ_MEASURE_CLK] = &gpu_cc_freq_measure_clk.clkr,
+ [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
+ [GPU_CC_GPU_SMMU_VOTE_CLK] = &gpu_cc_gpu_smmu_vote_clk.clkr,
+ [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr,
+ [GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr,
+ [GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr,
+ [GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr,
+ [GPU_CC_MEMNOC_GFX_CLK] = &gpu_cc_memnoc_gfx_clk.clkr,
+ [GPU_CC_MND1X_0_GFX3D_CLK] = &gpu_cc_mnd1x_0_gfx3d_clk.clkr,
+ [GPU_CC_MND1X_1_GFX3D_CLK] = &gpu_cc_mnd1x_1_gfx3d_clk.clkr,
+ [GPU_CC_PLL0] = &gpu_cc_pll0.clkr,
+ [GPU_CC_PLL1] = &gpu_cc_pll1.clkr,
+ [GPU_CC_SLEEP_CLK] = &gpu_cc_sleep_clk.clkr,
+ [GPU_CC_XO_CLK_SRC] = &gpu_cc_xo_clk_src.clkr,
+ [GPU_CC_XO_DIV_CLK_SRC] = &gpu_cc_xo_div_clk_src.clkr,
+};
+
+static struct gdsc *gpu_cc_eliza_gdscs[] = {
+ [GPU_CC_CX_GDSC] = &gpu_cc_cx_gdsc,
+ [GPU_CC_GX_GDSC] = &gpu_cc_gx_gdsc,
+};
+
+static const struct qcom_reset_map gpu_cc_eliza_resets[] = {
+ [GPU_CC_ACD_BCR] = { 0x939c },
+ [GPU_CC_CB_BCR] = { 0x93e4 },
+ [GPU_CC_CX_BCR] = { 0x910c },
+ [GPU_CC_FAST_HUB_BCR] = { 0x9428 },
+ [GPU_CC_FF_BCR] = { 0x94b4 },
+ [GPU_CC_GFX3D_AON_BCR] = { 0x91dc },
+ [GPU_CC_GMU_BCR] = { 0x9358 },
+ [GPU_CC_GX_BCR] = { 0x9058 },
+ [GPU_CC_RBCPR_BCR] = { 0x9224 },
+ [GPU_CC_XO_BCR] = { 0x9000 },
+};
+
+static struct clk_alpha_pll *gpu_cc_eliza_plls[] = {
+ &gpu_cc_pll0,
+ &gpu_cc_pll1,
+};
+
+static u32 gpu_cc_eliza_critical_cbcrs[] = {
+ 0x9004, /* GPU_CC_CXO_AON_CLK */
+ 0x900c, /* GPU_CC_DEMET_CLK */
+};
+
+static const struct regmap_config gpu_cc_eliza_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x9988,
+ .fast_io = true,
+};
+
+static struct qcom_cc_driver_data gpu_cc_eliza_driver_data = {
+ .alpha_plls = gpu_cc_eliza_plls,
+ .num_alpha_plls = ARRAY_SIZE(gpu_cc_eliza_plls),
+ .clk_cbcrs = gpu_cc_eliza_critical_cbcrs,
+ .num_clk_cbcrs = ARRAY_SIZE(gpu_cc_eliza_critical_cbcrs),
+};
+
+static const struct qcom_cc_desc gpu_cc_eliza_desc = {
+ .config = &gpu_cc_eliza_regmap_config,
+ .clks = gpu_cc_eliza_clocks,
+ .num_clks = ARRAY_SIZE(gpu_cc_eliza_clocks),
+ .resets = gpu_cc_eliza_resets,
+ .num_resets = ARRAY_SIZE(gpu_cc_eliza_resets),
+ .gdscs = gpu_cc_eliza_gdscs,
+ .num_gdscs = ARRAY_SIZE(gpu_cc_eliza_gdscs),
+ .use_rpm = true,
+ .driver_data = &gpu_cc_eliza_driver_data,
+};
+
+static const struct of_device_id gpu_cc_eliza_match_table[] = {
+ { .compatible = "qcom,eliza-gpucc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gpu_cc_eliza_match_table);
+
+static int gpu_cc_eliza_probe(struct platform_device *pdev)
+{
+ return qcom_cc_probe(pdev, &gpu_cc_eliza_desc);
+}
+
+static struct platform_driver gpu_cc_eliza_driver = {
+ .probe = gpu_cc_eliza_probe,
+ .driver = {
+ .name = "gpucc-eliza",
+ .of_match_table = gpu_cc_eliza_match_table,
+ },
+};
+
+module_platform_driver(gpu_cc_eliza_driver);
+
+MODULE_DESCRIPTION("QTI GPUCC Eliza Driver");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related
* [PATCH v2 7/8] arm64: defconfig: Enable clock controllers on Qualcomm Eliza SoC
From: Taniya Das @ 2026-04-09 18:10 UTC (permalink / raw)
To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio, Maxime Coquelin,
Alexandre Torgue
Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm,
linux-clk, devicetree, linux-kernel, linux-stm32,
linux-arm-kernel, Taniya Das
In-Reply-To: <20260409-eliza_mm_cc_v2-v2-0-bc0c6dd77bc5@oss.qualcomm.com>
Enable the video, camera and gpu clock controllers for their respective
functionalities on the Qualcomm Eliza MTP board.
Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
---
arch/arm64/configs/defconfig | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index dd1ac01ee29bf631d517c38486f6896ffd82dcc9..130e8716e67d69c54cde3f66db09b352f736feaf 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1475,9 +1475,12 @@ CONFIG_COMMON_CLK_MT8192_SCP_ADSP=y
CONFIG_COMMON_CLK_MT8192_VDECSYS=y
CONFIG_COMMON_CLK_MT8192_VENCSYS=y
CONFIG_COMMON_CLK_QCOM=y
+CONFIG_CLK_ELIZA_CAMCC=m
CONFIG_CLK_ELIZA_DISPCC=m
CONFIG_CLK_ELIZA_GCC=y
+CONFIG_CLK_ELIZA_GPUCC=m
CONFIG_CLK_ELIZA_TCSRCC=m
+CONFIG_CLK_ELIZA_VIDEOCC=m
CONFIG_CLK_GLYMUR_DISPCC=m
CONFIG_CLK_GLYMUR_GCC=y
CONFIG_CLK_GLYMUR_TCSRCC=m
--
2.34.1
^ permalink raw reply related
* [PATCH v2 4/8] clk: qcom: videocc: Add video clock controller driver for Eliza
From: Taniya Das @ 2026-04-09 18:10 UTC (permalink / raw)
To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio, Maxime Coquelin,
Alexandre Torgue
Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm,
linux-clk, devicetree, linux-kernel, linux-stm32,
linux-arm-kernel, Taniya Das, Konrad Dybcio
In-Reply-To: <20260409-eliza_mm_cc_v2-v2-0-bc0c6dd77bc5@oss.qualcomm.com>
Add support for the video clock controller for video clients to be able
to request for videocc clocks on Eliza platform.
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
---
drivers/clk/qcom/Kconfig | 9 +
drivers/clk/qcom/Makefile | 1 +
drivers/clk/qcom/videocc-eliza.c | 403 +++++++++++++++++++++++++++++++++++++++
3 files changed, 413 insertions(+)
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 22eb80be60ad3bde897f2c507ac9897951fbb8fe..4b0d40a38a6328fe9c41ebb15ae6821012223920 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -45,6 +45,15 @@ config CLK_ELIZA_TCSRCC
Support for the TCSR clock controller on Eliza devices.
Say Y if you want to use peripheral devices such as USB/PCIe/UFS.
+config CLK_ELIZA_VIDEOCC
+ tristate "Eliza Video Clock Controller"
+ depends on ARM64 || COMPILE_TEST
+ select CLK_GLYMUR_GCC
+ help
+ Support for the video clock controller on Eliza devices.
+ Say Y if you want to support video devices and functionality such as
+ video encode and decode.
+
config CLK_GLYMUR_DISPCC
tristate "Glymur Display Clock Controller"
depends on ARM64 || COMPILE_TEST
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index b818fd5af8bfb85a51ee90fdc3baa93af30dc39a..e7e239c5a0d088b2e78354bf421d871a4e4e6d9d 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
obj-$(CONFIG_CLK_ELIZA_DISPCC) += dispcc-eliza.o
obj-$(CONFIG_CLK_ELIZA_GCC) += gcc-eliza.o
obj-$(CONFIG_CLK_ELIZA_TCSRCC) += tcsrcc-eliza.o
+obj-$(CONFIG_CLK_ELIZA_VIDEOCC) += videocc-eliza.o
obj-$(CONFIG_CLK_GFM_LPASS_SM8250) += lpass-gfm-sm8250.o
obj-$(CONFIG_CLK_GLYMUR_DISPCC) += dispcc-glymur.o
obj-$(CONFIG_CLK_GLYMUR_GCC) += gcc-glymur.o
diff --git a/drivers/clk/qcom/videocc-eliza.c b/drivers/clk/qcom/videocc-eliza.c
new file mode 100644
index 0000000000000000000000000000000000000000..cb541cfec50c12761251a822e32094e763922cdb
--- /dev/null
+++ b/drivers/clk/qcom/videocc-eliza.c
@@ -0,0 +1,403 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,eliza-videocc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-regmap.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ DT_BI_TCXO,
+ DT_SLEEP_CLK,
+ DT_AHB_CLK,
+};
+
+enum {
+ P_BI_TCXO,
+ P_SLEEP_CLK,
+ P_VIDEO_CC_PLL0_OUT_MAIN,
+};
+
+static const struct pll_vco lucid_ole_vco[] = {
+ { 249600000, 2300000000, 0 },
+};
+
+/* 576.0 MHz Configuration */
+static const struct alpha_pll_config video_cc_pll0_config = {
+ .l = 0x1e,
+ .alpha = 0x0,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00182261,
+ .config_ctl_hi1_val = 0x82aa299c,
+ .test_ctl_val = 0x00000000,
+ .test_ctl_hi_val = 0x00000003,
+ .test_ctl_hi1_val = 0x00009000,
+ .test_ctl_hi2_val = 0x00000034,
+ .user_ctl_val = 0x00000000,
+ .user_ctl_hi_val = 0x00000005,
+};
+
+static struct clk_alpha_pll video_cc_pll0 = {
+ .offset = 0x0,
+ .config = &video_cc_pll0_config,
+ .vco_table = lucid_ole_vco,
+ .num_vco = ARRAY_SIZE(lucid_ole_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_pll0",
+ .parent_data = &(const struct clk_parent_data) {
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_evo_ops,
+ },
+ },
+};
+
+static const struct parent_map video_cc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+};
+
+static const struct clk_parent_data video_cc_parent_data_0[] = {
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map video_cc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_VIDEO_CC_PLL0_OUT_MAIN, 1 },
+};
+
+static const struct clk_parent_data video_cc_parent_data_1[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &video_cc_pll0.clkr.hw },
+};
+
+static const struct parent_map video_cc_parent_map_2[] = {
+ { P_SLEEP_CLK, 0 },
+};
+
+static const struct clk_parent_data video_cc_parent_data_2[] = {
+ { .index = DT_SLEEP_CLK },
+};
+
+static const struct freq_tbl ftbl_video_cc_ahb_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 video_cc_ahb_clk_src = {
+ .cmd_rcgr = 0x8018,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_0,
+ .freq_tbl = ftbl_video_cc_ahb_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_ahb_clk_src",
+ .parent_data = video_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(video_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = {
+ F(576000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(633000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(720000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1014000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1098000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1113000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1332000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ F(1600000000, P_VIDEO_CC_PLL0_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 video_cc_mvs0_clk_src = {
+ .cmd_rcgr = 0x8000,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_1,
+ .freq_tbl = ftbl_video_cc_mvs0_clk_src,
+ .hw_clk_ctrl = true,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0_clk_src",
+ .parent_data = video_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(video_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_video_cc_sleep_clk_src[] = {
+ F(32000, P_SLEEP_CLK, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 video_cc_sleep_clk_src = {
+ .cmd_rcgr = 0x8110,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_2,
+ .freq_tbl = ftbl_video_cc_sleep_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_sleep_clk_src",
+ .parent_data = video_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(video_cc_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 video_cc_xo_clk_src = {
+ .cmd_rcgr = 0x80f4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = video_cc_parent_map_0,
+ .freq_tbl = ftbl_video_cc_ahb_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_xo_clk_src",
+ .parent_data = video_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(video_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_regmap_div video_cc_mvs0_div_clk_src = {
+ .reg = 0x80ac,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src = {
+ .reg = 0x8058,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0c_div2_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_branch video_cc_mvs0_clk = {
+ .halt_reg = 0x80a0,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x80a0,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x80a0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs0_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvs0_shift_clk = {
+ .halt_reg = 0x8144,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x8144,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x8144,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0_shift_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvs0c_clk = {
+ .halt_reg = 0x804c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x804c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0c_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_mvs0c_div2_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch video_cc_mvs0c_shift_clk = {
+ .halt_reg = 0x8148,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x8148,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x8148,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "video_cc_mvs0c_shift_clk",
+ .parent_hws = (const struct clk_hw*[]) {
+ &video_cc_xo_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc video_cc_mvs0c_gdsc = {
+ .gdscr = 0x8034,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0x6,
+ .pd = {
+ .name = "video_cc_mvs0c_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE,
+};
+
+static struct gdsc video_cc_mvs0_gdsc = {
+ .gdscr = 0x808c,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0x6,
+ .pd = {
+ .name = "video_cc_mvs0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .parent = &video_cc_mvs0c_gdsc.pd,
+ .flags = POLL_CFG_GDSCR | RETAIN_FF_ENABLE | HW_CTRL_TRIGGER,
+};
+
+static struct clk_regmap *video_cc_eliza_clocks[] = {
+ [VIDEO_CC_AHB_CLK_SRC] = &video_cc_ahb_clk_src.clkr,
+ [VIDEO_CC_MVS0_CLK] = &video_cc_mvs0_clk.clkr,
+ [VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr,
+ [VIDEO_CC_MVS0_DIV_CLK_SRC] = &video_cc_mvs0_div_clk_src.clkr,
+ [VIDEO_CC_MVS0_SHIFT_CLK] = &video_cc_mvs0_shift_clk.clkr,
+ [VIDEO_CC_MVS0C_CLK] = &video_cc_mvs0c_clk.clkr,
+ [VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC] = &video_cc_mvs0c_div2_div_clk_src.clkr,
+ [VIDEO_CC_MVS0C_SHIFT_CLK] = &video_cc_mvs0c_shift_clk.clkr,
+ [VIDEO_CC_PLL0] = &video_cc_pll0.clkr,
+ [VIDEO_CC_SLEEP_CLK_SRC] = &video_cc_sleep_clk_src.clkr,
+ [VIDEO_CC_XO_CLK_SRC] = &video_cc_xo_clk_src.clkr,
+};
+
+static struct gdsc *video_cc_eliza_gdscs[] = {
+ [VIDEO_CC_MVS0_GDSC] = &video_cc_mvs0_gdsc,
+ [VIDEO_CC_MVS0C_GDSC] = &video_cc_mvs0c_gdsc,
+};
+
+static const struct qcom_reset_map video_cc_eliza_resets[] = {
+ [VIDEO_CC_INTERFACE_BCR] = { 0x80d8 },
+ [VIDEO_CC_MVS0_CLK_ARES] = { 0x80a0, 2 },
+ [VIDEO_CC_MVS0_BCR] = { 0x8088 },
+ [VIDEO_CC_MVS0C_CLK_ARES] = { 0x804c, 2 },
+ [VIDEO_CC_MVS0C_BCR] = { 0x8030 },
+ [VIDEO_CC_XO_CLK_ARES] = { 0x810c, 2 },
+};
+
+static struct clk_alpha_pll *video_cc_eliza_plls[] = {
+ &video_cc_pll0,
+};
+
+static u32 video_cc_eliza_critical_cbcrs[] = {
+ 0x80dc, /* VIDEO_CC_AHB_CLK */
+ 0x8128, /* VIDEO_CC_SLEEP_CLK */
+ 0x810c, /* VIDEO_CC_XO_CLK */
+};
+
+static const struct regmap_config video_cc_eliza_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x9f50,
+ .fast_io = true,
+};
+
+static struct qcom_cc_driver_data video_cc_eliza_driver_data = {
+ .alpha_plls = video_cc_eliza_plls,
+ .num_alpha_plls = ARRAY_SIZE(video_cc_eliza_plls),
+ .clk_cbcrs = video_cc_eliza_critical_cbcrs,
+ .num_clk_cbcrs = ARRAY_SIZE(video_cc_eliza_critical_cbcrs),
+};
+
+static const struct qcom_cc_desc video_cc_eliza_desc = {
+ .config = &video_cc_eliza_regmap_config,
+ .clks = video_cc_eliza_clocks,
+ .num_clks = ARRAY_SIZE(video_cc_eliza_clocks),
+ .resets = video_cc_eliza_resets,
+ .num_resets = ARRAY_SIZE(video_cc_eliza_resets),
+ .gdscs = video_cc_eliza_gdscs,
+ .num_gdscs = ARRAY_SIZE(video_cc_eliza_gdscs),
+ .driver_data = &video_cc_eliza_driver_data,
+};
+
+static const struct of_device_id video_cc_eliza_match_table[] = {
+ { .compatible = "qcom,eliza-videocc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, video_cc_eliza_match_table);
+
+static int video_cc_eliza_probe(struct platform_device *pdev)
+{
+ return qcom_cc_probe(pdev, &video_cc_eliza_desc);
+}
+
+static struct platform_driver video_cc_eliza_driver = {
+ .probe = video_cc_eliza_probe,
+ .driver = {
+ .name = "videocc-eliza",
+ .of_match_table = video_cc_eliza_match_table,
+ },
+};
+
+module_platform_driver(video_cc_eliza_driver);
+
+MODULE_DESCRIPTION("QTI VIDEOCC Eliza Driver");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related
* [PATCH v2 3/8] dt-bindings: clock: qcom: Add support for CAMCC for Eliza
From: Taniya Das @ 2026-04-09 18:10 UTC (permalink / raw)
To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio, Maxime Coquelin,
Alexandre Torgue
Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm,
linux-clk, devicetree, linux-kernel, linux-stm32,
linux-arm-kernel, Taniya Das
In-Reply-To: <20260409-eliza_mm_cc_v2-v2-0-bc0c6dd77bc5@oss.qualcomm.com>
Update the compatible and the bindings for CAMCC support on Eliza SoC.
Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
---
.../bindings/clock/qcom,eliza-camcc.yaml | 55 ++++++++
.../dt-bindings/clock/qcom,eliza-cambistmclkcc.h | 32 +++++
include/dt-bindings/clock/qcom,eliza-camcc.h | 151 +++++++++++++++++++++
3 files changed, 238 insertions(+)
diff --git a/Documentation/devicetree/bindings/clock/qcom,eliza-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,eliza-camcc.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..8f7c73707f713eba2e0938fcacbc5542e2de0892
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,eliza-camcc.yaml
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,eliza-camcc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Camera Clock & Reset Controller on Eliza
+
+maintainers:
+ - Taniya Das <taniya.das@oss.qualcomm.com>
+
+description: |
+ Qualcomm camera clock control module provides the clocks, resets and power
+ domains on Eliza.
+
+ See also:
+ include/dt-bindings/clock/qcom,eliza-camcc.h
+ include/dt-bindings/clock/qcom,eliza-cambistmclkcc.h
+
+properties:
+ compatible:
+ enum:
+ - qcom,eliza-cambistmclkcc
+ - qcom,eliza-camcc
+
+ clocks:
+ items:
+ - description: Camera AHB clock from GCC
+ - description: Board XO source
+ - description: Sleep clock source
+
+required:
+ - compatible
+ - clocks
+
+allOf:
+ - $ref: qcom,gcc.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,eliza-gcc.h>
+ clock-controller@adb0000 {
+ compatible = "qcom,eliza-camcc";
+ reg = <0x0adb0000 0x40000>;
+ clocks = <&bi_tcxo_div2>,
+ <&sleep_clk>,
+ <&gcc GCC_CAMERA_AHB_CLK>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
+...
diff --git a/include/dt-bindings/clock/qcom,eliza-cambistmclkcc.h b/include/dt-bindings/clock/qcom,eliza-cambistmclkcc.h
new file mode 100644
index 0000000000000000000000000000000000000000..7b8b285f18d2714393885149fc97c715b3fbb042
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,eliza-cambistmclkcc.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_CAM_BIST_MCLK_CC_ELIZA_H
+#define _DT_BINDINGS_CLK_QCOM_CAM_BIST_MCLK_CC_ELIZA_H
+
+/* CAM_BIST_MCLK_CC clocks */
+#define CAM_BIST_MCLK_CC_MCLK0_CLK 0
+#define CAM_BIST_MCLK_CC_MCLK0_CLK_SRC 1
+#define CAM_BIST_MCLK_CC_MCLK1_CLK 2
+#define CAM_BIST_MCLK_CC_MCLK1_CLK_SRC 3
+#define CAM_BIST_MCLK_CC_MCLK2_CLK 4
+#define CAM_BIST_MCLK_CC_MCLK2_CLK_SRC 5
+#define CAM_BIST_MCLK_CC_MCLK3_CLK 6
+#define CAM_BIST_MCLK_CC_MCLK3_CLK_SRC 7
+#define CAM_BIST_MCLK_CC_MCLK4_CLK 8
+#define CAM_BIST_MCLK_CC_MCLK4_CLK_SRC 9
+#define CAM_BIST_MCLK_CC_MCLK5_CLK 10
+#define CAM_BIST_MCLK_CC_MCLK5_CLK_SRC 11
+#define CAM_BIST_MCLK_CC_MCLK6_CLK 12
+#define CAM_BIST_MCLK_CC_MCLK6_CLK_SRC 13
+#define CAM_BIST_MCLK_CC_MCLK7_CLK 14
+#define CAM_BIST_MCLK_CC_MCLK7_CLK_SRC 15
+#define CAM_BIST_MCLK_CC_PLL0 16
+#define CAM_BIST_MCLK_CC_PLL_TEST_CLK 17
+#define CAM_BIST_MCLK_CC_PLL_TEST_DIV_CLK_SRC 18
+#define CAM_BIST_MCLK_CC_SLEEP_CLK 19
+#define CAM_BIST_MCLK_CC_SLEEP_CLK_SRC 20
+
+#endif
diff --git a/include/dt-bindings/clock/qcom,eliza-camcc.h b/include/dt-bindings/clock/qcom,eliza-camcc.h
new file mode 100644
index 0000000000000000000000000000000000000000..d85ef9777d08d12ec349d57f6da5e76a305404f8
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,eliza-camcc.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_CAM_CC_ELIZA_H
+#define _DT_BINDINGS_CLK_QCOM_CAM_CC_ELIZA_H
+
+/* CAM_CC clocks */
+#define CAM_CC_CAM_TOP_AHB_CLK 0
+#define CAM_CC_CAM_TOP_FAST_AHB_CLK 1
+#define CAM_CC_CAMNOC_DCD_XO_CLK 2
+#define CAM_CC_CAMNOC_NRT_AXI_CLK 3
+#define CAM_CC_CAMNOC_NRT_CRE_CLK 4
+#define CAM_CC_CAMNOC_NRT_IPE_NPS_CLK 5
+#define CAM_CC_CAMNOC_NRT_OFE_ANCHOR_CLK 6
+#define CAM_CC_CAMNOC_NRT_OFE_HDR_CLK 7
+#define CAM_CC_CAMNOC_NRT_OFE_MAIN_CLK 8
+#define CAM_CC_CAMNOC_RT_AXI_CLK 9
+#define CAM_CC_CAMNOC_RT_AXI_CLK_SRC 10
+#define CAM_CC_CAMNOC_RT_IFE_LITE_CLK 11
+#define CAM_CC_CAMNOC_RT_TFE_0_BAYER_CLK 12
+#define CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK 13
+#define CAM_CC_CAMNOC_RT_TFE_1_BAYER_CLK 14
+#define CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK 15
+#define CAM_CC_CAMNOC_RT_TFE_2_BAYER_CLK 16
+#define CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK 17
+#define CAM_CC_CAMNOC_XO_CLK 18
+#define CAM_CC_CCI_0_CLK 19
+#define CAM_CC_CCI_0_CLK_SRC 20
+#define CAM_CC_CCI_1_CLK 21
+#define CAM_CC_CCI_1_CLK_SRC 22
+#define CAM_CC_CCI_2_CLK 23
+#define CAM_CC_CCI_2_CLK_SRC 24
+#define CAM_CC_CORE_AHB_CLK 25
+#define CAM_CC_CPHY_RX_CLK_SRC 26
+#define CAM_CC_CRE_AHB_CLK 27
+#define CAM_CC_CRE_CLK 28
+#define CAM_CC_CRE_CLK_SRC 29
+#define CAM_CC_CSI0PHYTIMER_CLK 30
+#define CAM_CC_CSI0PHYTIMER_CLK_SRC 31
+#define CAM_CC_CSI1PHYTIMER_CLK 32
+#define CAM_CC_CSI1PHYTIMER_CLK_SRC 33
+#define CAM_CC_CSI2PHYTIMER_CLK 34
+#define CAM_CC_CSI2PHYTIMER_CLK_SRC 35
+#define CAM_CC_CSI3PHYTIMER_CLK 36
+#define CAM_CC_CSI3PHYTIMER_CLK_SRC 37
+#define CAM_CC_CSI4PHYTIMER_CLK 38
+#define CAM_CC_CSI4PHYTIMER_CLK_SRC 39
+#define CAM_CC_CSI5PHYTIMER_CLK 40
+#define CAM_CC_CSI5PHYTIMER_CLK_SRC 41
+#define CAM_CC_CSID_CLK 42
+#define CAM_CC_CSID_CLK_SRC 43
+#define CAM_CC_CSID_CSIPHY_RX_CLK 44
+#define CAM_CC_CSIPHY0_CLK 45
+#define CAM_CC_CSIPHY1_CLK 46
+#define CAM_CC_CSIPHY2_CLK 47
+#define CAM_CC_CSIPHY3_CLK 48
+#define CAM_CC_CSIPHY4_CLK 49
+#define CAM_CC_CSIPHY5_CLK 50
+#define CAM_CC_DRV_AHB_CLK 51
+#define CAM_CC_DRV_XO_CLK 52
+#define CAM_CC_FAST_AHB_CLK_SRC 53
+#define CAM_CC_GDSC_CLK 54
+#define CAM_CC_ICP_0_AHB_CLK 55
+#define CAM_CC_ICP_0_CLK 56
+#define CAM_CC_ICP_0_CLK_SRC 57
+#define CAM_CC_ICP_1_AHB_CLK 58
+#define CAM_CC_ICP_1_CLK 59
+#define CAM_CC_ICP_1_CLK_SRC 60
+#define CAM_CC_IFE_LITE_AHB_CLK 61
+#define CAM_CC_IFE_LITE_CLK 62
+#define CAM_CC_IFE_LITE_CLK_SRC 63
+#define CAM_CC_IFE_LITE_CPHY_RX_CLK 64
+#define CAM_CC_IFE_LITE_CSID_CLK 65
+#define CAM_CC_IFE_LITE_CSID_CLK_SRC 66
+#define CAM_CC_IPE_NPS_AHB_CLK 67
+#define CAM_CC_IPE_NPS_CLK 68
+#define CAM_CC_IPE_NPS_CLK_SRC 69
+#define CAM_CC_IPE_NPS_FAST_AHB_CLK 70
+#define CAM_CC_IPE_PPS_CLK 71
+#define CAM_CC_IPE_PPS_FAST_AHB_CLK 72
+#define CAM_CC_JPEG_0_CLK 73
+#define CAM_CC_JPEG_1_CLK 74
+#define CAM_CC_JPEG_CLK_SRC 75
+#define CAM_CC_OFE_AHB_CLK 76
+#define CAM_CC_OFE_ANCHOR_CLK 77
+#define CAM_CC_OFE_ANCHOR_FAST_AHB_CLK 78
+#define CAM_CC_OFE_CLK_SRC 79
+#define CAM_CC_OFE_HDR_CLK 80
+#define CAM_CC_OFE_HDR_FAST_AHB_CLK 81
+#define CAM_CC_OFE_MAIN_CLK 82
+#define CAM_CC_OFE_MAIN_FAST_AHB_CLK 83
+#define CAM_CC_PLL0 84
+#define CAM_CC_PLL0_OUT_EVEN 85
+#define CAM_CC_PLL0_OUT_ODD 86
+#define CAM_CC_PLL1 87
+#define CAM_CC_PLL1_OUT_EVEN 88
+#define CAM_CC_PLL2 89
+#define CAM_CC_PLL2_OUT_EVEN 90
+#define CAM_CC_PLL3 91
+#define CAM_CC_PLL3_OUT_EVEN 92
+#define CAM_CC_PLL4 93
+#define CAM_CC_PLL4_OUT_EVEN 94
+#define CAM_CC_PLL5 95
+#define CAM_CC_PLL5_OUT_EVEN 96
+#define CAM_CC_PLL6 97
+#define CAM_CC_PLL6_OUT_EVEN 98
+#define CAM_CC_PLL6_OUT_ODD 99
+#define CAM_CC_QDSS_DEBUG_CLK 100
+#define CAM_CC_QDSS_DEBUG_CLK_SRC 101
+#define CAM_CC_QDSS_DEBUG_XO_CLK 102
+#define CAM_CC_SLEEP_CLK 103
+#define CAM_CC_SLEEP_CLK_SRC 104
+#define CAM_CC_SLOW_AHB_CLK_SRC 105
+#define CAM_CC_TFE_0_BAYER_CLK 106
+#define CAM_CC_TFE_0_BAYER_FAST_AHB_CLK 107
+#define CAM_CC_TFE_0_CLK_SRC 108
+#define CAM_CC_TFE_0_MAIN_CLK 109
+#define CAM_CC_TFE_0_MAIN_FAST_AHB_CLK 110
+#define CAM_CC_TFE_1_BAYER_CLK 111
+#define CAM_CC_TFE_1_BAYER_FAST_AHB_CLK 112
+#define CAM_CC_TFE_1_CLK_SRC 113
+#define CAM_CC_TFE_1_MAIN_CLK 114
+#define CAM_CC_TFE_1_MAIN_FAST_AHB_CLK 115
+#define CAM_CC_TFE_2_BAYER_CLK 116
+#define CAM_CC_TFE_2_BAYER_FAST_AHB_CLK 117
+#define CAM_CC_TFE_2_CLK_SRC 118
+#define CAM_CC_TFE_2_MAIN_CLK 119
+#define CAM_CC_TFE_2_MAIN_FAST_AHB_CLK 120
+#define CAM_CC_XO_CLK_SRC 121
+
+/* CAM_CC power domains */
+#define CAM_CC_IPE_0_GDSC 0
+#define CAM_CC_OFE_GDSC 1
+#define CAM_CC_TFE_0_GDSC 2
+#define CAM_CC_TFE_1_GDSC 3
+#define CAM_CC_TFE_2_GDSC 4
+#define CAM_CC_TITAN_TOP_GDSC 5
+
+/* CAM_CC resets */
+#define CAM_CC_DRV_BCR 0
+#define CAM_CC_ICP_BCR 1
+#define CAM_CC_IPE_0_BCR 2
+#define CAM_CC_OFE_BCR 3
+#define CAM_CC_QDSS_DEBUG_BCR 4
+#define CAM_CC_TFE_0_BCR 5
+#define CAM_CC_TFE_1_BCR 6
+#define CAM_CC_TFE_2_BCR 7
+
+#endif
--
2.34.1
^ permalink raw reply related
* [PATCH v2 2/8] dt-bindings: clock: qcom: document the Eliza GPU Clock Controller
From: Taniya Das @ 2026-04-09 18:10 UTC (permalink / raw)
To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio, Maxime Coquelin,
Alexandre Torgue
Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm,
linux-clk, devicetree, linux-kernel, linux-stm32,
linux-arm-kernel, Taniya Das
In-Reply-To: <20260409-eliza_mm_cc_v2-v2-0-bc0c6dd77bc5@oss.qualcomm.com>
Add bindings documentation for the Eliza Graphics Clock Controller.
Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
---
.../bindings/clock/qcom,sm8450-gpucc.yaml | 3 ++
include/dt-bindings/clock/qcom,eliza-gpucc.h | 52 ++++++++++++++++++++++
2 files changed, 55 insertions(+)
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml
index fdbdf605ee695637512ce4f98c9b6fcfacb9154f..734bab762a30800bda94c726f48013679f9ec542 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sm8450-gpucc.yaml
@@ -15,6 +15,7 @@ description: |
domains on Qualcomm SoCs.
See also:
+ include/dt-bindings/clock/qcom,eliza-gpucc.h
include/dt-bindings/clock/qcom,glymur-gpucc.h
include/dt-bindings/clock/qcom,kaanapali-gpucc.h
include/dt-bindings/clock/qcom,milos-gpucc.h
@@ -30,6 +31,7 @@ description: |
properties:
compatible:
enum:
+ - qcom,eliza-gpucc
- qcom,glymur-gpucc
- qcom,kaanapali-gpucc
- qcom,milos-gpucc
@@ -71,6 +73,7 @@ allOf:
compatible:
contains:
enum:
+ - qcom,eliza-gpucc
- qcom,sm8750-gpucc
then:
required:
diff --git a/include/dt-bindings/clock/qcom,eliza-gpucc.h b/include/dt-bindings/clock/qcom,eliza-gpucc.h
new file mode 100644
index 0000000000000000000000000000000000000000..706e1c93240a8234dd8017ee181d19e58091fd6d
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,eliza-gpucc.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_GPU_CC_ELIZA_H
+#define _DT_BINDINGS_CLK_QCOM_GPU_CC_ELIZA_H
+
+/* GPU_CC clocks */
+#define GPU_CC_AHB_CLK 0
+#define GPU_CC_CRC_AHB_CLK 1
+#define GPU_CC_CX_ACCU_SHIFT_CLK 2
+#define GPU_CC_CX_FF_CLK 3
+#define GPU_CC_CX_GMU_CLK 4
+#define GPU_CC_CXO_AON_CLK 5
+#define GPU_CC_CXO_CLK 6
+#define GPU_CC_DEMET_CLK 7
+#define GPU_CC_DEMET_DIV_CLK_SRC 8
+#define GPU_CC_FF_CLK_SRC 9
+#define GPU_CC_FREQ_MEASURE_CLK 10
+#define GPU_CC_GMU_CLK_SRC 11
+#define GPU_CC_GPU_SMMU_VOTE_CLK 12
+#define GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK 13
+#define GPU_CC_HUB_AON_CLK 14
+#define GPU_CC_HUB_CLK_SRC 15
+#define GPU_CC_HUB_CX_INT_CLK 16
+#define GPU_CC_MEMNOC_GFX_CLK 17
+#define GPU_CC_MND1X_0_GFX3D_CLK 18
+#define GPU_CC_MND1X_1_GFX3D_CLK 19
+#define GPU_CC_PLL0 20
+#define GPU_CC_PLL1 21
+#define GPU_CC_SLEEP_CLK 22
+#define GPU_CC_XO_CLK_SRC 23
+#define GPU_CC_XO_DIV_CLK_SRC 24
+
+/* GPU_CC power domains */
+#define GPU_CC_CX_GDSC 0
+#define GPU_CC_GX_GDSC 1
+
+/* GPU_CC resets */
+#define GPU_CC_ACD_BCR 0
+#define GPU_CC_CB_BCR 1
+#define GPU_CC_CX_BCR 2
+#define GPU_CC_FAST_HUB_BCR 3
+#define GPU_CC_FF_BCR 4
+#define GPU_CC_GFX3D_AON_BCR 5
+#define GPU_CC_GMU_BCR 6
+#define GPU_CC_GX_BCR 7
+#define GPU_CC_RBCPR_BCR 8
+#define GPU_CC_XO_BCR 9
+
+#endif
--
2.34.1
^ permalink raw reply related
* [PATCH v2 1/8] dt-bindings: clock: qcom: Add video clock controller on Eliza SoC
From: Taniya Das @ 2026-04-09 18:10 UTC (permalink / raw)
To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio, Maxime Coquelin,
Alexandre Torgue
Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm,
linux-clk, devicetree, linux-kernel, linux-stm32,
linux-arm-kernel, Taniya Das
In-Reply-To: <20260409-eliza_mm_cc_v2-v2-0-bc0c6dd77bc5@oss.qualcomm.com>
Add compatible string for Eliza video clock controller and the bindings
for Eliza Qualcomm SoC.
Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
---
.../bindings/clock/qcom,eliza-videocc.yaml | 51 ++++++++++++++++++++++
include/dt-bindings/clock/qcom,eliza-videocc.h | 37 ++++++++++++++++
2 files changed, 88 insertions(+)
diff --git a/Documentation/devicetree/bindings/clock/qcom,eliza-videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,eliza-videocc.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..26a0c85f26b13ca8e7a4f5f418e8c98235f10558
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,eliza-videocc.yaml
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,eliza-videocc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Video Clock & Reset Controller on Eliza
+
+maintainers:
+ - Taniya Das <taniya.das@oss.qualcomm.com>
+
+description: |
+ Qualcomm video clock control module provides the clocks, resets and power
+ domains on Eliza.
+
+ See also: include/dt-bindings/clock/qcom,eliza-videocc.h
+
+properties:
+ compatible:
+ const: qcom,eliza-videocc
+
+ clocks:
+ items:
+ - description: Board XO source
+ - description: Sleep clock source
+ - description: Video AHB clock from GCC
+
+required:
+ - compatible
+ - clocks
+
+allOf:
+ - $ref: qcom,gcc.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,eliza-gcc.h>
+ clock-controller@aaf0000 {
+ compatible = "qcom,eliza-videocc";
+ reg = <0x0aaf0000 0x10000>;
+ clocks = <&bi_tcxo_div2>,
+ <&sleep_clk>,
+ <&gcc GCC_VIDEO_AHB_CLK>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
+...
diff --git a/include/dt-bindings/clock/qcom,eliza-videocc.h b/include/dt-bindings/clock/qcom,eliza-videocc.h
new file mode 100644
index 0000000000000000000000000000000000000000..1e922250a7fae77f5c996208d50ff372b252aa51
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,eliza-videocc.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_VIDEO_CC_ELIZA_H
+#define _DT_BINDINGS_CLK_QCOM_VIDEO_CC_ELIZA_H
+
+/* VIDEO_CC clocks */
+#define VIDEO_CC_AHB_CLK 0
+#define VIDEO_CC_AHB_CLK_SRC 1
+#define VIDEO_CC_MVS0_CLK 2
+#define VIDEO_CC_MVS0_CLK_SRC 3
+#define VIDEO_CC_MVS0_DIV_CLK_SRC 4
+#define VIDEO_CC_MVS0_SHIFT_CLK 5
+#define VIDEO_CC_MVS0C_CLK 6
+#define VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC 7
+#define VIDEO_CC_MVS0C_SHIFT_CLK 8
+#define VIDEO_CC_PLL0 9
+#define VIDEO_CC_SLEEP_CLK 10
+#define VIDEO_CC_SLEEP_CLK_SRC 11
+#define VIDEO_CC_XO_CLK 12
+#define VIDEO_CC_XO_CLK_SRC 13
+
+/* VIDEO_CC power domains */
+#define VIDEO_CC_MVS0_GDSC 0
+#define VIDEO_CC_MVS0C_GDSC 1
+
+/* VIDEO_CC resets */
+#define VIDEO_CC_INTERFACE_BCR 0
+#define VIDEO_CC_MVS0_CLK_ARES 1
+#define VIDEO_CC_MVS0_BCR 2
+#define VIDEO_CC_MVS0C_CLK_ARES 3
+#define VIDEO_CC_MVS0C_BCR 4
+#define VIDEO_CC_XO_CLK_ARES 5
+
+#endif
--
2.34.1
^ permalink raw reply related
* [PATCH v2 0/8] Add support for Video, Camera, Graphics clock controllers on Eliza
From: Taniya Das @ 2026-04-09 18:10 UTC (permalink / raw)
To: Bjorn Andersson, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio, Maxime Coquelin,
Alexandre Torgue
Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm,
linux-clk, devicetree, linux-kernel, linux-stm32,
linux-arm-kernel, Taniya Das, Konrad Dybcio
Add driver for Eliza SoC camera, graphics and Video clock controllers.
The camera clock controller supports the cambist clock controller and
the regular camera clock controller.
The patches have been tested on Qualcomm Eliza MTP board.
Changes in v2:
- rebased the patches on the latest linux-next.
- Add new bindings for Video and Camcc.
- Remove commented code in GPUCC (limiter code).
- Add device nodes for the corresponding clock controllers.
- Add RB-by tags for VideoCC and CamCC/Cambistmclk from v1.
- Link to v1: https://lore.kernel.org/r/20260317-eliza_mm_clock_controllers_v1-v1-0-4696eeda8cfb@oss.qualcomm.com
Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com>
---
Taniya Das (8):
dt-bindings: clock: qcom: Add video clock controller on Eliza SoC
dt-bindings: clock: qcom: document the Eliza GPU Clock Controller
dt-bindings: clock: qcom: Add support for CAMCC for Eliza
clk: qcom: videocc: Add video clock controller driver for Eliza
clk: qcom: gpucc: Add GPU Clock Controller driver for Eliza
clk: qcom: camcc: Add support for camera clock controller for Eliza
arm64: defconfig: Enable clock controllers on Qualcomm Eliza SoC
arm64: dts: qcom: eliza: Add support for MM clock controllers
.../bindings/clock/qcom,eliza-camcc.yaml | 55 +
.../bindings/clock/qcom,eliza-videocc.yaml | 51 +
.../bindings/clock/qcom,sm8450-gpucc.yaml | 3 +
arch/arm64/boot/dts/qcom/eliza.dtsi | 54 +
arch/arm64/configs/defconfig | 3 +
drivers/clk/qcom/Kconfig | 28 +
drivers/clk/qcom/Makefile | 3 +
drivers/clk/qcom/cambistmclkcc-eliza.c | 465 ++++
drivers/clk/qcom/camcc-eliza.c | 2803 ++++++++++++++++++++
drivers/clk/qcom/gpucc-eliza.c | 621 +++++
drivers/clk/qcom/videocc-eliza.c | 403 +++
.../dt-bindings/clock/qcom,eliza-cambistmclkcc.h | 32 +
include/dt-bindings/clock/qcom,eliza-camcc.h | 151 ++
include/dt-bindings/clock/qcom,eliza-gpucc.h | 52 +
include/dt-bindings/clock/qcom,eliza-videocc.h | 37 +
15 files changed, 4761 insertions(+)
---
base-commit: db7efce4ae23ad5e42f5f55428f529ff62b86fab
change-id: 20260409-eliza_mm_cc_v2-701c34ddb74e
Best regards,
--
Taniya Das <taniya.das@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH] KVM: arm64: Add KVM_CAP_ARM_NATIVE_CACHE_CONFIG vcpu capability
From: David Woodhouse @ 2026-04-09 17:49 UTC (permalink / raw)
To: Marc Zyngier
Cc: Gutierrez Cantu, Bernardo, alexandru.elisei, alyssa, asahi,
broonie, catalin.marinas, james.morse, kvmarm, linux-arm-kernel,
linux-kernel, marcan, mathieu.poirier, oliver.upton,
suzuki.poulose, sven, will
In-Reply-To: <86se942hbv.wl-maz@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 7534 bytes --]
On Thu, 2026-04-09 at 18:07 +0100, Marc Zyngier wrote:
> On Thu, 09 Apr 2026 16:29:06 +0100,
> David Woodhouse <dwmw2@infradead.org> wrote:
> >
> > [1 <text/plain; UTF-8 (quoted-printable)>]
> > From: David Woodhouse <dwmw@amazon.co.uk>
> >
> > Commit 7af0c2534f4c5 ("KVM: arm64: Normalize cache configuration")
> > fabricates CLIDR_EL1 and CCSIDR_EL1 values instead of using the real
> > hardware values. While this provides consistent values across
> > heterogeneous CPUs, it does cause visible changes in the CPU model
> > exposed to guests.
> >
> > The commit claims that userspace can restore the original values, but
> > there is no way for userspace to obtain the real CLIDR_EL1 register
> > value — it is not fully reconstructible from sysfs, which lacks the
> > LoC, LoUU, and LoUIS fields.
> >
> > Add a per-vcpu KVM_CAP_ARM_NATIVE_CACHE_CONFIG capability that reads
> > the real CLIDR_EL1 and all CCSIDR_EL1 values from the current physical
> > CPU and sets them on the vcpu.
> >
> > This allows hypervisors to present the real hardware cache configuration
> > to guests, which is important for consistency of the environment across
> > kernel versions and for migration compatibility with hosts running
> > older kernels that exposed the real values.
> >
> > Fixes: 7af0c2534f4c ("KVM: arm64: Normalize cache configuration")
> > Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> > ---
> > Documentation/virt/kvm/api.rst | 23 ++++++++
> > arch/arm64/include/asm/kvm_host.h | 1 +
> > arch/arm64/kvm/arm.c | 17 ++++++
> > arch/arm64/kvm/sys_regs.c | 26 ++++++++++
> > include/uapi/linux/kvm.h | 1 +
> > tools/testing/selftests/kvm/Makefile.kvm | 1 +
> > .../selftests/kvm/arm64/native_cache_config.c | 52 +++++++++++++++++++
> > 7 files changed, 121 insertions(+)
> > create mode 100644 tools/testing/selftests/kvm/arm64/native_cache_config.c
> >
> > diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> > index e3b3bd9edeec..ee47dc07ceac 100644
> > --- a/Documentation/virt/kvm/api.rst
> > +++ b/Documentation/virt/kvm/api.rst
> > @@ -8930,6 +8930,29 @@ no-op.
> >
> > ``KVM_CHECK_EXTENSION`` returns the bitmask of exits that can be disabled.
> >
> > +7.48 KVM_CAP_ARM_NATIVE_CACHE_CONFIG
> > +-------------------------------------
> > +
> > +:Architecture: arm64
> > +:Target: vcpu
> > +:Parameters: none
> > +:Returns: 0 on success, -ENOMEM on allocation failure, -EINVAL if
> > + args[0] or flags are non-zero.
> > +
> > +This per-vcpu capability reads the real CLIDR_EL1 and CCSIDR_EL1 values
> > +from the physical CPU on which the ioctl is executed, and sets them on
> > +the vcpu. This replaces the fabricated cache configuration that KVM
> > +provides by default.
> > +
> > +The caller should ensure the vcpu thread is pinned to the desired
> > +physical CPU before invoking this capability, so that the correct cache
> > +topology is captured. On heterogeneous systems, different physical CPUs
> > +may have different cache configurations.
> > +
> > +After this capability is enabled, the vcpu's CLIDR_EL1 and CCSIDR_EL1
> > +values can still be overridden individually via ``KVM_SET_ONE_REG`` and
> > +the ``KVM_REG_ARM_DEMUX`` interface.
> > +
> > 8. Other capabilities.
> > ======================
> >
> > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> > index a1bb025c641f..c9713a472c47 100644
> > --- a/arch/arm64/include/asm/kvm_host.h
> > +++ b/arch/arm64/include/asm/kvm_host.h
> > @@ -1296,6 +1296,7 @@ void kvm_sys_regs_create_debugfs(struct kvm *kvm);
> > void kvm_reset_sys_regs(struct kvm_vcpu *vcpu);
> >
> > int __init kvm_sys_reg_table_init(void);
> > +int kvm_vcpu_set_native_cache_config(struct kvm_vcpu *vcpu);
> > struct sys_reg_desc;
> > int __init populate_sysreg_config(const struct sys_reg_desc *sr,
> > unsigned int idx);
> > diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> > index 326a99fea753..579583e8dc5c 100644
> > --- a/arch/arm64/kvm/arm.c
> > +++ b/arch/arm64/kvm/arm.c
> > @@ -393,6 +393,10 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
> > case KVM_CAP_ARM_DISABLE_EXITS:
> > r = KVM_ARM_DISABLE_VALID_EXITS;
> > break;
> > + case KVM_CAP_ARM_NATIVE_CACHE_CONFIG:
> > + case KVM_CAP_ENABLE_CAP:
> > + r = 1;
> > + break;
> > case KVM_CAP_SET_GUEST_DEBUG2:
> > return KVM_GUESTDBG_VALID_MASK;
> > case KVM_CAP_ARM_SET_DEVICE_ADDR:
> > @@ -1793,6 +1797,19 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
> > r = kvm_arch_vcpu_ioctl_vcpu_init(vcpu, &init);
> > break;
> > }
> > + case KVM_ENABLE_CAP: {
> > + struct kvm_enable_cap cap;
> > +
> > + r = -EFAULT;
> > + if (copy_from_user(&cap, argp, sizeof(cap)))
> > + break;
> > +
> > + r = -EINVAL;
> > + if (cap.cap == KVM_CAP_ARM_NATIVE_CACHE_CONFIG &&
> > + !cap.args[0] && !cap.flags)
> > + r = kvm_vcpu_set_native_cache_config(vcpu);
> > + break;
> > + }
> > case KVM_SET_ONE_REG:
> > case KVM_GET_ONE_REG: {
> > struct kvm_one_reg reg;
> > diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> > index 1b4cacb6e918..c19d84e48f8b 100644
> > --- a/arch/arm64/kvm/sys_regs.c
> > +++ b/arch/arm64/kvm/sys_regs.c
> > @@ -484,6 +484,32 @@ static int set_ccsidr(struct kvm_vcpu *vcpu, u32 csselr, u32 val)
> > return 0;
> > }
> >
> > +int kvm_vcpu_set_native_cache_config(struct kvm_vcpu *vcpu)
> > +{
> > + u32 csselr;
> > +
> > + if (!vcpu->arch.ccsidr) {
> > + vcpu->arch.ccsidr = kmalloc_array(CSSELR_MAX, sizeof(u32),
> > + GFP_KERNEL_ACCOUNT);
> > + if (!vcpu->arch.ccsidr)
> > + return -ENOMEM;
> > + }
>
> Well, no.
>
> The moment you decide to expose all of the host's crap, you really
> need to put everything on the table. It means fully handling
> FEAT_CCIDX, which we were careful not to expose anywhere because it is
> a terrible idea.
The intent here is not to "expose all of the host's crap", but to
maintain compatibility with what the kernel did before commit
7af0c2534f4c. No need to expose FEAT_CCIDX.
> > + for (csselr = 0; csselr < CSSELR_MAX; csselr++) {
> > + write_sysreg(csselr, csselr_el1);
> > + isb();
> > + vcpu->arch.ccsidr[csselr] = read_sysreg(ccsidr_el1);
>
> That's not how the selection register works. CLIDR_EL1 tells you what
> each cache level is (Instructions, Data, Unified, Tags), and that must
> be combined with the index (which doesn't start at bit 0).
Ack, thanks. I'll rework that based on the old is_valid_cache()
function.
> I also wonder how you reconcile not exposing MTE when the cache
> hierarchy indicate support for tags. That clearly contradicts "report
> what the HW has".
If that was an issue then it would already have been an issue before
commit 7af0c2534f4 (and in kernels with that commit reverted), hosting
millions of guests today.
This isn't about introducing *new* behaviour; it's about allowing the
existing established behaviour to be maintained so that we can have a
*managed* transition to the new model (for new launches) rather than an
unconditional uncontrolled change as the kernel gets upgraded.
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5069 bytes --]
^ permalink raw reply
* Re: [PATCH] media: cedrus: skip invalid H.264 reference list entries
From: Nicolas Dufresne @ 2026-04-09 17:48 UTC (permalink / raw)
To: Paul Kocialkowski
Cc: Pengpeng Hou, mripard, mchehab, gregkh, wens, jernej.skrabec,
samuel, linux-media, linux-staging, linux-arm-kernel, linux-sunxi,
linux-kernel
In-Reply-To: <adfGZHR9wM2d6-yJ@shepard>
[-- Attachment #1: Type: text/plain, Size: 3173 bytes --]
Le jeudi 09 avril 2026 à 17:31 +0200, Paul Kocialkowski a écrit :
> Hi,
>
> On Thu 09 Apr 26, 10:39, Nicolas Dufresne wrote:
> > Hi,
> >
> > Le jeudi 09 avril 2026 à 16:31 +0200, Paul Kocialkowski a écrit :
> > > I think it make sense yes, but it would be good to document it in the uAPI
> > > document too.
> >
> > Basically, extend in the M2M decoder spec(s) on the existing documentation:
> >
> > V4L2_BUF_FLAG_ERROR:
> > -
> > When this flag is set, the buffer has been dequeued successfully, although
> > the data might **have been corrupted**. This is recoverable, streaming may
> > continue as normal and the buffer may be reused normally. Drivers set this
> > flag when the VIDIOC_DQBUF ioctl is called.
>
> Well this part is about v4l2 buffers in general, not just m2m/decoders.
> But I guess this mechanism would make sense for more device classes than just
> decoders, so we could indeed specify it there. Maybe with a sufficiently broad
> wording.
This is current spec, I did meant to use that as basis and improve that codec
specific part.
>
> But it would be good to also update the stateless decode document (and maybe
> stateful too) where V4L2_BUF_FLAG_ERROR is already mentionned a few times.
> We could indicate how this behavior related to reference frames there.
>
> If we agree I could make a series with the following:
> - Introduce a V4L2_H264_REF_MISSING 0xff define (same for HEVC)
> - Update the v4l2_h264_reference doc to mention it
> - Update the cedrus driver to error out (zero-size payload) when the L0/L1 index
> is either V4L2_H264_REF_MISSING or an invalid index that doesn't exist in the
> DPB (same for HEVC)
Base on what you reported, this is currently the shortest and safe thing to do.
> - Update the v4l2 buffer and stateless(+stateful) documents to mention that
> buffers marked with V4L2_BUF_FLAG_ERROR may or may not contain usable (yet
> corrupted) data depending on the payload size and how it relates to reference
> frames.
wfm
>
> Then we could later envision having a mechanism (hopefully common) to figure out
> the best replacement to a given missing reference, which would allow cedrus
> (and maybe other drivers too) to return a frame with incorrect data instead of
> a zero-size payload error.
Certainly, though from my experience best or any works quite well, and quite
better then skipping. But if it makes the HW unstable, or sending uninitialized
data to the HW, I agree this is better to hard fail that frame now, enhance
later. Also, be aware that some HW (RK3399 iirc) have error counters, so you
know how many macroblocks are not decoded properly. Other HW have error IRQ,
with a register that tells which macroblock it failed on. The reference decoder
have optional support for software concealment for the failing macroblock, the
down side is that in the worse case you get an irq per block, which is quite a
disaster performance whise.
>
> What do you think?
Yes, I'm happy with the proposal to get this moving forward.
Nicolas
>
> All the best,
>
> Paul
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH 5/7] clk: qcom: gpucc: Add GPU Clock Controller driver for Eliza
From: Taniya Das @ 2026-04-09 17:44 UTC (permalink / raw)
To: Konrad Dybcio, Bjorn Andersson, Michael Turquette, Stephen Boyd,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Konrad Dybcio,
Vladimir Zapolskiy, Akhil P Oommen
Cc: Ajit Pandey, Imran Shaik, Jagadeesh Kona, linux-arm-msm,
linux-clk, devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <d97237a6-7f3b-4358-8972-5fd4b65d8f27@oss.qualcomm.com>
On 3/19/2026 6:25 PM, Konrad Dybcio wrote:
>> +// [GPU_CC_FREQUENCY_LIMITER_IRQ_CLEAR] = { 0x9538 },
> dead code
>
> +Akhil is that useful?
>
> [...]
I will remove the code in the next patch. It is not required.
>
>> +static void clk_eliza_regs_configure(struct device *dev, struct regmap *regmap)
>> +{
>> + /* Enable frequency limiter irq */
>> + regmap_clear_bits(regmap, 0x9534, BIT(0));
>> +}
> ..sounds like it
I missed to clean it up.
--
Thanks,
Taniya Das
^ permalink raw reply
* Re: [PATCH v4 2/4] pwm: sun50i: Add H616 PWM support
From: Paul Kocialkowski @ 2026-04-09 17:30 UTC (permalink / raw)
To: Richard Genoud
Cc: Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Philipp Zabel, Thomas Petazzoni, John Stultz, Joao Schim,
linux-pwm, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel
In-Reply-To: <20260305091959.2530374-3-richard.genoud@bootlin.com>
[-- Attachment #1: Type: text/plain, Size: 10986 bytes --]
Hi Richard,
On Thu 05 Mar 26, 10:19, Richard Genoud wrote:
> +/* PWM IRQ Enable Register */
> +#define H616_PWM_IER 0x0
I think it would make more sense to keep the full register names from the
manual after the suffix and stick to them. It makes things easier when
comparing the code with documentation or the reference implementation.
So something like SUN8I_PWM_PIER here.
> +
> +/* PWM IRQ Status Register */
> +#define H616_PWM_ISR 0x4
> +
> +/* PWM Capture IRQ Enable Register */
> +#define H616_PWM_CIER 0x10
> +
> +/* PWM Capture IRQ Status Register */
> +#define H616_PWM_CISR 0x14
> +
> +/* PWMCC Pairs Clock Configuration Registers */
> +#define H616_PWM_XY_CLK_CR(pair) (0x20 + ((pair) * 0x4))
> +#define H616_PWM_XY_CLK_CR_SRC_SHIFT 7
> +#define H616_PWM_XY_CLK_CR_SRC_MASK 1
> +#define H616_PWM_XY_CLK_CR_GATE_BIT 4
> +#define H616_PWM_XY_CLK_CR_BYPASS_BIT(chan) ((chan) % 2 + 5)
> +#define H616_PWM_XY_CLK_CR_DIV_M_SHIFT 0
> +
> +/* PWMCC Pairs Dead Zone Control Registers */
> +#define H616_PWM_XY_DZ(pair) (0x30 + ((pair) * 0x4))
> +
> +/* PWM Enable Register */
> +#define H616_PWM_ENR 0x40
> +#define H616_PWM_ENABLE(x) BIT(x)
> +
> +/* PWM Capture Enable Register */
> +#define H616_PWM_CER 0x44
> +
> +/* PWM Control Register */
> +#define H616_PWM_CTRL_REG(chan) (0x60 + (chan) * 0x20)
You're sometimes calling the register offset _REG and sometimes not.
Both options are fine but you need to keep it consistent across the whole
definitions. I would be enclined to not use it after using the register names
coming from the manual as suggested above.
Also you're sometimes using "chan", sometimes "ch" for the argument to the
register macros. This is inconsistent and you might as well just use "c"
everywhere so it doesn't take too much space.
> +#define H616_PWM_CTRL_PRESCAL_K_SHIFT 0
> +#define H616_PWM_CTRL_PRESCAL_K_WIDTH 8
> +#define H616_PWM_CTRL_ACTIVE_STATE BIT(8)
> +
> +/* PWM Period Register */
> +#define H616_PWM_PERIOD_REG(ch) (0x64 + (ch) * 0x20)
> +#define H616_PWM_PERIOD_MASK GENMASK(31, 16)
> +#define H616_PWM_DUTY_MASK GENMASK(15, 0)
> +#define H616_PWM_REG_PERIOD(reg) (FIELD_GET(H616_PWM_PERIOD_MASK, reg) + 1)
> +#define H616_PWM_REG_DUTY(reg) FIELD_GET(H616_PWM_DUTY_MASK, reg)
> +#define H616_PWM_PERIOD(prd) FIELD_PREP(H616_PWM_PERIOD_MASK, (prd) - 1)
> +#define H616_PWM_DUTY(dty) FIELD_PREP(H616_PWM_DUTY_MASK, dty)
> +#define H616_PWM_PERIOD_MAX (FIELD_MAX(H616_PWM_PERIOD_MASK) + 1)
Using REG as a prefix feels a bit confusing here. I would rather see:
#define SUN8I_PWM_PPR(c) (0x64 + (c) * 0x20)
#define SUN8I_PWM_PPR_PERIOD(p) FIELD_PREP(...)
#define SUN8I_PWM_PPR_PERIOD_VALUE(r) FIELD_GET(...)
#define SUN8I_PWN_PPR_PERIOD_MAX FIELD_MAX(...)
#define SUN8I_PWM_PPR_DUTY(d) FIELD_PREP(...)
#define SUN8I_PWM_PPR_DUTY_VALUE(r) FIELD_GET(...)
> +
> +/* PWM Count Register */
> +#define H616_PWM_CNT_REG(x) (0x68 + (x) * 0x20)
> +
> +/* PWM Capture Control Register */
> +#define H616_PWM_CCR(x) (0x6c + (x) * 0x20)
> +
> +/* PWM Capture Rise Lock Register */
> +#define H616_PWM_CRLR(x) (0x70 + (x) * 0x20)
> +
> +/* PWM Capture Fall Lock Register */
> +#define H616_PWM_CFLR(x) (0x74 + (x) * 0x20)
> +
> +#define H616_PWM_PAIR_IDX(chan) ((chan) >> 2)
> +
> +/*
> + * Block diagram of the PWM clock controller:
> + *
> + * _____ ______ ________
> + * OSC24M --->| | | | | |
> + * APB1 ----->| Mux |--->| Gate |--->| /div_m |-----> H616_PWM_clock_src_xy
> + * |_____| |______| |________|
> + * ________
> + * | |
> + * +->| /div_k |---> H616_PWM_clock_x
> + * | |________|
> + * | ______
> + * | | |
> + * +-->| Gate |----> H616_PWM_bypass_clock_x
> + * | |______|
> + * H616_PWM_clock_src_xy ----+ ________
> + * | | |
> + * +->| /div_k |---> H616_PWM_clock_y
> + * | |________|
> + * | ______
> + * | | |
> + * +-->| Gate |----> H616_PWM_bypass_clock_y
> + * |______|
> + *
> + * NB: when the bypass is set, all the PWM logic is bypassed.
> + * So, the duty cycle and polarity can't be modified (we just have a clock).
> + * The bypass in PWM mode is used to achieve a 1/2 relative duty cycle with the
> + * fastest clock.
> + *
> + * H616_PWM_clock_x/y serve for the PWM purpose.
> + * H616_PWM_bypass_clock_x/y serve for the clock-provider purpose.
> + *
> + */
> +
> +/*
> + * Table used for /div_m (diviser before obtaining H616_PWM_clock_src_xy)
> + * It's actually CLK_DIVIDER_POWER_OF_TWO, but limited to /256
> + */
> +#define CLK_TABLE_DIV_M_ENTRY(i) { \
> + .val = (i), .div = 1 << (i) \
> +}
> +
> +static const struct clk_div_table clk_table_div_m[] = {
> + CLK_TABLE_DIV_M_ENTRY(0),
> + CLK_TABLE_DIV_M_ENTRY(1),
> + CLK_TABLE_DIV_M_ENTRY(2),
> + CLK_TABLE_DIV_M_ENTRY(3),
> + CLK_TABLE_DIV_M_ENTRY(4),
> + CLK_TABLE_DIV_M_ENTRY(5),
> + CLK_TABLE_DIV_M_ENTRY(6),
> + CLK_TABLE_DIV_M_ENTRY(7),
> + CLK_TABLE_DIV_M_ENTRY(8),
> + { /* sentinel */ }
> +};
> +
> +#define H616_PWM_XY_SRC_GATE(_pair, _reg) \
> +struct clk_gate gate_xy_##_pair = { \
> + .reg = (void *)(_reg), \
> + .bit_idx = H616_PWM_XY_CLK_CR_GATE_BIT, \
> + .hw.init = &(struct clk_init_data){ \
> + .ops = &clk_gate_ops, \
> + } \
> +}
> +
> +#define H616_PWM_XY_SRC_MUX(_pair, _reg) \
> +struct clk_mux mux_xy_##_pair = { \
> + .reg = (void *)(_reg), \
> + .shift = H616_PWM_XY_CLK_CR_SRC_SHIFT, \
> + .mask = H616_PWM_XY_CLK_CR_SRC_MASK, \
> + .flags = CLK_MUX_ROUND_CLOSEST, \
> + .hw.init = &(struct clk_init_data){ \
> + .ops = &clk_mux_ops, \
> + } \
> +}
> +
> +#define H616_PWM_XY_SRC_DIV(_pair, _reg) \
> +struct clk_divider rate_xy_##_pair = { \
> + .reg = (void *)(_reg), \
> + .shift = H616_PWM_XY_CLK_CR_DIV_M_SHIFT, \
> + .table = clk_table_div_m, \
> + .hw.init = &(struct clk_init_data){ \
> + .ops = &clk_divider_ops, \
> + } \
> +}
> +
> +#define H616_PWM_X_DIV(_idx, _reg) \
> +struct clk_divider rate_x_##_idx = { \
> + .reg = (void *)(_reg), \
> + .shift = H616_PWM_CTRL_PRESCAL_K_SHIFT, \
> + .width = H616_PWM_CTRL_PRESCAL_K_WIDTH, \
> + .hw.init = &(struct clk_init_data){ \
> + .ops = &clk_divider_ops, \
> + } \
> +}
> +
> +#define H616_PWM_X_BYPASS_GATE(_idx) \
> +struct clk_gate gate_x_bypass_##_idx = { \
> + .reg = (void *)H616_PWM_ENR, \
> + .bit_idx = _idx, \
> + .hw.init = &(struct clk_init_data){ \
> + .ops = &clk_gate_ops, \
> + } \
> +}
> +
> +#define H616_PWM_XY_CLK_SRC(_pair, _reg) \
> + static H616_PWM_XY_SRC_MUX(_pair, _reg); \
> + static H616_PWM_XY_SRC_GATE(_pair, _reg); \
> + static H616_PWM_XY_SRC_DIV(_pair, _reg)
> +
> +#define H616_PWM_X_CLK(_idx) \
> + static H616_PWM_X_DIV(_idx, H616_PWM_CTRL_REG(_idx))
> +
> +#define H616_PWM_X_BYPASS_CLK(_idx) \
> + H616_PWM_X_BYPASS_GATE(_idx)
> +
> +#define REF_CLK_XY_SRC(_pair) \
> + { \
> + .name = "pwm-clk-src" #_pair, \
> + .mux_hw = &mux_xy_##_pair.hw, \
> + .gate_hw = &gate_xy_##_pair.hw, \
> + .rate_hw = &rate_xy_##_pair.hw, \
> + }
> +
> +#define REF_CLK_X(_idx, _pair) \
> + { \
> + .name = "pwm-clk" #_idx, \
> + .parent_names = (const char *[]){ "pwm-clk-src" #_pair }, \
> + .num_parents = 1, \
> + .rate_hw = &rate_x_##_idx.hw, \
> + .flags = CLK_SET_RATE_PARENT, \
> + }
> +
> +#define REF_CLK_BYPASS(_idx, _pair) \
> + { \
> + .name = "pwm-clk-bypass" #_idx, \
> + .parent_names = (const char *[]){ "pwm-clk-src" #_pair }, \
> + .num_parents = 1, \
> + .gate_hw = &gate_x_bypass_##_idx.hw, \
> + .flags = CLK_SET_RATE_PARENT, \
> + }
> +
> +/*
> + * H616_PWM_clock_src_xy generation:
> + * _____ ______ ________
> + * OSC24M --->| | | | | |
> + * APB1 ----->| Mux |--->| Gate |--->| /div_m |-----> H616_PWM_clock_src_xy
> + * |_____| |______| |________|
> + */
> +H616_PWM_XY_CLK_SRC(01, H616_PWM_XY_CLK_CR(0));
> +H616_PWM_XY_CLK_SRC(23, H616_PWM_XY_CLK_CR(1));
> +H616_PWM_XY_CLK_SRC(45, H616_PWM_XY_CLK_CR(2));
> +
> +/*
> + * H616_PWM_clock_x_div generation:
> + * ________
> + * | | H616_PWM_clock_x/y
> + * H616_PWM_clock_src_xy --->| /div_k |--------------->
> + * |________|
> + */
> +H616_PWM_X_CLK(0);
> +H616_PWM_X_CLK(1);
> +H616_PWM_X_CLK(2);
> +H616_PWM_X_CLK(3);
> +H616_PWM_X_CLK(4);
> +H616_PWM_X_CLK(5);
> +
> +/*
> + * H616_PWM_bypass_clock_xy generation:
> + * ______
> + * | |
> + * H616_PWM_clock_src_xy ---->| Gate |-------> H616_PWM_bypass_clock_x
> + * |______|
> + *
> + * The gate is actually H616_PWM_ENR register.
> + */
> +H616_PWM_X_BYPASS_CLK(0);
> +H616_PWM_X_BYPASS_CLK(1);
> +H616_PWM_X_BYPASS_CLK(2);
> +H616_PWM_X_BYPASS_CLK(3);
> +H616_PWM_X_BYPASS_CLK(4);
> +H616_PWM_X_BYPASS_CLK(5);
> +
> +struct clk_pwm_data {
> + const char *name;
> + const char **parent_names;
> + unsigned int num_parents;
> + struct clk_hw *mux_hw;
> + struct clk_hw *rate_hw;
> + struct clk_hw *gate_hw;
> + unsigned long flags;
> +};
> +
> +#define CLK_BYPASS(h616chip, ch) ((h616chip)->data->npwm + (ch))
> +#define CLK_XY_SRC_IDX(h616chip, ch) ((h616chip)->data->npwm * 2 + ((ch) >> 1))
> +static struct clk_pwm_data pwmcc_data[] = {
> + REF_CLK_X(0, 01),
> + REF_CLK_X(1, 01),
> + REF_CLK_X(2, 23),
> + REF_CLK_X(3, 23),
> + REF_CLK_X(4, 45),
> + REF_CLK_X(5, 45),
> + REF_CLK_BYPASS(0, 01),
> + REF_CLK_BYPASS(1, 01),
> + REF_CLK_BYPASS(2, 23),
> + REF_CLK_BYPASS(3, 23),
> + REF_CLK_BYPASS(4, 45),
> + REF_CLK_BYPASS(5, 45),
> + REF_CLK_XY_SRC(01),
> + REF_CLK_XY_SRC(23),
> + REF_CLK_XY_SRC(45),
> + { /* sentinel */ }
> +};
We'll probably need a way to tie these static definitions to a particular
instance of the unit for a given chip. But I guess that can be done later
when adding more chips to the driver.
I'm not too versed in the clk and pwm APIs but the rest generally looks good
to me.
All the best,
Paul
--
Paul Kocialkowski,
Independent contractor - sys-base - https://www.sys-base.io/
Free software developer - https://www.paulk.fr/
Expert in multimedia, graphics and embedded hardware support with Linux.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH] crypto: tstmgr - guard xxhash tests
From: Hamza Mahfooz @ 2026-04-09 17:18 UTC (permalink / raw)
To: Herbert Xu
Cc: linux-crypto, David S. Miller, Maxime Coquelin, Alexandre Torgue,
linux-stm32, linux-arm-kernel, linux-kernel, Jeff Barnes,
Paul Monson
In-Reply-To: <adYNClYB6RY820Xl@gondor.apana.org.au>
On Wed, Apr 08, 2026 at 04:08:42PM +0800, Herbert Xu wrote:
> Please show me the panic. Normally it's not an issue if an algorithm
> is not present while the test vectors are.
>
alg: hash: failed to allocate transform for xxhash64: -2
Kernel panic - not syncing: alg: self-tests for xxhash64 (xxhash64) failed in fips mode!
CPU: 0 PID: 425 Comm: modprobe Not tainted 6.6.130.2-2.azl3 #1
Hardware name: Microsoft Corporation Virtual Machine/Virtual Machine, BIOS Hyper-V UEFI Release v4.1 01/08/2026
Call Trace:
<TASK>
dump_stack_lvl+0x4c/0x70
dump_stack+0x14/0x20
panic+0x179/0x330
alg_test+0x678/0x680
? __alloc_pages+0x1e2/0x340
do_test+0x26f8/0x7670 [tcrypt]
do_test+0x72c5/0x7670 [tcrypt]
tcrypt_mod_init+0x65/0xff0 [tcrypt]
? __pfx_tcrypt_mod_init+0x10/0x10 [tcrypt]
do_one_initcall+0x4e/0x330
? kmalloc_trace+0x2e/0xa0
do_init_module+0x68/0x250
load_module+0x1f2e/0x2150
? __do_sys_init_module+0xe6/0x1d0
__do_sys_init_module+0x19c/0x1d0
? __do_sys_init_module+0x19c/0x1d0
__x64_sys_init_module+0x1e/0x30
x64_sys_call+0x11b3/0x1c90
do_syscall_64+0x5a/0x80
? irqentry_exit_to_user_mode+0x29/0x50
? irqentry_exit+0x3f/0x50
? exc_page_fault+0x87/0x160
entry_SYSCALL_64_after_hwframe+0x78/0xe2
RIP: 0033:0x7715f70fab9e
Code: 48 8b 0d 85 32 12 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 49 89 ca b8 af 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 52 32 12 00 f7 d8 64 89 01 48
RSP: 002b:00007ffde8fef6c8 EFLAGS: 00000246 ORIG_RAX: 00000000000000af
RAX: ffffffffffffffda RBX: 00005d0b39626af0 RCX: 00007715f70fab9e
RDX: 00005d0b1710197a RSI: 0000000000028c39 RDI: 00005d0b39635310
RBP: 00005d0b1710197a R08: 0000000000000001 R09: 0000000000000000
R10: 0000000000000071 R11: 0000000000000246 R12: 00005d0b39635310
R13: 0000000000000000 R14: 00005d0b39626c20 R15: 00005d0b39626da0
</TASK>
Seems like crypto_alg_mod_lookup() [1] fails and that triggers the panic() at [2].
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/crypto/api.c?h=v7.0-rc7#n338
[2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/crypto/testmgr.c?h=v7.0-rc7#n5760
BR,
Hamza
^ permalink raw reply
* Re: [PATCH v2 0/3] media: imx-csi: cleanup media pipeline start
From: Michael Tretter @ 2026-04-09 17:17 UTC (permalink / raw)
To: Frank Li
Cc: Hans Verkuil, Steve Longerbeam, Philipp Zabel,
Mauro Carvalho Chehab, Fabio Estevam, Greg Kroah-Hartman,
Shawn Guo, Sascha Hauer, linux-media, imx, linux-arm-kernel,
Pengutronix Kernel Team, linux-staging
In-Reply-To: <acqK9Ms_eRxg59Xa@lizhi-Precision-Tower-5810>
Hi Frank,
On Mon, 30 Mar 2026 10:38:44 -0400, Frank Li wrote:
> On Mon, Mar 30, 2026 at 10:49:22AM +0200, Michael Tretter wrote:
> > Hi Hans,
> >
> > On Fri, 23 Jan 2026 17:57:23 +0100, Michael Tretter wrote:
> > > On Thu, 18 Dec 2025 10:23:48 +0100, Michael Tretter wrote:
> > > > The imx media device currently assumes that there is only a single media
> > > > pipeline. However, the media graph has multiple imx capture devices.
> > > > These may be started separately on media pipelines if they don't cause
> > > > conflicts in the media graph.
> > > >
> > > > Move the media pipeline from the media device to the capture devices to
> > > > properly track and handle multiple media pipelines for the imx-csi.
> > > > Refactor the code to start the media pipeline from the driver to help
> > > > the reader.
> > >
> >
> > Could you take a look and apply this series for the imx-media driver,
> > too? The patches are already reviewed by Frank Li and Philipp Zabel.
>
> Michael Tretter:
>
> Sorry, I will take care imx's stage driver. I already sent pull-request,
> which included your other two patches.
Thanks for taking care! I found the other two patches in the
media-committers repository.
>
> Do you have others patches, which need me take care. I am not sure if
> there are chance to send 2nd pull request for 7.1.
Currently, I have only the patches in this series.
Michael
> > >
> > > >
> > > > Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
> > > > ---
> > > > Changes in v2:
> > > > - Improve code readability in Patch 2
> > > > - Update commit message of Patch 3 as suggested by Frank Li
> > > > - Link to v1: https://patch.msgid.link/20251107-media-imx-cleanup-v1-0-f82a693c28f4@pengutronix.de
> > > >
> > > > ---
> > > > Michael Tretter (3):
> > > > media: imx-csi: move media_pipeline to video device
> > > > media: imx-csi: explicitly start media pipeline on pad 0
> > > > media: imx-csi: use media_pad_is_streaming helper
> > > >
> > > > drivers/staging/media/imx/imx-media-capture.c | 8 ++++----
> > > > drivers/staging/media/imx/imx-media-utils.c | 12 ++++++++----
> > > > drivers/staging/media/imx/imx-media.h | 7 ++++---
> > > > 3 files changed, 16 insertions(+), 11 deletions(-)
> > > > ---
> > > > base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
> > > > change-id: 20251107-media-imx-cleanup-9022d941ae44
^ permalink raw reply
* Re: [PATCH v4 0/4] Introduce Allwinner H616 PWM controller
From: Paul Kocialkowski @ 2026-04-09 17:16 UTC (permalink / raw)
To: Richard Genoud
Cc: Uwe Kleine-König, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Philipp Zabel, Thomas Petazzoni, John Stultz, Joao Schim,
linux-pwm, devicetree, linux-arm-kernel, linux-sunxi,
linux-kernel
In-Reply-To: <20260305091959.2530374-1-richard.genoud@bootlin.com>
[-- Attachment #1: Type: text/plain, Size: 7856 bytes --]
Hi Richard,
On Thu 05 Mar 26, 10:19, Richard Genoud wrote:
> Allwinner H616 PWM controller is quite different from the A10 one.
As I've mentionned before, this PWM controller is not specific to the H616
but also appears in other chips, so the name of the driver and registers
should not mention H616.
After further investigation, I can see multiple versions of this new PWM IP
being used in different chips, starting with the R40/V40 (sun8iw11) in 2016.
The latest downstream BSP driver has a list of the different generations:
https://github.com/radxa/allwinner-bsp/blob/cubie-aiot-v1.4.6/drivers/pwm/pwm-sunxi.c#L1901
We have a first generation called v100/v101 for the following chips:
H616, R328 and R40. A second generation is called v200 and brings slight
register layout differences for A133, D1/T113-S3 and V851. Subsequent
iterations (v201-5) are used in more recent chips like A527 and A733 and
seem register-compatible with v200 (from a quick look).
So what I suggest here is to rename the driver "sun8i-pwm" and eventually add
a list of generations to the driver and different registers when needed, with
an appropriate suffix in their name.
But since you're currently only dealing with H616, this work can be done later
when introducing support for more chips.
> It can drive 6 PWM channels, and like for the A10, each channel has a
> bypass that permits to output a clock, bypassing the PWM logic, when
> enabled.
>
> But, the channels are paired 2 by 2, sharing a first set of
> MUX/prescaler/gate.
> Then, for each channel, there's another prescaler (that will be bypassed
> if the bypass is enabled for this channel).
>
> It looks like that:
> _____ ______ ________
> OSC24M --->| | | | | |
> APB1 ----->| Mux |--->| Gate |--->| /div_m |-----> PWM_clock_src_xy
> |_____| |______| |________|
> ________
> | |
> +->| /div_k |---> PWM_clock_x
> | |________|
> | ______
> | | |
> +-->| Gate |----> PWM_bypass_clock_x
> | |______|
> PWM_clock_src_xy -----+ ________
> | | |
> +->| /div_k |---> PWM_clock_y
> | |________|
> | ______
> | | |
> +-->| Gate |----> PWM_bypass_clock_y
> |______|
>
> Where xy can be 0/1, 2/3, 4/5
>
> PWM_clock_x/y serve for the PWM purpose.
> PWM_bypass_clock_x/y serve for the clock-provider purpose.
> The common clock framework has been used to manage those clocks.
>
> This PWM driver serves as a clock-provider for PWM_bypass_clocks.
> This is needed for example by the embedded AC300 PHY which clock comes
> from PMW5 pin (PB12).
>
> Usually, to get a clock from a PWM driver, we use the pwm-clock driver
> so that the PWM driver doesn't need to be a clk-provider itself.
> While this works in most cases, here it just doesn't.
> That's because the pwm-clock request a period from the PWM driver,
> without any clue that it actually wants a clock at a specific frequency,
> and not a PWM signal with duty cycle capability.
From what I understand the pwm-clock driver will either assume a fixed rate
set in device-tree or deduce the rate from the pwm period. In any case it will
check that the pwm period (which it cannot change) is the same as the requested
clock period.
So I agree that pwm-clock is unable to change the clock rate at runtime and will
just use whatever frequency the pwm is running at (which is typically set
in the device-tree consumer property).
> So, the PWM driver doesn't know if it can use the bypass or not, it
> doesn't even have the real accurate frequency information (23809524 Hz
> instead of 24MHz) because PWM drivers only deal with periods.
I agree that the driver needs to register as a proper clock provider in
addition to pwm. But what happens if the same PWM clock is requested both from
the clk side and the pwm side?
> With pwm-clock, we loose a precious information along the way (that we
> actually want a clock and not a PWM signal).
> That's ok with simple PWM drivers that don't have multiple input clocks,
> but in this case, without this information, we can't know for sure which
> clock to use.
> And here, for instance, if we ask for a 24MHz clock, pwm-clock will
> requests 42ns (assigned-clocks doesn't help for that matter). The logic
> is to select the highest clock (100MHz) with no prescaler and a duty
> cycle value of 2/4 => we have 25MHz instead of 24MHz.
> And that's a perfectly fine choice for a PMW, because we still can
> change the duty cycle in the range [0-4]/4.
> But obviously for a clock, we don't care about the duty cycle, but more
> about the clock accuracy.
>
> And actually, this PWM is really a PWM AND a real clock when the bypass
> is set.
Make sense to me.
> This series is based onto v6.19-rc4
>
> NB: checkpatch is not happy with patch 2, but it's a false positive.
> It doesn't detect that PWM_XY_SRC_MUX/GATE/DIV are structures, but as
> it's more readable like that, I prefer keeping it that way.
>
> NB2: for geopolitical reasons, I didn't re-use the old series that Paul
> was referring to.
>
> Changes since v3:
> - gather Acked-by/Tested-by
> - fix cast from pointer to integer of different size (kernel test robot
> with arc platform)
> - add devm_action for clk_hw_unregister_composite as suggested by Philipp
> - remove now unused pwm_remove as suggested by Philipp
>
> Changes since v2:
> - use U32_MAX instead of defining UINT32_MAX
> - add a comment on U32_MAX usage in clk_round_rate()
> - change clk_table_div_m (use macros)
> - fix formatting (double space, superfluous comma, extra line feed)
> - fix the parent clock order
> - simplify code by using scoped_guard()
> - add missing const in to_h616_pwm_chip() and rename to
> h616_pwm_from_chip()
> - add/remove missing/superflous error messages
> - rename cnt->period_ticks, duty_cnt->duty_ticks
> - fix PWM_PERIOD_MAX
> - add .remove() callback
> - fix DIV_ROUND_CLOSEST_ULL->DIV_ROUND_UP_ULL
> - add H616_ prefix
> - protect _reg in macros
> - switch to waveforms instead of apply/get_state
> - shrink struct h616_pwm_channel
> - rebase on v6.19-rc4
>
> Changes since v1:
> - rebase onto v6.19-rc1
> - add missing headers
> - remove MODULE_ALIAS (suggested by Krzysztof)
> - use sun4i-pwm binding instead of creating a new one (suggested by Krzysztof)
> - retrieve the parent clocks from the devicetree
> - switch num_parents to unsigned int
>
> Richard Genoud (4):
> dt-bindings: pwm: allwinner: add h616 pwm compatible
> pwm: sun50i: Add H616 PWM support
> arm64: dts: allwinner: h616: add PWM controller
> MAINTAINERS: Add entry on Allwinner H616 PWM driver
>
> .../bindings/pwm/allwinner,sun4i-a10-pwm.yaml | 19 +-
> MAINTAINERS | 5 +
> .../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 47 +
> drivers/pwm/Kconfig | 12 +
> drivers/pwm/Makefile | 1 +
> drivers/pwm/pwm-sun50i-h616.c | 936 ++++++++++++++++++
> 6 files changed, 1019 insertions(+), 1 deletion(-)
> create mode 100644 drivers/pwm/pwm-sun50i-h616.c
>
>
> base-commit: 11439c4635edd669ae435eec308f4ab8a0804808
--
Paul Kocialkowski,
Independent contractor - sys-base - https://www.sys-base.io/
Free software developer - https://www.paulk.fr/
Expert in multimedia, graphics and embedded hardware support with Linux.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* [PATCH RFC 12/12] drm/mediatek: Use dp_connector helpers to report link training state
From: Kory Maincent @ 2026-04-09 17:08 UTC (permalink / raw)
To: Jani Nikula, Rodrigo Vivi, Joonas Lahtinen, Tvrtko Ursulin,
David Airlie, Simona Vetter, Dave Airlie, Jesse Barnes,
Eric Anholt, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Chun-Kuang Hu, Philipp Zabel,
Matthias Brugger, AngeloGioacchino Del Regno, Chris Wilson
Cc: Thomas Petazzoni, Mark Yacoub, Sean Paul, Louis Chauvet,
intel-gfx, intel-xe, dri-devel, linux-kernel, linux-mediatek,
linux-arm-kernel, Simona Vetter, Kory Maincent
In-Reply-To: <20260409-feat_link_cap-v1-0-7069e8199ce2@bootlin.com>
Set DRM_BRIDGE_OP_DP and populate dp_link_train_caps with the supported
link rates, lane counts, voltage swing and pre-emphasis levels so the
bridge connector uses drmm_connector_dp_init() and exposes the link
training state properties to userspace.
Store per-lane voltage swing and pre-emphasis values in
mtk_dp_train_info and report the negotiated link parameters via
drm_connector_dp_set_link_train_properties() on training completion.
Clear them via drm_connector_dp_reset_link_train_properties() when a
disconnect is detected in the HPD event thread.
Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
---
This patch has still not been tested. I am in the process of finding the
hardware for that.
---
drivers/gpu/drm/mediatek/mtk_dp.c | 34 +++++++++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c
index c52cc7c2e2006..119718c1374c5 100644
--- a/drivers/gpu/drm/mediatek/mtk_dp.c
+++ b/drivers/gpu/drm/mediatek/mtk_dp.c
@@ -10,6 +10,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_crtc.h>
+#include <drm/drm_dp_connector.h>
#include <drm/drm_edid.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
@@ -72,6 +73,8 @@ struct mtk_dp_train_info {
/* link_rate is in multiple of 0.27Gbps */
int link_rate;
int lane_count;
+ u8 vswing[4];
+ u8 preemphasis[4];
unsigned int channel_eq_pattern;
};
@@ -1561,6 +1564,9 @@ static void mtk_dp_train_update_swing_pre(struct mtk_dp *mtk_dp, int lanes,
mtk_dp_set_swing_pre_emphasis(mtk_dp, lane, swing, preemphasis);
drm_dp_dpcd_writeb(&mtk_dp->aux, DP_TRAINING_LANE0_SET + lane,
val);
+
+ mtk_dp->train_info.vswing[lane] = swing;
+ mtk_dp->train_info.preemphasis[lane] = preemphasis;
}
}
@@ -1812,6 +1818,21 @@ static void mtk_dp_train_change_mode(struct mtk_dp *mtk_dp)
mtk_dp_reset_swing_pre_emphasis(mtk_dp);
}
+static int mtk_dp_report_link_train(struct mtk_dp *mtk_dp)
+{
+ struct drm_connector_dp_link_train dp_link_train;
+
+ dp_link_train.rate = drm_dp_bw_code_to_link_rate(mtk_dp->train_info.link_rate);
+ dp_link_train.nlanes = mtk_dp->train_info.lane_count;
+
+ for (int i = 0; i < mtk_dp->train_info.lane_count; i++) {
+ dp_link_train.v_swing[i] = 1 << mtk_dp->train_info.vswing[i];
+ dp_link_train.pre_emph[i] = 1 << mtk_dp->train_info.preemphasis[i];
+ }
+
+ return drm_connector_dp_set_link_train_properties(mtk_dp->conn, &dp_link_train);
+}
+
static int mtk_dp_training(struct mtk_dp *mtk_dp)
{
int ret;
@@ -1892,7 +1913,7 @@ static int mtk_dp_training(struct mtk_dp *mtk_dp)
mtk_dp_training_set_scramble(mtk_dp, true);
mtk_dp_set_enhanced_frame_mode(mtk_dp);
- return 0;
+ return mtk_dp_report_link_train(mtk_dp);
}
static void mtk_dp_video_enable(struct mtk_dp *mtk_dp, bool enable)
@@ -2004,6 +2025,7 @@ static irqreturn_t mtk_dp_hpd_event_thread(int hpd, void *dev)
mtk_dp->need_debounce = false;
mod_timer(&mtk_dp->debounce_timer,
jiffies + msecs_to_jiffies(100) - 1);
+ drm_connector_dp_reset_link_train_properties(mtk_dp->conn);
} else {
mtk_dp_aux_panel_poweron(mtk_dp, true);
@@ -2742,6 +2764,14 @@ static int mtk_dp_edp_link_panel(struct drm_dp_aux *mtk_aux)
static int mtk_dp_probe(struct platform_device *pdev)
{
+ static const u32 dp_rates[] = {162000, 270000, 540000, 810000};
+ static const struct drm_connector_dp_link_train_caps dp_link_train_caps = {
+ .nlanes = DRM_DP_1LANE | DRM_DP_2LANE | DRM_DP_4LANE,
+ .nrates = ARRAY_SIZE(dp_rates),
+ .rates = dp_rates,
+ .v_swings = DRM_DP_VOLTAGE_SWING_LEVEL_MASK,
+ .pre_emphs = DRM_DP_PRE_EMPH_LEVEL_MASK,
+ };
struct mtk_dp *mtk_dp;
struct device *dev = &pdev->dev;
int ret;
@@ -2809,6 +2839,8 @@ static int mtk_dp_probe(struct platform_device *pdev)
mtk_dp->bridge.of_node = dev->of_node;
mtk_dp->bridge.type = mtk_dp->data->bridge_type;
+ mtk_dp->bridge.dp_link_train_caps = &dp_link_train_caps;
+ mtk_dp->bridge.ops = DRM_BRIDGE_OP_DP;
if (mtk_dp->bridge.type == DRM_MODE_CONNECTOR_eDP) {
/*
--
2.43.0
^ permalink raw reply related
* [PATCH RFC 11/12] drm/bridge: Wire drmm_connector_dp_init() via new DRM_BRIDGE_OP_DP flag
From: Kory Maincent @ 2026-04-09 17:08 UTC (permalink / raw)
To: Jani Nikula, Rodrigo Vivi, Joonas Lahtinen, Tvrtko Ursulin,
David Airlie, Simona Vetter, Dave Airlie, Jesse Barnes,
Eric Anholt, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Chun-Kuang Hu, Philipp Zabel,
Matthias Brugger, AngeloGioacchino Del Regno, Chris Wilson
Cc: Thomas Petazzoni, Mark Yacoub, Sean Paul, Louis Chauvet,
intel-gfx, intel-xe, dri-devel, linux-kernel, linux-mediatek,
linux-arm-kernel, Simona Vetter, Kory Maincent
In-Reply-To: <20260409-feat_link_cap-v1-0-7069e8199ce2@bootlin.com>
Introduce DRM_BRIDGE_OP_DP, a new bridge operation flag for bridges
that provide DisplayPort connector operations with link training support.
Bridges advertising this flag must fill the dp_link_train_caps field in
struct drm_bridge with their link training capabilities.
In drm_bridge_connector_init(), when a bridge sets DRM_BRIDGE_OP_DP,
use drmm_connector_dp_init() instead of the generic drmm_connector_init()
so the connector exposes link training state properties to userspace.
This mirrors the existing pattern used for HDMI bridges.
Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
---
drivers/gpu/drm/display/drm_bridge_connector.c | 26 +++++++++++++++++++++++++-
include/drm/drm_bridge.h | 13 +++++++++++++
2 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c
index 39cc18f78eda1..e20b61bb03f12 100644
--- a/drivers/gpu/drm/display/drm_bridge_connector.c
+++ b/drivers/gpu/drm/display/drm_bridge_connector.c
@@ -13,7 +13,7 @@
#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_bridge_connector.h>
-#include <drm/drm_connector.h>
+#include <drm/drm_dp_connector.h>
#include <drm/drm_device.h>
#include <drm/drm_edid.h>
#include <drm/drm_managed.h>
@@ -108,6 +108,13 @@ struct drm_bridge_connector {
* HDMI Audio infrastructure, if any (see &DRM_BRIDGE_OP_HDMI_AUDIO).
*/
struct drm_bridge *bridge_hdmi_audio;
+ /**
+ * @bridge_dp:
+ *
+ * The bridge in the chain that implements necessary support for the
+ * DisplayPort connector infrastructure, if any (see &DRM_BRIDGE_OP_DP).
+ */
+ struct drm_bridge *bridge_dp;
/**
* @bridge_dp_audio:
*
@@ -766,6 +773,7 @@ static void drm_bridge_connector_put_bridges(struct drm_device *dev, void *data)
drm_bridge_put(bridge_connector->bridge_hdmi_audio);
drm_bridge_put(bridge_connector->bridge_dp_audio);
drm_bridge_put(bridge_connector->bridge_hdmi_cec);
+ drm_bridge_put(bridge_connector->bridge_dp);
}
/**
@@ -898,6 +906,15 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
bridge_connector->bridge_hdmi_audio = drm_bridge_get(bridge);
}
+ if (bridge->ops & DRM_BRIDGE_OP_DP) {
+ if (bridge_connector->bridge_dp)
+ return ERR_PTR(-EBUSY);
+ if (!bridge->dp_link_train_caps)
+ return ERR_PTR(-EINVAL);
+
+ bridge_connector->bridge_dp = drm_bridge_get(bridge);
+ }
+
if (bridge->ops & DRM_BRIDGE_OP_DP_AUDIO) {
if (bridge_connector->bridge_dp_audio)
return ERR_PTR(-EBUSY);
@@ -986,6 +1003,13 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm,
max_bpc);
if (ret)
return ERR_PTR(ret);
+ } else if (bridge_connector->bridge_dp) {
+ ret = drmm_connector_dp_init(drm, connector,
+ &drm_bridge_connector_funcs,
+ bridge_connector->bridge_dp->dp_link_train_caps,
+ connector_type, ddc);
+ if (ret)
+ return ERR_PTR(ret);
} else {
ret = drmm_connector_init(drm, connector,
&drm_bridge_connector_funcs,
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
index a8d67bd9ee505..b3df9dffd5bcc 100644
--- a/include/drm/drm_bridge.h
+++ b/include/drm/drm_bridge.h
@@ -1092,6 +1092,14 @@ enum drm_bridge_ops {
* &drm_bridge_funcs->hdmi_clear_spd_infoframe callbacks.
*/
DRM_BRIDGE_OP_HDMI_SPD_INFOFRAME = BIT(10),
+ /**
+ * @DRM_BRIDGE_OP_DP: The bridge provides DisplayPort connector
+ * operations, including link training support. Bridges that set
+ * this flag must provide DisplayPort-related information and
+ * fill the &drm_bridge->dp_link_train_caps link training
+ * capabilities.
+ */
+ DRM_BRIDGE_OP_DP = BIT(11),
};
/**
@@ -1267,6 +1275,11 @@ struct drm_bridge {
*/
void *hpd_data;
+ /**
+ * @dp_link_train_caps: DisplayPort link training capabilities
+ */
+ const struct drm_connector_dp_link_train_caps *dp_link_train_caps;
+
/**
* @next_bridge: Pointer to the following bridge, automatically put
* when this bridge is freed (i.e. at destroy time). This is for
--
2.43.0
^ permalink raw reply related
* [PATCH RFC 10/12] drm/i915/display/dp: Adopt dp_connector helpers to expose link training state
From: Kory Maincent @ 2026-04-09 17:08 UTC (permalink / raw)
To: Jani Nikula, Rodrigo Vivi, Joonas Lahtinen, Tvrtko Ursulin,
David Airlie, Simona Vetter, Dave Airlie, Jesse Barnes,
Eric Anholt, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Chun-Kuang Hu, Philipp Zabel,
Matthias Brugger, AngeloGioacchino Del Regno, Chris Wilson
Cc: Thomas Petazzoni, Mark Yacoub, Sean Paul, Louis Chauvet,
intel-gfx, intel-xe, dri-devel, linux-kernel, linux-mediatek,
linux-arm-kernel, Simona Vetter, Kory Maincent
In-Reply-To: <20260409-feat_link_cap-v1-0-7069e8199ce2@bootlin.com>
Switch the i915 DP connector initialization from drmm_connector_init()
to drmm_connector_dp_init(), providing the source link capabilities
(supported lane counts, link rates, DSC support, voltage swing and
pre-emphasis levels).
Add intel_dp_report_link_train() to collect the negotiated link
parameters (rate, lane count, DSC enable, per-lane voltage swing and
pre-emphasis) and report them via drm_connector_dp_set_link_train_properties()
once link training completes successfully.
Reset the link training properties via
drm_connector_dp_reset_link_train_properties() when the connector is
reported as disconnected or when the display device is disabled, so
the exposed state always reflects the current link status.
Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
---
drivers/gpu/drm/i915/display/intel_dp.c | 31 +++++++++++++++++++---
.../gpu/drm/i915/display/intel_dp_link_training.c | 25 +++++++++++++++++
2 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 2af64de9c81de..641406bdc0cc9 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -45,6 +45,7 @@
#include <drm/display/drm_hdmi_helper.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
+#include <drm/drm_dp_connector.h>
#include <drm/drm_edid.h>
#include <drm/drm_fixed.h>
#include <drm/drm_managed.h>
@@ -6337,8 +6338,10 @@ intel_dp_detect(struct drm_connector *_connector,
drm_WARN_ON(display->drm,
!drm_modeset_is_locked(&display->drm->mode_config.connection_mutex));
- if (!intel_display_device_enabled(display))
+ if (!intel_display_device_enabled(display)) {
+ drm_connector_dp_reset_link_train_properties(_connector);
return connector_status_disconnected;
+ }
if (!intel_display_driver_check_access(display))
return connector->base.status;
@@ -6388,6 +6391,8 @@ intel_dp_detect(struct drm_connector *_connector,
intel_dp_tunnel_disconnect(intel_dp);
+ drm_connector_dp_reset_link_train_properties(_connector);
+
goto out_unset_edid;
}
@@ -7162,10 +7167,12 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(dig_port);
+ struct drm_connector_dp_link_train_caps link_caps;
struct intel_dp *intel_dp = &dig_port->dp;
struct intel_encoder *encoder = &dig_port->base;
struct drm_device *dev = encoder->base.dev;
enum port port = encoder->port;
+ u32 *rates;
int type;
if (drm_WARN(dev, dig_port->max_lanes < 1,
@@ -7213,8 +7220,25 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
type == DRM_MODE_CONNECTOR_eDP ? "eDP" : "DP",
encoder->base.base.id, encoder->base.name);
- drmm_connector_init(dev, &connector->base, &intel_dp_connector_funcs,
- type, &intel_dp->aux.ddc);
+ intel_dp_set_source_rates(intel_dp);
+ link_caps.nlanes = DRM_DP_1LANE | DRM_DP_2LANE | DRM_DP_4LANE;
+ link_caps.nrates = intel_dp->num_source_rates;
+ rates = kzalloc_objs(*rates, intel_dp->num_source_rates);
+ if (!rates)
+ goto fail;
+
+ for (int i = 0; i < intel_dp->num_source_rates; i++)
+ rates[i] = intel_dp->source_rates[i];
+
+ link_caps.rates = rates;
+ link_caps.dsc = true;
+ link_caps.v_swings = DRM_DP_VOLTAGE_SWING_LEVEL_MASK;
+ link_caps.pre_emphs = DRM_DP_PRE_EMPH_LEVEL_MASK;
+
+ drmm_connector_dp_init(dev, &connector->base, &intel_dp_connector_funcs,
+ &link_caps, type, &intel_dp->aux.ddc);
+ kfree(rates);
+
drm_connector_helper_add(&connector->base, &intel_dp_connector_helper_funcs);
if (drmm_add_action_or_reset(dev, intel_connector_destroy, connector)) {
@@ -7240,7 +7264,6 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
if (!intel_edp_init_connector(intel_dp, connector))
goto fail;
- intel_dp_set_source_rates(intel_dp);
intel_dp_set_common_rates(intel_dp);
intel_dp_reset_link_params(intel_dp);
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index 54c585c59b900..c2fd46a323650 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -25,6 +25,7 @@
#include <linux/iopoll.h>
#include <drm/display/drm_dp_helper.h>
+#include <drm/drm_dp_connector.h>
#include <drm/drm_print.h>
#include "intel_display_core.h"
@@ -1116,6 +1117,27 @@ intel_dp_128b132b_intra_hop(struct intel_dp *intel_dp,
return sink_status & DP_INTRA_HOP_AUX_REPLY_INDICATION ? 1 : 0;
}
+static void intel_dp_report_link_train(struct intel_dp *intel_dp)
+{
+ struct intel_connector *connector = intel_dp->attached_connector;
+ struct drm_connector_dp_link_train dp_link_train;
+
+ dp_link_train.rate = intel_dp->link_rate;
+ dp_link_train.nlanes = intel_dp->lane_count;
+ dp_link_train.dsc_en = connector->dp.dsc_decompression_enabled;
+
+ for (int i = 0; i < intel_dp->lane_count; i++) {
+ int v_swing_level = (intel_dp->train_set[i] &
+ DP_TRAIN_VOLTAGE_SWING_MASK) >> DP_TRAIN_VOLTAGE_SWING_SHIFT;
+ int pre_emph_level = (intel_dp->train_set[i] &
+ DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT;
+ dp_link_train.v_swing[i] = 1 << v_swing_level;
+ dp_link_train.pre_emph[i] = 1 << pre_emph_level;
+ }
+
+ drm_connector_dp_set_link_train_properties(&connector->base, &dp_link_train);
+}
+
/**
* intel_dp_stop_link_train - stop link training
* @intel_dp: DP struct
@@ -1144,6 +1166,9 @@ void intel_dp_stop_link_train(struct intel_dp *intel_dp,
intel_dp_program_link_training_pattern(intel_dp, crtc_state, DP_PHY_DPRX,
DP_TRAINING_PATTERN_DISABLE);
+ if (!intel_dp->is_mst)
+ intel_dp_report_link_train(intel_dp);
+
if (intel_dp_is_uhbr(crtc_state)) {
ret = poll_timeout_us(ret = intel_dp_128b132b_intra_hop(intel_dp, crtc_state),
ret == 0,
--
2.43.0
^ permalink raw reply related
* [PATCH RFC 09/12] drm: Introduce drmm_connector_dp_init() with link training state properties
From: Kory Maincent @ 2026-04-09 17:08 UTC (permalink / raw)
To: Jani Nikula, Rodrigo Vivi, Joonas Lahtinen, Tvrtko Ursulin,
David Airlie, Simona Vetter, Dave Airlie, Jesse Barnes,
Eric Anholt, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Chun-Kuang Hu, Philipp Zabel,
Matthias Brugger, AngeloGioacchino Del Regno, Chris Wilson
Cc: Thomas Petazzoni, Mark Yacoub, Sean Paul, Louis Chauvet,
intel-gfx, intel-xe, dri-devel, linux-kernel, linux-mediatek,
linux-arm-kernel, Simona Vetter, Kory Maincent
In-Reply-To: <20260409-feat_link_cap-v1-0-7069e8199ce2@bootlin.com>
Add a managed DisplayPort connector initialization helper,
drmm_connector_dp_init(), modeled after the existing HDMI counterpart
drmm_connector_hdmi_init(). Cleanup is handled automatically via a
DRM-managed action.
The helper creates the following immutable connector properties to expose
DP link training capabilities and state to userspace:
- num_lanes: bitmask of supported lane counts (1, 2, 4)
- link_rate: Array of supported link rates.
- dsc_en: Display Stream Compression supported
- voltage_swingN: per-lane voltage swing level bitmask
- pre-emphasisN: per-lane pre-emphasis level bitmask
Link rates are passed by the driver in deca-kbps, following the DRM
convention, but exposed to userspace in kbps for clarity.
Two additional helpers are provided to update and reset those properties
at runtime:
- drm_connector_dp_set_link_train_properties()
- drm_connector_dp_reset_link_train_properties()
Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
---
drivers/gpu/drm/Makefile | 1 +
drivers/gpu/drm/drm_dp_connector.c | 344 +++++++++++++++++++++++++++++++++++++
include/drm/drm_connector.h | 38 ++++
include/drm/drm_dp_connector.h | 109 ++++++++++++
4 files changed, 492 insertions(+)
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index e97faabcd7830..8ff08c2fb863e 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -42,6 +42,7 @@ drm-y := \
drm_color_mgmt.o \
drm_colorop.o \
drm_connector.o \
+ drm_dp_connector.o \
drm_crtc.o \
drm_displayid.o \
drm_drv.o \
diff --git a/drivers/gpu/drm/drm_dp_connector.c b/drivers/gpu/drm/drm_dp_connector.c
new file mode 100644
index 0000000000000..b25637a4378d5
--- /dev/null
+++ b/drivers/gpu/drm/drm_dp_connector.c
@@ -0,0 +1,344 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2026 Google
+ * Author: Kory Maincent <kory.maincent@bootlin.com>
+ */
+#include <drm/drm_dp_connector.h>
+#include <drm/drm_print.h>
+#include <linux/list.h>
+
+/**
+ * drm_connector_dp_link_reset_properties() - Reset DisplayPort link configuration
+ * @connector: DRM connector
+ * @dp_link: Link training informations
+ *
+ * Returns: Zero on success, or an errno code otherwise.
+ */
+int
+drm_connector_dp_set_link_train_properties(struct drm_connector *connector,
+ const struct drm_connector_dp_link_train *dp_link_train)
+{
+ u32 lrate = 0;
+ int ret;
+
+ if (!connector)
+ return -ENODEV;
+
+ if (dp_link_train->nlanes && !is_power_of_2(dp_link_train->nlanes & DRM_NLANES_MASK)) {
+ drm_err(connector->dev, "Wrong lane number");
+ return -EINVAL;
+ }
+
+ if (dp_link_train->rate) {
+ struct drm_property_enum *prop_enum;
+ bool found = false;
+
+ list_for_each_entry(prop_enum, &connector->dp.link_rate_property->enum_list, head) {
+ u32 parsed_rate;
+
+ /* Convert dp_link_train->rate from deca-kbps to kbps */
+ if (!kstrtou32(prop_enum->name, 10, &parsed_rate) &&
+ dp_link_train->rate * 10 == parsed_rate) {
+ lrate = 1 << prop_enum->value;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ drm_err(connector->dev, "Wrong rate value");
+ return -EINVAL;
+ }
+ }
+
+ ret = drm_object_property_set_value(&connector->base, connector->dp.nlanes_property,
+ dp_link_train->nlanes);
+ if (ret)
+ return ret;
+
+ ret = drm_object_property_set_value(&connector->base, connector->dp.link_rate_property,
+ lrate);
+ if (ret)
+ return ret;
+
+ if (connector->dp.dsc_en_property) {
+ ret = drm_object_property_set_value(&connector->base, connector->dp.dsc_en_property,
+ dp_link_train->dsc_en);
+ if (ret)
+ return ret;
+ }
+
+ for (int i = 0; i < 4; i++) {
+ if (connector->dp.v_swing_property[i]) {
+ ret = drm_object_property_set_value(&connector->base,
+ connector->dp.v_swing_property[i],
+ dp_link_train->v_swing[i]);
+ if (ret)
+ return ret;
+ }
+
+ if (connector->dp.pre_emph_property[i]) {
+ ret = drm_object_property_set_value(&connector->base,
+ connector->dp.pre_emph_property[i],
+ dp_link_train->pre_emph[i]);
+ if (ret)
+ return ret;
+ }
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_connector_dp_set_link_train_properties);
+
+/**
+ * drm_connector_dp_link_reset_properties() - Reset DisplayPort link configuration
+ * @connector: DRM connector
+ */
+void drm_connector_dp_reset_link_train_properties(struct drm_connector *connector)
+{
+ struct drm_connector_dp_link_train dp_link_train = {0};
+
+ drm_connector_dp_set_link_train_properties(connector, &dp_link_train);
+}
+EXPORT_SYMBOL(drm_connector_dp_reset_link_train_properties);
+
+static int drm_connector_create_nlanes_prop(struct drm_connector *connector,
+ u8 sup_nlanes)
+{
+ static const struct drm_prop_enum_list props[] = {
+ {__builtin_ffs(DRM_DP_1LANE) - 1, "1" },
+ {__builtin_ffs(DRM_DP_2LANE) - 1, "2" },
+ {__builtin_ffs(DRM_DP_4LANE) - 1, "4" },
+ };
+ struct drm_property *prop;
+
+ if (drm_WARN_ON(connector->dev, sup_nlanes != (sup_nlanes & DRM_NLANES_MASK)))
+ return -EINVAL;
+
+ prop = drm_property_create_bitmask(connector->dev, DRM_MODE_PROP_IMMUTABLE,
+ "num_lanes", props, ARRAY_SIZE(props),
+ sup_nlanes);
+ if (!prop)
+ return -ENOMEM;
+
+ drm_object_attach_property(&connector->base, prop, 0);
+
+ connector->dp.nlanes_property = prop;
+
+ return 0;
+}
+
+static int drm_connector_create_lrate_prop(struct drm_connector *connector,
+ u32 sup_nlrates,
+ const u32 *sup_lrates)
+{
+ struct drm_prop_enum_list *props;
+ u32 supp_nlrates_bitmask = 0;
+ struct drm_property *prop;
+ int ret = 0;
+
+ if (!sup_nlrates || !sup_lrates)
+ return 0;
+
+ props = kcalloc(sup_nlrates, sizeof(*props), GFP_KERNEL);
+ if (!props)
+ return -ENOMEM;
+
+ for (int i = 0; i < sup_nlrates; i++) {
+ props[i].type = i;
+ /* Convert deca-kbps to kbps */
+ props[i].name = kasprintf(GFP_KERNEL, "%d", sup_lrates[i] * 10);
+ if (!props[i].name) {
+ while (i--)
+ kfree(props[i].name);
+ kfree(props);
+ return -ENOMEM;
+ }
+ supp_nlrates_bitmask |= 1 << i;
+ }
+
+ prop = drm_property_create_bitmask(connector->dev, DRM_MODE_PROP_IMMUTABLE,
+ "link_rate", props, sup_nlrates,
+ supp_nlrates_bitmask);
+ if (!prop) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ drm_object_attach_property(&connector->base, prop, 0);
+
+ connector->dp.link_rate_property = prop;
+
+out:
+ for (int i = 0; i < sup_nlrates; i++)
+ kfree(props[i].name);
+
+ kfree(props);
+ return ret;
+}
+
+static int drm_connector_create_dsc_prop(struct drm_connector *connector)
+{
+ struct drm_property *prop;
+
+ prop = drm_property_create_bool(connector->dev, DRM_MODE_PROP_IMMUTABLE, "dsc_en");
+ if (!prop)
+ return -ENOMEM;
+
+ drm_object_attach_property(&connector->base, prop, 0);
+
+ connector->dp.dsc_en_property = prop;
+
+ return 0;
+}
+
+static int drm_connector_create_vswing_prop(struct drm_connector *connector,
+ u8 sup_v_swings, int id)
+{
+ static const struct drm_prop_enum_list props[] = {
+ {__builtin_ffs(DRM_DP_VOLTAGE_SWING_LEVEL_0) - 1, "level_0" },
+ {__builtin_ffs(DRM_DP_VOLTAGE_SWING_LEVEL_1) - 1, "level_1" },
+ {__builtin_ffs(DRM_DP_VOLTAGE_SWING_LEVEL_2) - 1, "level_2" },
+ {__builtin_ffs(DRM_DP_VOLTAGE_SWING_LEVEL_3) - 1, "level_3" },
+ };
+ struct drm_property *prop;
+ char str[16];
+
+ if (!sup_v_swings)
+ return 0;
+
+ if (drm_WARN_ON(connector->dev, sup_v_swings != (sup_v_swings &
+ DRM_DP_VOLTAGE_SWING_LEVEL_MASK)))
+ return -EINVAL;
+
+ snprintf(str, sizeof(str), "voltage_swing%d", id);
+ prop = drm_property_create_bitmask(connector->dev, DRM_MODE_PROP_IMMUTABLE,
+ str, props, ARRAY_SIZE(props),
+ sup_v_swings);
+ if (!prop)
+ return -ENOMEM;
+
+ drm_object_attach_property(&connector->base, prop, 0);
+
+ connector->dp.v_swing_property[id] = prop;
+
+ return 0;
+}
+
+static int drm_connector_create_pre_emph_prop(struct drm_connector *connector,
+ u8 sup_pre_emph, int id)
+{
+ static const struct drm_prop_enum_list props[] = {
+ {__builtin_ffs(DRM_DP_PRE_EMPH_LEVEL_0) - 1, "level_0" },
+ {__builtin_ffs(DRM_DP_PRE_EMPH_LEVEL_1) - 1, "level_1" },
+ {__builtin_ffs(DRM_DP_PRE_EMPH_LEVEL_2) - 1, "level_2" },
+ {__builtin_ffs(DRM_DP_PRE_EMPH_LEVEL_3) - 1, "level_3" },
+ };
+ struct drm_property *prop;
+ char str[16];
+
+ if (!sup_pre_emph)
+ return 0;
+
+ if (drm_WARN_ON(connector->dev, sup_pre_emph != (sup_pre_emph &
+ DRM_DP_PRE_EMPH_LEVEL_MASK)))
+ return -EINVAL;
+
+ snprintf(str, sizeof(str), "pre_emphasis%d", id);
+ prop = drm_property_create_bitmask(connector->dev, DRM_MODE_PROP_IMMUTABLE,
+ str, props, ARRAY_SIZE(props),
+ sup_pre_emph);
+ if (!prop)
+ return -ENOMEM;
+
+ drm_object_attach_property(&connector->base, prop, 0);
+
+ connector->dp.pre_emph_property[id] = prop;
+
+ return 0;
+}
+
+static int
+drm_connector_dp_create_props(struct drm_connector *connector,
+ const struct drm_connector_dp_link_train_caps *dp_link_train_caps)
+{
+ u8 nlanes;
+ int ret;
+
+ ret = drm_connector_create_nlanes_prop(connector, dp_link_train_caps->nlanes);
+ if (ret)
+ return ret;
+
+ ret = drm_connector_create_lrate_prop(connector, dp_link_train_caps->nrates,
+ dp_link_train_caps->rates);
+ if (ret)
+ return ret;
+
+ if (dp_link_train_caps->dsc) {
+ ret = drm_connector_create_dsc_prop(connector);
+ if (ret)
+ return ret;
+ }
+
+ nlanes = 1 << (fls(dp_link_train_caps->nlanes) - 1);
+ for (int i = 0; i < nlanes; i++) {
+ ret = drm_connector_create_vswing_prop(connector,
+ dp_link_train_caps->v_swings, i);
+ if (ret)
+ return ret;
+
+ ret = drm_connector_create_pre_emph_prop(connector,
+ dp_link_train_caps->pre_emphs, i);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * drmm_connector_dp_init - Init a preallocated DisplayPort connector
+ * @dev: DRM device
+ * @connector: A pointer to the DisplayPort connector to init
+ * @funcs: callbacks for this connector
+ * @dp_link_train_caps: DisplayPort link training capabilities. The pointer
+ * is not kept by the DRM core
+ * @connector_type: user visible type of the connector
+ * @ddc: optional pointer to the associated ddc adapter
+ *
+ * Initialises a preallocated DisplayPort connector. Connectors can be
+ * subclassed as part of driver connector objects.
+ *
+ * Cleanup is automatically handled with a call to
+ * drm_connector_cleanup() in a DRM-managed action.
+ *
+ * The connector structure should be allocated with drmm_kzalloc().
+ *
+ * The @drm_connector_funcs.destroy hook must be NULL.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drmm_connector_dp_init(struct drm_device *dev,
+ struct drm_connector *connector,
+ const struct drm_connector_funcs *funcs,
+ const struct drm_connector_dp_link_train_caps *dp_link_train_caps,
+ int connector_type,
+ struct i2c_adapter *ddc)
+{
+ int ret;
+
+ if (!(connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
+ connector_type == DRM_MODE_CONNECTOR_eDP))
+ return -EINVAL;
+
+ if (!dp_link_train_caps)
+ return -EINVAL;
+
+ ret = drmm_connector_init(dev, connector, funcs, connector_type, ddc);
+ if (ret)
+ return ret;
+
+ return drm_connector_dp_create_props(connector, dp_link_train_caps);
+}
+EXPORT_SYMBOL(drmm_connector_dp_init);
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index f83f28cae2075..df3a71fed35b1 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1987,6 +1987,39 @@ struct drm_connector_cec {
void *data;
};
+/**
+ * struct drm_connector_dp - DRM Connector DisplayPort-related structure
+ */
+struct drm_connector_dp {
+ /**
+ * @nlanes_property: Connector property to report the number of lanes
+ */
+ struct drm_property *nlanes_property;
+
+ /**
+ * @link_rate_property: Connector property to report the link rate
+ */
+ struct drm_property *link_rate_property;
+
+ /**
+ * @dsc_en_property: Connector property to report the Display Stream
+ * Compression supporrt
+ */
+ struct drm_property *dsc_en_property;
+
+ /**
+ * @v_swing_property: Connector property to report the voltage
+ * swing per lane
+ */
+ struct drm_property *v_swing_property[4];
+
+ /**
+ * @pre_emph_property: Connector property to report the
+ * pre-emphasis per lane
+ */
+ struct drm_property *pre_emph_property[4];
+};
+
/**
* struct drm_connector - central DRM connector control structure
*
@@ -2410,6 +2443,11 @@ struct drm_connector {
* @cec: CEC-related data.
*/
struct drm_connector_cec cec;
+
+ /**
+ * @dp: DisplayPort-related variable and properties.
+ */
+ struct drm_connector_dp dp;
};
#define obj_to_connector(x) container_of(x, struct drm_connector, base)
diff --git a/include/drm/drm_dp_connector.h b/include/drm/drm_dp_connector.h
new file mode 100644
index 0000000000000..77d2f4bb6df68
--- /dev/null
+++ b/include/drm/drm_dp_connector.h
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef DRM_DP_CONNECTOR_H_
+#define DRM_DP_CONNECTOR_H_
+
+#include <drm/drm_connector.h>
+
+#define DRM_DP_1LANE BIT(0)
+#define DRM_DP_2LANE BIT(1)
+#define DRM_DP_4LANE BIT(2)
+#define DRM_NLANES_MASK (DRM_DP_1LANE | DRM_DP_2LANE | DRM_DP_4LANE)
+#define DRM_DP_VOLTAGE_SWING_LEVEL_0 BIT(0)
+#define DRM_DP_VOLTAGE_SWING_LEVEL_1 BIT(1)
+#define DRM_DP_VOLTAGE_SWING_LEVEL_2 BIT(2)
+#define DRM_DP_VOLTAGE_SWING_LEVEL_3 BIT(3)
+#define DRM_DP_VOLTAGE_SWING_LEVEL_MASK (DRM_DP_VOLTAGE_SWING_LEVEL_0 | \
+ DRM_DP_VOLTAGE_SWING_LEVEL_1 | \
+ DRM_DP_VOLTAGE_SWING_LEVEL_2 | \
+ DRM_DP_VOLTAGE_SWING_LEVEL_3)
+#define DRM_DP_PRE_EMPH_LEVEL_0 BIT(0)
+#define DRM_DP_PRE_EMPH_LEVEL_1 BIT(1)
+#define DRM_DP_PRE_EMPH_LEVEL_2 BIT(2)
+#define DRM_DP_PRE_EMPH_LEVEL_3 BIT(3)
+#define DRM_DP_PRE_EMPH_LEVEL_MASK (DRM_DP_PRE_EMPH_LEVEL_0 | \
+ DRM_DP_PRE_EMPH_LEVEL_1 | \
+ DRM_DP_PRE_EMPH_LEVEL_2 | \
+ DRM_DP_PRE_EMPH_LEVEL_3)
+
+/**
+ * struct drm_connector_dp_link_train_caps - DRM DisplayPort link training
+ * capabilities
+ */
+struct drm_connector_dp_link_train_caps {
+ /**
+ * @nlanes: Bitmask of lanes number supported
+ */
+ u8 nlanes;
+
+ /**
+ * @nrates: Number of link rates supported
+ */
+ u32 nrates;
+
+ /**
+ * @rates: Array listing the supported link rates in deca-kbps
+ */
+ const u32 *rates;
+
+ /**
+ * @dsc: Display Stream Compression supported
+ */
+ bool dsc;
+
+ /**
+ * @v_swings: Bitmask of voltage swing level supported
+ */
+ u8 v_swings;
+
+ /**
+ * @pre_emphs: Bitmask of pre-emphasis level supported
+ */
+ u8 pre_emphs;
+};
+
+/**
+ * struct drm_connector_dp_link_train - DRM DisplayPort link training
+ * information report
+ */
+struct drm_connector_dp_link_train {
+ /**
+ * @nlanes: The number of lanes used
+ */
+ u8 nlanes;
+
+ /**
+ * @rates: Link rate value selected in deca-kbps
+ */
+ u32 rate;
+
+ /**
+ * @dsc: Display Stream Compression enabled
+ */
+ bool dsc_en;
+
+ /**
+ * @v_swings: Array listing the bitmask voltage swing level per lanes
+ */
+ u8 v_swing[4];
+
+ /**
+ * @pre_emph: Array listing the bitmask pre-emphasis level per lanes
+ */
+ u8 pre_emph[4];
+};
+
+int drmm_connector_dp_init(struct drm_device *dev,
+ struct drm_connector *connector,
+ const struct drm_connector_funcs *funcs,
+ const struct drm_connector_dp_link_train_caps *dp_link_train_caps,
+ int connector_type,
+ struct i2c_adapter *ddc);
+
+int
+drm_connector_dp_set_link_train_properties(struct drm_connector *con,
+ const struct drm_connector_dp_link_train *dp_link_train);
+
+void drm_connector_dp_reset_link_train_properties(struct drm_connector *connector);
+
+#endif // DRM_DP_CONNECTOR_H_
--
2.43.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox