* Re: [PATCH] clocksource/drivers/arm_arch_timer: Workaround bcm2712 broken EL2 virtual timer
From: Jon Hunter @ 2026-07-27 13:07 UTC (permalink / raw)
To: Marc Zyngier
Cc: linux-kernel, linux-arm-kernel, John, Daniel Drake,
Marek Szyprowski, Florian Fainelli, Daniel Lezcano,
Thomas Gleixner, Mark Rutland, linux-tegra@vger.kernel.org
In-Reply-To: <8633xadlv3.wl-maz@kernel.org>
On 23/07/2026 11:46, Marc Zyngier wrote:
...
>> Hmmm, I am looking at this spec [0] and it says ...
>>
>> "The GIC-400 implements the interrupt types:
>> 16 Software Generated Interrupts (SGIs).
>> 6 external Private Peripheral Interrupts (PPIs) for each processor.
>> 1 internal PPI for each processor."
>>
>> The table in [1] shows interrupts for non-sec, sec, virt and
>> hypervisor timers, but I don't see a hyp-virt.
>
> This documentation was never updated past 2012, which predates ARMv8.1
> (go complain to ARM). But the IP does support it:
>
> [ 0.000000] Machine model: Khadas VIM3L
> [...]
> [ 0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
> [ 0.000000] Root IRQ handler: gic_handle_irq
> [ 0.000000] GIC: Using split EOI/Deactivate mode
> [ 0.000000] rcu: srcu_init: Setting srcu_struct sizes based on contention.
> [ 0.000000] arch_timer: cp15 timer running at 24.00MHz (hyp-virt).
> [ 0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x588fe9dc0, max_idle_ns: 440795202592 ns
> [ 0.000000] sched_clock: 56 bits at 24MHz, resolution 41ns, wraps every 4398046511097ns
>
> GIC400, A55 cores. Produced by one of the worse SoC vendor on this
> side of the galaxy.
>
> And the signal you are looking for is the one labelled as "Legacy FIQ
> signal" (PPI12, aka INTID 28). The labels are purely indicative of
> what you *could* connect to it, not a requirement.
>
> Anyway, this is beside the point. Even if the IP didn't support it,
> you shouldn't end-up with a design that explicitly contradict the
> architecture, because that's the contract SW relies on.
Got it. Armed with this information I went back to the h/w folks and was
able to track down the right person. I have now learnt that this timer
interrupt is hooked up to PPI15 for Tegra194 and using that I now see ...
[ 0.000000] Machine model: NVIDIA Jetson AGX Xavier Developer Kit
...
[ 0.000000] arch_timer: cp15 timer running at 31.25MHz (hyp-virt).
I will post a patch to fix this for Tegra194.
Jon
--
nvpublic
^ permalink raw reply
* Re: [RFC PATCH 12/36] arm64: entry: replace DAIF helpers with entry helpers
From: Vladimir Murzin @ 2026-07-27 13:05 UTC (permalink / raw)
To: Liao, Chang, linux-arm-kernel
Cc: mark.rutland, maz, ruanjinjie, catalin.marinas, will
In-Reply-To: <6bfbb77f-6c98-44ba-a396-b5d5287d190d@huawei.com>
On 7/14/26 13:14, Liao, Chang wrote:
> Hi, Vladimir and Ada,
>
> 在 2026/7/9 20:13, Vladimir Murzin 写道:
>> From: Ada Couprie Diaz <ada.coupriediaz@arm.com>
>>
>> Replace all uses of the `local_daif_...` helpers in `entry-common.c`
>> with the new entry-specific exception masking helpers.
>>
>> Also replace `local_irq_disable()` with a switch to NOIRQ context
>> using the new helpers. This provides:
>>
>> - consistency checks for hardware state
>>
>> - a unified style for managing exception context
>>
>> Now that exception context is tracked explicitly, involuntary kernel
>> preemption can be optimized. We either preempt:
>>
>> - from PROCESS exception context, or
>>
>> - when returning from an interrupt handler, where the GIC code
>> switches from NONMI to NOIRQ exception context
>>
>> To support this split, divide `arm64_exit_to_kernel_mode()` into
>> preempt, non-preempt, and dispatch parts.
>>
>> Remove `local_daif_inherit()`, since it is no longer used.
>>
>> Now that both the irqflags API and entry code handle DAIF and PMR
>> correctly, remove `GIC_PRIO_PSR_I_SET` from the PMR value set by
>> `kernel_entry` in `entry.S` and by `init_gic_priority_masking()` in
>> `kernel/smp.c`.
>>
>> The `local_daif_...` helpers and other specialized code still use
>> `GIC_PRIO_PSR_I_SET` for now; this commit does not change their
>> behavior.
>>
>> Signed-off-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
>> Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com>
>> ---
>> arch/arm64/include/asm/daifflags.h | 22 ---
>> arch/arm64/kernel/entry-common.c | 272 ++++++++++++++++++++---------
>> arch/arm64/kernel/entry.S | 2 +-
>> arch/arm64/kernel/smp.c | 2 +-
>> 4 files changed, 190 insertions(+), 108 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/daifflags.h b/arch/arm64/include/asm/daifflags.h
>> index 56341578e7e3..6b14ec4d4dbe 100644
>> --- a/arch/arm64/include/asm/daifflags.h
>> +++ b/arch/arm64/include/asm/daifflags.h
>> @@ -120,28 +120,6 @@ static __always_inline void local_daif_restore(unsigned long flags)
>> trace_hardirqs_off();
>> }
>>
>> -/*
>> - * Called by synchronous exception handlers to restore the DAIF bits that were
>> - * modified by taking an exception.
>> - */
>> -static __always_inline void local_daif_inherit(struct pt_regs *regs)
>> -{
>> - unsigned long flags = regs->pstate & DAIF_MASK;
>> -
>> - if (!regs_irqs_disabled(regs))
>> - trace_hardirqs_on();
>> -
>> - if (system_uses_irq_prio_masking())
>> - gic_write_pmr(regs->pmr);
>> -
>> - /*
>> - * We can't use local_daif_restore(regs->pstate) here as
>> - * system_has_prio_mask_debugging() won't restore the I bit if it can
>> - * use the pmr instead.
>> - */
>> - write_sysreg(flags, daif);
>> -}
>> -
>> /*
>> * During early boot, we unmask PSR.DA before the GIC has been set up.
>> * If we use IRQ priority masking, the PMR and PSR will be out of sync
>> diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
>> index 2be42d7f4eaa..a13653b228b7 100644
>> --- a/arch/arm64/kernel/entry-common.c
>> +++ b/arch/arm64/kernel/entry-common.c
>> @@ -18,11 +18,11 @@
>> #include <linux/thread_info.h>
>>
>> #include <asm/cpufeature.h>
>> -#include <asm/daifflags.h>
>> #include <asm/esr.h>
>> #include <asm/exception.h>
>> #include <asm/fpsimd.h>
>> #include <asm/irq_regs.h>
>> +#include <asm/interrupts/entry.h>
>> #include <asm/kprobes.h>
>> #include <asm/mmu.h>
>> #include <asm/processor.h>
>> @@ -52,12 +52,11 @@ static noinstr irqentry_state_t arm64_enter_from_kernel_mode(struct pt_regs *reg
>> * After this function returns it is not safe to call regular kernel code,
>> * instrumentable code, or any code which may trigger an exception.
>> */
>> -static void noinstr arm64_exit_to_kernel_mode(struct pt_regs *regs,
>> - irqentry_state_t state)
>> +static void noinstr __arm64_exit_to_kernel_mode(struct pt_regs *regs,
>> + irqentry_state_t state,
>> + arm64_exc_hwstate_t hwstate)
>> {
>> - local_irq_disable();
>> - irqentry_exit_to_kernel_mode_preempt(regs, state);
>> - local_daif_mask();
>> + arm64_mask_exc_context(hwstate);
>> mte_check_tfsr_exit();
>> irqentry_exit_to_kernel_mode_after_preempt(regs, state);
>> }
>> @@ -69,6 +68,30 @@ static __always_inline void arm64_syscall_enter_from_user_mode(struct pt_regs *r
>> sme_enter_from_user_mode();
>> }
>>
>> +/*
>> + * We are returning from the context which allows involuntary kernel preemption
>> + */
>> +static void noinstr arm64_exit_to_kernel_mode_preempt(struct pt_regs *regs,
>> + irqentry_state_t state,
>> + arm64_exc_hwstate_t hwstate)
>> +{
>> + irqentry_exit_to_kernel_mode_preempt(regs, state);
>> + __arm64_exit_to_kernel_mode(regs, state, hwstate);
>> +}
>> +
>> +static void noinstr arm64_exit_to_kernel_mode(struct pt_regs *regs,
>> + irqentry_state_t state,
>> + arm64_exc_hwstate_t hwstate)
>> +{
>> + if (!arch_irqs_disabled_flags(hwstate.flags)) {
>> + hwstate = arm64_lift_exc_context(hwstate, NOIRQ_CONTEXT);
>> + arm64_exit_to_kernel_mode_preempt(regs, state, hwstate);
>> + return;
>> + }
>> +
>> + __arm64_exit_to_kernel_mode(regs, state, hwstate);
>> +}
>> +
>> /*
>> * Handle IRQ/context state management when entering from user mode.
>> * Before this function is called it is not safe to call regular kernel code,
>> @@ -82,11 +105,12 @@ static __always_inline void arm64_enter_from_user_mode(struct pt_regs *regs)
>> sme_enter_from_user_mode();
>> }
>>
>> -static __always_inline void arm64_syscall_exit_to_user_mode(struct pt_regs *regs)
>> +static __always_inline void arm64_syscall_exit_to_user_mode(struct pt_regs *regs,
>> + arm64_exc_hwstate_t hwstate)
>> {
>> - local_irq_disable();
>> + hwstate = arm64_lift_exc_context(hwstate, NOIRQ_CONTEXT);
>> syscall_exit_to_user_mode_prepare(regs);
>> - local_daif_mask();
>> + arm64_mask_exc_context(hwstate);
> To be honest, arm64_mask_exc_context() is not quite self-explanatory. To make the code
> more readable, could we use arm64_lift_exc_context(hwstate, CRITICAL_CONTEXT) directly
> here instead?
>
That suggestion is similar to one of my early implementations. One
piece of offline feedback I received was that, in most cases, we
only need simple unmask/mask operations, with only a few cases
requiring something more involved. The idea was therefore to keep
the common and boring cases using unmask/mask, while using
drop/lift only for the non-trivial cases so they immediately stand
out.
I'm more than happy to revisit if there is consesus on use expicit
drop/lift everywhere...
>> sme_exit_to_user_mode();
>> mte_check_tfsr_exit();
>> exit_to_user_mode();
>> @@ -97,11 +121,12 @@ static __always_inline void arm64_syscall_exit_to_user_mode(struct pt_regs *regs
>> * After this function returns it is not safe to call regular kernel code,
>> * instrumentable code, or any code which may trigger an exception.
>> */
>> -static __always_inline void arm64_exit_to_user_mode(struct pt_regs *regs)
>> +static __always_inline void arm64_exit_to_user_mode(struct pt_regs *regs,
>> + arm64_exc_hwstate_t hwstate)
>> {
>> - local_irq_disable();
>> + hwstate = arm64_lift_exc_context(hwstate, NOIRQ_CONTEXT);
>> irqentry_exit_to_user_mode_prepare(regs);
>> - local_daif_mask();
>> + arm64_mask_exc_context(hwstate);
>> sme_exit_to_user_mode();
>> mte_check_tfsr_exit();
>> exit_to_user_mode();
> Looking through the exception exit paths from EL0 to user mode, they all seem to boil down
> to two distinct patterns of exception mask transitions:
>
> 1. Interrupts (e.g., el0_interrupt): Transition goes from NOIRQ_CONTEXT to CRITICAL_CONTEXT.
> 2. Other exceptions (e.g., el0_svc, el0_error, ret_from_fork): Transition goes from
> PROCESS_CONTEXT to CRITICAL_CONTEXT.
>
> Currently, these two helper functions share a lot of duplicate boilerplate code and
> hide these transitions behind less self-explanatory helpers like arm64_mask_exc_context().
> To make the state-machine transitions explicit and unify the exit flow, I would suggest
> reworking these helpers as follows:
>
> /* Prepare for syscall exit by lifting the implicit PROCESS_CONTEXT to NOIRQ_CONTEXT */
> static __always_inline arm64_exc_hwstate_t
> arm64_syscall_exit_to_user_mode_prepare(struct pt_regs *regs)
> {
> arm64_exc_hwstate_t hwstate =
> arm64_lift_exc_context(arm64_exc_hwstate_of_context(PROCESS_CONTEXT), NOIRQ_CONTEXT);
> syscall_exit_to_user_mode_prepare(regs);
> return hwstate;
> }
>
> /* Prepare for other EL0 exceptions exit by lifting the inherited hwstate to NOIRQ_CONTEXT */
> static __always_inline arm64_exc_hwstate_t
> arm64_exit_to_user_mode_prepare(struct pt_regs *regs, arm64_exc_hwstate_t hwstate)
> {
> hwstate = arm64_lift_exc_context(hwstate, NORIRQ_CONTEXT);
> irqentry_exit_to_user_mode_prepare(regs);
> return hwstate;
> }
>
> /* Finalize the exit by lifting to CRITICAL_CONTEXT before entering assembly world */
> static __always_inline
> void arm64_exit_to_user_mode(arm64_exc_hwstate_t hwstate)
> {
> arm64_lift_exc_context(hwstate, CRITICAL_CONTEXT);
> sme_exit_to_user_mode();
> mte_check_tfsr_exit();
> exit_to_user_mode();
> }
>
> asmlinkage void noinstr asm_exit_to_user_mode(struct pt_regs *regs)
> {
> arm64_exc_hwstate_t hwstate = arm64_syscall_exit_to_user_mode_prepare(regs);
> arm64_exit_to_user_mode(hwstate);
> }
>
I don't have a strong opinion on this. If there is strong support
for going that way, I'm happy to follow. The only thing I'd point
out is that this would probably need to be a separate patch,
either as a preparatory step or as a later optimization.
Cheers
Vladimir
>> @@ -109,7 +134,10 @@ static __always_inline void arm64_exit_to_user_mode(struct pt_regs *regs)
>>
>> asmlinkage void noinstr asm_exit_to_user_mode(struct pt_regs *regs)
>> {
>> - arm64_syscall_exit_to_user_mode(regs);
>> + arm64_exc_hwstate_t hwstate = arm64_exc_hwstate_of_context(PROCESS_CONTEXT);
>> +
>> + arm64_syscall_exit_to_user_mode(regs, hwstate);
>> + arm64_debug_exc_context(CRITICAL_CONTEXT);
>> }
>>
>> /*
>> @@ -315,63 +343,69 @@ UNHANDLED(el1t, 64, error)
>> static void noinstr el1_abort(struct pt_regs *regs, unsigned long esr)
>> {
>> unsigned long far = read_sysreg(far_el1);
>> + arm64_exc_hwstate_t hwstate;
>> irqentry_state_t state;
>>
>> state = arm64_enter_from_kernel_mode(regs);
>> - local_daif_inherit(regs);
>> + hwstate = arm64_inherit_exc_context(regs);
>> do_mem_abort(far, esr, regs);
>> - arm64_exit_to_kernel_mode(regs, state);
>> + arm64_exit_to_kernel_mode(regs, state, hwstate);
>> }
>>
>> static void noinstr el1_pc(struct pt_regs *regs, unsigned long esr)
>> {
>> unsigned long far = read_sysreg(far_el1);
>> + arm64_exc_hwstate_t hwstate;
>> irqentry_state_t state;
>>
>> state = arm64_enter_from_kernel_mode(regs);
>> - local_daif_inherit(regs);
>> + hwstate = arm64_inherit_exc_context(regs);
>> do_sp_pc_abort(far, esr, regs);
>> - arm64_exit_to_kernel_mode(regs, state);
>> + arm64_exit_to_kernel_mode(regs, state, hwstate);
>> }
>>
>> static void noinstr el1_undef(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> irqentry_state_t state;
>>
>> state = arm64_enter_from_kernel_mode(regs);
>> - local_daif_inherit(regs);
>> + hwstate = arm64_inherit_exc_context(regs);
>> do_el1_undef(regs, esr);
>> - arm64_exit_to_kernel_mode(regs, state);
>> + arm64_exit_to_kernel_mode(regs, state, hwstate);
>> }
>>
>> static void noinstr el1_bti(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> irqentry_state_t state;
>>
>> state = arm64_enter_from_kernel_mode(regs);
>> - local_daif_inherit(regs);
>> + hwstate = arm64_inherit_exc_context(regs);
>> do_el1_bti(regs, esr);
>> - arm64_exit_to_kernel_mode(regs, state);
>> + arm64_exit_to_kernel_mode(regs, state, hwstate);
>> }
>>
>> static void noinstr el1_gcs(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> irqentry_state_t state;
>>
>> state = arm64_enter_from_kernel_mode(regs);
>> - local_daif_inherit(regs);
>> + hwstate = arm64_inherit_exc_context(regs);
>> do_el1_gcs(regs, esr);
>> - arm64_exit_to_kernel_mode(regs, state);
>> + arm64_exit_to_kernel_mode(regs, state, hwstate);
>> }
>>
>> static void noinstr el1_mops(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> irqentry_state_t state;
>>
>> state = arm64_enter_from_kernel_mode(regs);
>> - local_daif_inherit(regs);
>> + hwstate = arm64_inherit_exc_context(regs);
>> do_el1_mops(regs, esr);
>> - arm64_exit_to_kernel_mode(regs, state);
>> + arm64_exit_to_kernel_mode(regs, state, hwstate);
>> }
>>
>> static void noinstr el1_breakpt(struct pt_regs *regs, unsigned long esr)
>> @@ -431,12 +465,13 @@ static void noinstr el1_brk64(struct pt_regs *regs, unsigned long esr)
>>
>> static void noinstr el1_fpac(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> irqentry_state_t state;
>>
>> state = arm64_enter_from_kernel_mode(regs);
>> - local_daif_inherit(regs);
>> + hwstate = arm64_inherit_exc_context(regs);
>> do_el1_fpac(regs, esr);
>> - arm64_exit_to_kernel_mode(regs, state);
>> + arm64_exit_to_kernel_mode(regs, state, hwstate);
>> }
>>
>> asmlinkage void noinstr el1h_64_sync_handler(struct pt_regs *regs)
>> @@ -486,16 +521,20 @@ asmlinkage void noinstr el1h_64_sync_handler(struct pt_regs *regs)
>> default:
>> __panic_unhandled(regs, "64-bit el1h sync", esr);
>> }
>> +
>> + arm64_debug_exc_context(CRITICAL_CONTEXT);
>> }
>>
>> static __always_inline void __el1_pnmi(struct pt_regs *regs,
>> void (*handler)(struct pt_regs *))
>> {
>> + arm64_exc_hwstate_t hwstate;
>> irqentry_state_t state;
>>
>> state = irqentry_nmi_enter(regs);
>> + hwstate = arm64_unmask_exc_context(NONMI_CONTEXT);
>> do_interrupt_handler(regs, handler);
>> - local_daif_mask();
>> + arm64_mask_exc_context(hwstate);
>> irqentry_nmi_exit(regs, state);
>> }
>>
>> @@ -506,21 +545,32 @@ static __always_inline void __el1_irq(struct pt_regs *regs,
>>
>> state = arm64_enter_from_kernel_mode(regs);
>>
>> + arm64_unmask_exc_context(NONMI_CONTEXT);
>> +
>> irq_enter_rcu();
>> do_interrupt_handler(regs, handler);
>> irq_exit_rcu();
>>
>> - arm64_exit_to_kernel_mode(regs, state);
>> + /*
>> + * If pseudo-NMIs are enabled and the interrupted context had
>> + * IRQs unmasked, the interrupt handler will have cleared DAIF
>> + * and switched to PMR masking in order to handle
>> + * NMIs. Otherwise it would keep IF. In both cases on return
>> + * we effectivly have NOIRQ_CONTEXT - keep track of it
>> + */
>> + arm64_debug_exc_context(NOIRQ_CONTEXT);
>> + arm64_exit_to_kernel_mode_preempt(regs, state, arm64_exc_hwstate_of_context(NOIRQ_CONTEXT));
>> }
>> +
>> static void noinstr el1_interrupt(struct pt_regs *regs,
>> void (*handler)(struct pt_regs *))
>> {
>> - write_sysreg(DAIF_PROCCTX_NOIRQ, daif);
>> -
>> if (IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) && regs_irqs_disabled(regs))
>> __el1_pnmi(regs, handler);
>> else
>> __el1_irq(regs, handler);
>> +
>> + arm64_debug_exc_context(CRITICAL_CONTEXT);
>> }
>>
>> asmlinkage void noinstr el1h_64_irq_handler(struct pt_regs *regs)
>> @@ -536,28 +586,31 @@ asmlinkage void noinstr el1h_64_fiq_handler(struct pt_regs *regs)
>> asmlinkage void noinstr el1h_64_error_handler(struct pt_regs *regs)
>> {
>> unsigned long esr = read_sysreg(esr_el1);
>> + arm64_exc_hwstate_t hwstate;
>> irqentry_state_t state;
>>
>> - local_daif_restore(DAIF_ERRCTX);
>> + hwstate = arm64_unmask_exc_context(ERROR_CONTEXT);
>> state = irqentry_nmi_enter(regs);
>> do_serror(regs, esr);
>> - local_daif_mask();
>> + arm64_mask_exc_context(hwstate);
>> irqentry_nmi_exit(regs, state);
>> }
>>
>> static void noinstr el0_da(struct pt_regs *regs, unsigned long esr)
>> {
>> unsigned long far = read_sysreg(far_el1);
>> + arm64_exc_hwstate_t hwstate;
>>
>> arm64_enter_from_user_mode(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> do_mem_abort(far, esr, regs);
>> - arm64_exit_to_user_mode(regs);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_ia(struct pt_regs *regs, unsigned long esr)
>> {
>> unsigned long far = read_sysreg(far_el1);
>> + arm64_exc_hwstate_t hwstate;
>>
>> /*
>> * We've taken an instruction abort from userspace and not yet
>> @@ -568,114 +621,139 @@ static void noinstr el0_ia(struct pt_regs *regs, unsigned long esr)
>> arm64_apply_bp_hardening();
>>
>> arm64_enter_from_user_mode(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> do_mem_abort(far, esr, regs);
>> - arm64_exit_to_user_mode(regs);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_fpsimd_acc(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> +
>> arm64_enter_from_user_mode(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> do_fpsimd_acc(esr, regs);
>> - arm64_exit_to_user_mode(regs);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_sve_acc(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> +
>> arm64_enter_from_user_mode(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> do_sve_acc(esr, regs);
>> - arm64_exit_to_user_mode(regs);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_sme_acc(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> +
>> arm64_enter_from_user_mode(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> do_sme_acc(esr, regs);
>> - arm64_exit_to_user_mode(regs);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_fpsimd_exc(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> +
>> arm64_enter_from_user_mode(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> do_fpsimd_exc(esr, regs);
>> - arm64_exit_to_user_mode(regs);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_sys(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> +
>> arm64_enter_from_user_mode(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> do_el0_sys(esr, regs);
>> - arm64_exit_to_user_mode(regs);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_pc(struct pt_regs *regs, unsigned long esr)
>> {
>> unsigned long far = read_sysreg(far_el1);
>> + arm64_exc_hwstate_t hwstate;
>>
>> if (!is_ttbr0_addr(instruction_pointer(regs)))
>> arm64_apply_bp_hardening();
>>
>> arm64_enter_from_user_mode(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> do_sp_pc_abort(far, esr, regs);
>> - arm64_exit_to_user_mode(regs);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_sp(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> +
>> arm64_enter_from_user_mode(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> do_sp_pc_abort(regs->sp, esr, regs);
>> - arm64_exit_to_user_mode(regs);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_undef(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> +
>> arm64_enter_from_user_mode(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> do_el0_undef(regs, esr);
>> - arm64_exit_to_user_mode(regs);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_bti(struct pt_regs *regs)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> +
>> arm64_enter_from_user_mode(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> do_el0_bti(regs);
>> - arm64_exit_to_user_mode(regs);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_mops(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> +
>> arm64_enter_from_user_mode(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> do_el0_mops(regs, esr);
>> - arm64_exit_to_user_mode(regs);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_gcs(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> +
>> arm64_enter_from_user_mode(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> do_el0_gcs(regs, esr);
>> - arm64_exit_to_user_mode(regs);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_inv(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> +
>> arm64_enter_from_user_mode(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> bad_el0_sync(regs, 0, esr);
>> - arm64_exit_to_user_mode(regs);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_breakpt(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> +
>> if (!is_ttbr0_addr(regs->pc))
>> arm64_apply_bp_hardening();
>>
>> @@ -683,12 +761,13 @@ static void noinstr el0_breakpt(struct pt_regs *regs, unsigned long esr)
>> debug_exception_enter(regs);
>> do_breakpoint(esr, regs);
>> debug_exception_exit(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> - arm64_exit_to_user_mode(regs);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_softstp(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> bool step_done;
>>
>> if (!is_ttbr0_addr(regs->pc))
>> @@ -702,50 +781,56 @@ static void noinstr el0_softstp(struct pt_regs *regs, unsigned long esr)
>> * the single-step is complete.
>> */
>> step_done = try_step_suspended_breakpoints(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> if (!step_done)
>> do_el0_softstep(esr, regs);
>> - arm64_exit_to_user_mode(regs);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_watchpt(struct pt_regs *regs, unsigned long esr)
>> {
>> /* Watchpoints are the only debug exception to write FAR_EL1 */
>> unsigned long far = read_sysreg(far_el1);
>> + arm64_exc_hwstate_t hwstate;
>>
>> arm64_enter_from_user_mode(regs);
>> debug_exception_enter(regs);
>> do_watchpoint(far, esr, regs);
>> debug_exception_exit(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> - arm64_exit_to_user_mode(regs);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_brk64(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> +
>> arm64_enter_from_user_mode(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> do_el0_brk64(esr, regs);
>> - arm64_exit_to_user_mode(regs);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_svc(struct pt_regs *regs)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> arm64_syscall_enter_from_user_mode(regs);
>> cortex_a76_erratum_1463225_svc_handler();
>> fpsimd_syscall_enter();
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> do_el0_svc(regs);
>> - arm64_syscall_exit_to_user_mode(regs);
>> + arm64_syscall_exit_to_user_mode(regs, hwstate);
>> fpsimd_syscall_exit();
>> }
>>
>> static void noinstr el0_fpac(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> +
>> arm64_enter_from_user_mode(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> do_el0_fpac(regs, esr);
>> - arm64_exit_to_user_mode(regs);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> asmlinkage void noinstr el0t_64_sync_handler(struct pt_regs *regs)
>> @@ -814,6 +899,8 @@ asmlinkage void noinstr el0t_64_sync_handler(struct pt_regs *regs)
>> default:
>> el0_inv(regs, esr);
>> }
>> +
>> + arm64_debug_exc_context(CRITICAL_CONTEXT);
>> }
>>
>> static void noinstr el0_interrupt(struct pt_regs *regs,
>> @@ -821,7 +908,7 @@ static void noinstr el0_interrupt(struct pt_regs *regs,
>> {
>> arm64_enter_from_user_mode(regs);
>>
>> - write_sysreg(DAIF_PROCCTX_NOIRQ, daif);
>> + arm64_unmask_exc_context(NONMI_CONTEXT);
>> > if (regs->pc & BIT(55))
>> arm64_apply_bp_hardening();
>> @@ -830,7 +917,14 @@ static void noinstr el0_interrupt(struct pt_regs *regs,
>> do_interrupt_handler(regs, handler);
>> irq_exit_rcu();
>>
>> - arm64_exit_to_user_mode(regs);
>> + /*
>> + * For the same reason as in el1_irq() we effectivly
>> + * have NOIRQ_CONTEXT on return from handler - keep
>> + * track of it
>> + */
>> + arm64_debug_exc_context(NOIRQ_CONTEXT);
>> + arm64_exit_to_user_mode(regs, arm64_exc_hwstate_of_context(NOIRQ_CONTEXT));
>> + arm64_debug_exc_context(CRITICAL_CONTEXT);
>> }
>>
>> static void noinstr __el0_irq_handler_common(struct pt_regs *regs)
>> @@ -856,15 +950,17 @@ asmlinkage void noinstr el0t_64_fiq_handler(struct pt_regs *regs)
>> static void noinstr __el0_error_handler_common(struct pt_regs *regs)
>> {
>> unsigned long esr = read_sysreg(esr_el1);
>> + arm64_exc_hwstate_t hwstate;
>> irqentry_state_t state;
>>
>> arm64_enter_from_user_mode(regs);
>> - local_daif_restore(DAIF_ERRCTX);
>> + hwstate = arm64_unmask_exc_context(ERROR_CONTEXT);
>> state = irqentry_nmi_enter(regs);
>> do_serror(regs, esr);
>> irqentry_nmi_exit(regs, state);
>> - local_daif_restore(DAIF_PROCCTX);
>> - arm64_exit_to_user_mode(regs);
>> + hwstate = arm64_drop_exc_context(hwstate, PROCESS_CONTEXT);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> + arm64_debug_exc_context(CRITICAL_CONTEXT);
>> }
>>
>> asmlinkage void noinstr el0t_64_error_handler(struct pt_regs *regs)
>> @@ -875,27 +971,33 @@ asmlinkage void noinstr el0t_64_error_handler(struct pt_regs *regs)
>> #ifdef CONFIG_COMPAT
>> static void noinstr el0_cp15(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> +
>> arm64_enter_from_user_mode(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> do_el0_cp15(esr, regs);
>> - arm64_exit_to_user_mode(regs);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_svc_compat(struct pt_regs *regs)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> +
>> arm64_syscall_enter_from_user_mode(regs);
>> cortex_a76_erratum_1463225_svc_handler();
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> do_el0_svc_compat(regs);
>> - arm64_syscall_exit_to_user_mode(regs);
>> + arm64_syscall_exit_to_user_mode(regs, hwstate);
>> }
>>
>> static void noinstr el0_bkpt32(struct pt_regs *regs, unsigned long esr)
>> {
>> + arm64_exc_hwstate_t hwstate;
>> +
>> arm64_enter_from_user_mode(regs);
>> - local_daif_restore(DAIF_PROCCTX);
>> + hwstate = arm64_unmask_exc_context(PROCESS_CONTEXT);
>> do_bkpt32(esr, regs);
>> - arm64_exit_to_user_mode(regs);
>> + arm64_exit_to_user_mode(regs, hwstate);
>> }
>>
>> asmlinkage void noinstr el0t_32_sync_handler(struct pt_regs *regs)
>> @@ -946,6 +1048,8 @@ asmlinkage void noinstr el0t_32_sync_handler(struct pt_regs *regs)
>> default:
>> el0_inv(regs, esr);
>> }
>> +
>> + arm64_debug_exc_context(CRITICAL_CONTEXT);
>> }
>>
>> asmlinkage void noinstr el0t_32_irq_handler(struct pt_regs *regs)
>> diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
>> index f63049ac32dc..cb3be770f2d0 100644
>> --- a/arch/arm64/kernel/entry.S
>> +++ b/arch/arm64/kernel/entry.S
>> @@ -316,7 +316,7 @@ alternative_else_nop_endif
>>
>> mrs_s x20, SYS_ICC_PMR_EL1
>> str w20, [sp, #S_PMR]
>> - mov x20, #GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET
>> + mov x20, #GIC_PRIO_IRQON
>> msr_s SYS_ICC_PMR_EL1, x20
>>
>> .Lskip_pmr_save\@:
>> diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
>> index d46022f72075..b91cf163aac7 100644
>> --- a/arch/arm64/kernel/smp.c
>> +++ b/arch/arm64/kernel/smp.c
>> @@ -185,7 +185,7 @@ static void init_gic_priority_masking(void)
>> WARN_ON(!(cpuflags & PSR_I_BIT));
>> WARN_ON(!(cpuflags & PSR_F_BIT));
>>
>> - gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
>> + gic_write_pmr(GIC_PRIO_IRQON);
>> }
>>
>> /*
>
> -- BR Liao, Chang
>
^ permalink raw reply
* Re: [PATCH 2/3] usb: typec: tipd: Factor out i2c specifics
From: Sasha Finkelstein @ 2026-07-27 13:05 UTC (permalink / raw)
To: Heikki Krogerus
Cc: Sven Peter, Janne Grunau, Neal Gompa, Greg Kroah-Hartman,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, asahi,
linux-arm-kernel, linux-usb, devicetree, linux-kernel,
Alyssa Milburn
In-Reply-To: <amdVkYEiv_tOZuwG@black.igk.intel.com>
On Jul 27, 2026, at 14:56, Heikki Krogerus <heikki.krogerus@linux.intel.com> wrote:
>
> Hi,
>
> On Sat, Jul 25, 2026 at 06:20:57PM +0200, Sasha Finkelstein wrote:
>> From: Alyssa Milburn <amilburn@zall.org>
>>
>> Make the core driver more bus-agnostic to prepare for SPMI variants of
>> the tipd chip
>>
>> Signed-off-by: Alyssa Milburn <amilburn@zall.org>
>> Signed-off-by: Sasha Finkelstein <k@chaosmail.tech>
>> ---
>> drivers/usb/typec/tipd/Makefile | 2 +-
>> drivers/usb/typec/tipd/{core.c => core.h} | 109 ++++++++++++++++++++++++++++---------------------------------------------------------------------------------
>
> That has to be a mistake, right? You don't move code into a header
> like that.
Yes, it was a bad idea, already fixed in a v2 that will be sent in the
near future.
>> +static struct tps6598x *tps6598x_from_device(struct device *dev)
>> +{
>> + struct i2c_client *client = i2c_verify_client(dev);
>> + struct tps6598x *tps = i2c_get_clientdata(client);
>> + return tps;
>> +}
>
> You should not need anything like that.
This should make more sense together with the following patch, as it
can get the tps6598x from either the i2c or spmi backend.
>> --- /dev/null
>> +++ b/drivers/usb/typec/tipd/i2c.c
>> @@ -0,0 +1,86 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Driver for TI TPS6598x USB Power Delivery controller family
>> + *
>> + * Copyright (C) 2017, Intel Corporation
>> + * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
>> + */
>
> This driver is not coming from me.
I kept the attribution as both core and i2c are your driver, but split
into two. Should I have done something else?
>
> Thanks,
>
> --
> heikki
^ permalink raw reply
* Re: [PATCH] net: stmmac: enable MAC rx/tx after DMA start
From: Andrew Lunn @ 2026-07-27 13:03 UTC (permalink / raw)
To: Abid Ali
Cc: alexandre.torgue, andrew+netdev, davem, edumazet, kuba,
linux-arm-kernel, linux-kernel, linux-stm32, mcoquelin.stm32,
netdev, pabeni
In-Reply-To: <20260727055715.4430-1-dev.taqnialabs@gmail.com>
On Mon, Jul 27, 2026 at 05:57:15AM +0000, Abid Ali wrote:
> On Sun, Jul 26, 2026 at 18:15:20 +0000, Andrew Lunn wrote:
> > There should be a function which is the opposite of stmmac_hw_setup(),
> > which tears it down. What order are things done there? tear down is
> > generally done in the opposite order to setup, so does the "Disable
> > the MAC Rx/Tx" also need to move?
>
> I have not seen the FIFO stall in the teardown in my testing,
> but the MAC Rx/Tx should be disabled before the DMA engine is stopped.
> For the normal path (__stmmac_release), phylink_stop() is called first
> which triggers stmmac_mac_link_down() -> stmmac_mac_set(false), so the
> MAC is already disabled before stmmac_stop_all_dma(). The teardown
> order is already correct there.
Thanks for checking. Please add a comment to the commit message about
this.
>
> > Same comment for the opposite of stmmac_xdp_open().
>
> Currently, stmmac_xdp_release() does:
>
> stmmac_stop_all_dma(priv);
> ...
> stmmac_mac_set(priv, priv->ioaddr, false);
>
> The ordering is not followed here, I'll make it follow the similar
> ordering to (__stmmac_release) in v2.
Great.
Andrew
---
pw-bot: cr
^ permalink raw reply
* [PATCH v4 11/11] arm64: dts: Enable EdgeLock Secure Enclave on all i.MX91/i.MX93 boards
From: Frieder Schrempf @ 2026-07-27 13:00 UTC (permalink / raw)
To: Srinivas Kandagatla, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Pankaj Gupta, Peng Fan (OSS)
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, linux,
Frieder Schrempf
In-Reply-To: <20260727-upstreaming-next-20260609-imx-ocotp-ele-v4-0-1a515de33093@kontron.de>
From: Frieder Schrempf <frieder.schrempf@kontron.de>
Include the common dtsi to enable the firmware node for all boards
based on the i.MX91 or i.MX93 SoC.
For the TQ-Systems i.MX91 TQMa91xxCA / TQMa91xxLA SOM that already has
a node for the reserved memory, keep the current settings.
Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts | 1 +
arch/arm64/boot/dts/freescale/imx91-11x11-frdm-s.dts | 1 +
arch/arm64/boot/dts/freescale/imx91-11x11-frdm.dts | 1 +
arch/arm64/boot/dts/freescale/imx91-9x9-qsb.dts | 1 +
arch/arm64/boot/dts/freescale/imx91-phycore-som.dtsi | 1 +
arch/arm64/boot/dts/freescale/imx91-tqma9131.dtsi | 15 ++++++++-------
arch/arm64/boot/dts/freescale/imx91-var-dart.dtsi | 1 +
arch/arm64/boot/dts/freescale/imx91-var-som.dtsi | 1 +
arch/arm64/boot/dts/freescale/imx93-11x11-evk-common.dtsi | 1 +
arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts | 1 +
arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts | 1 +
arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts | 1 +
arch/arm64/boot/dts/freescale/imx93-kontron-osm-s.dtsi | 1 +
arch/arm64/boot/dts/freescale/imx93-phycore-som.dtsi | 1 +
arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi | 1 +
arch/arm64/boot/dts/freescale/imx93-var-dart.dtsi | 1 +
arch/arm64/boot/dts/freescale/imx93-var-som.dtsi | 1 +
17 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts b/arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts
index 5716febb5a50..7813a3cf215b 100644
--- a/arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts
@@ -7,6 +7,7 @@
#include <dt-bindings/usb/pd.h>
#include "imx91.dtsi"
+#include "imx93-firmware.dtsi"
/ {
compatible = "fsl,imx91-11x11-evk", "fsl,imx91";
diff --git a/arch/arm64/boot/dts/freescale/imx91-11x11-frdm-s.dts b/arch/arm64/boot/dts/freescale/imx91-11x11-frdm-s.dts
index 62dc1dedfb0e..b5a042a58b57 100644
--- a/arch/arm64/boot/dts/freescale/imx91-11x11-frdm-s.dts
+++ b/arch/arm64/boot/dts/freescale/imx91-11x11-frdm-s.dts
@@ -7,6 +7,7 @@
#include <dt-bindings/usb/pd.h>
#include "imx91.dtsi"
+#include "imx93-firmware.dtsi"
/ {
compatible = "fsl,imx91-11x11-frdm-s", "fsl,imx91";
diff --git a/arch/arm64/boot/dts/freescale/imx91-11x11-frdm.dts b/arch/arm64/boot/dts/freescale/imx91-11x11-frdm.dts
index c25561574d3f..20c7e4989367 100644
--- a/arch/arm64/boot/dts/freescale/imx91-11x11-frdm.dts
+++ b/arch/arm64/boot/dts/freescale/imx91-11x11-frdm.dts
@@ -7,6 +7,7 @@
#include <dt-bindings/usb/pd.h>
#include "imx91.dtsi"
+#include "imx93-firmware.dtsi"
/ {
compatible = "fsl,imx91-11x11-frdm", "fsl,imx91";
diff --git a/arch/arm64/boot/dts/freescale/imx91-9x9-qsb.dts b/arch/arm64/boot/dts/freescale/imx91-9x9-qsb.dts
index ea8cf14e0bc6..430c0402138b 100644
--- a/arch/arm64/boot/dts/freescale/imx91-9x9-qsb.dts
+++ b/arch/arm64/boot/dts/freescale/imx91-9x9-qsb.dts
@@ -7,6 +7,7 @@
#include <dt-bindings/usb/pd.h>
#include "imx91.dtsi"
+#include "imx93-firmware.dtsi"
/ {
compatible = "fsl,imx91-9x9-qsb", "fsl,imx91";
diff --git a/arch/arm64/boot/dts/freescale/imx91-phycore-som.dtsi b/arch/arm64/boot/dts/freescale/imx91-phycore-som.dtsi
index 8b8cb3daecbb..509d869a216b 100644
--- a/arch/arm64/boot/dts/freescale/imx91-phycore-som.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx91-phycore-som.dtsi
@@ -11,6 +11,7 @@
#include <dt-bindings/regulator/nxp,pca9450-regulator.h>
#include "imx91.dtsi"
+#include "imx93-firmware.dtsi"
/ {
model = "PHYTEC phyCORE-i.MX91";
diff --git a/arch/arm64/boot/dts/freescale/imx91-tqma9131.dtsi b/arch/arm64/boot/dts/freescale/imx91-tqma9131.dtsi
index c99d7bc16848..ad66fea4099a 100644
--- a/arch/arm64/boot/dts/freescale/imx91-tqma9131.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx91-tqma9131.dtsi
@@ -7,6 +7,7 @@
*/
#include "imx91.dtsi"
+#include "imx93-firmware.dtsi"
/{
model = "TQ-Systems i.MX91 TQMa91xxCA / TQMa91xxLA SOM";
@@ -31,13 +32,6 @@ linux,cma {
size = <0 0x10000000>;
linux,cma-default;
};
-
- /* EdgeLock secure enclave */
- ele_reserved: ele-reserved@a4120000 {
- compatible = "shared-dma-pool";
- reg = <0 0xa4120000 0 0x100000>;
- no-map;
- };
};
/* SD2 RST# via PMIC SW_EN */
@@ -58,6 +52,13 @@ &adc1 {
vref-supply = <&buck5>;
};
+&ele_memory {
+ /delete-property/alloc-ranges;
+ /delete-property/size;
+ reg = <0 0xa4120000 0 0x100000>;
+ no-map;
+};
+
&flexspi1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_flexspi1>;
diff --git a/arch/arm64/boot/dts/freescale/imx91-var-dart.dtsi b/arch/arm64/boot/dts/freescale/imx91-var-dart.dtsi
index a9e44efad13f..2e1830c33012 100644
--- a/arch/arm64/boot/dts/freescale/imx91-var-dart.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx91-var-dart.dtsi
@@ -13,6 +13,7 @@
#include <dt-bindings/leds/common.h>
#include <dt-bindings/usb/pd.h>
#include "imx91.dtsi"
+#include "imx93-firmware.dtsi"
/ {
model = "Variscite DART-MX91 Module";
diff --git a/arch/arm64/boot/dts/freescale/imx91-var-som.dtsi b/arch/arm64/boot/dts/freescale/imx91-var-som.dtsi
index b30a0d8a81ba..87db0abb8257 100644
--- a/arch/arm64/boot/dts/freescale/imx91-var-som.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx91-var-som.dtsi
@@ -11,6 +11,7 @@
/dts-v1/;
#include "imx91.dtsi"
+#include "imx93-firmware.dtsi"
/{
model = "Variscite VAR-SOM-MX91 module";
diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-evk-common.dtsi b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-common.dtsi
index f48e7947cf64..65db986fc7ba 100644
--- a/arch/arm64/boot/dts/freescale/imx93-11x11-evk-common.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx93-11x11-evk-common.dtsi
@@ -4,6 +4,7 @@
*/
#include <dt-bindings/usb/pd.h>
+#include "imx93-firmware.dtsi"
/ {
aliases {
diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts
index bd14ba28690c..0bd19988ce9f 100644
--- a/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts
+++ b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts
@@ -3,6 +3,7 @@
#include <dt-bindings/usb/pd.h>
#include "imx93.dtsi"
+#include "imx93-firmware.dtsi"
/ {
compatible = "fsl,imx93-11x11-frdm", "fsl,imx93";
diff --git a/arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts b/arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts
index ec78c03f4788..0e5c7d1ed4ee 100644
--- a/arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts
@@ -7,6 +7,7 @@
#include <dt-bindings/usb/pd.h>
#include "imx93.dtsi"
+#include "imx93-firmware.dtsi"
/ {
model = "NXP i.MX93 14X14 EVK board";
diff --git a/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts
index 01c11c517986..694f114aef36 100644
--- a/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts
+++ b/arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts
@@ -7,6 +7,7 @@
#include <dt-bindings/usb/pd.h>
#include "imx93.dtsi"
+#include "imx93-firmware.dtsi"
/ {
model = "NXP i.MX93 9x9 Quick Start Board";
diff --git a/arch/arm64/boot/dts/freescale/imx93-kontron-osm-s.dtsi b/arch/arm64/boot/dts/freescale/imx93-kontron-osm-s.dtsi
index c79b1df339db..c9aa764cc3b8 100644
--- a/arch/arm64/boot/dts/freescale/imx93-kontron-osm-s.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx93-kontron-osm-s.dtsi
@@ -5,6 +5,7 @@
#include <dt-bindings/interrupt-controller/irq.h>
#include "imx93.dtsi"
+#include "imx93-firmware.dtsi"
/ {
model = "Kontron OSM-S i.MX93";
diff --git a/arch/arm64/boot/dts/freescale/imx93-phycore-som.dtsi b/arch/arm64/boot/dts/freescale/imx93-phycore-som.dtsi
index 325e465d0056..076716cc2095 100644
--- a/arch/arm64/boot/dts/freescale/imx93-phycore-som.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx93-phycore-som.dtsi
@@ -12,6 +12,7 @@
#include <dt-bindings/regulator/nxp,pca9450-regulator.h>
#include "imx93.dtsi"
+#include "imx93-firmware.dtsi"
/{
model = "PHYTEC phyCORE-i.MX93";
diff --git a/arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi b/arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi
index ce34a296495c..159be0d5dfde 100644
--- a/arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi
@@ -6,6 +6,7 @@
*/
#include "imx93.dtsi"
+#include "imx93-firmware.dtsi"
/{
model = "TQ-Systems i.MX93 TQMa93xxLA/TQMa93xxCA SOM";
diff --git a/arch/arm64/boot/dts/freescale/imx93-var-dart.dtsi b/arch/arm64/boot/dts/freescale/imx93-var-dart.dtsi
index 69495bb7fc9f..122a8a091c80 100644
--- a/arch/arm64/boot/dts/freescale/imx93-var-dart.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx93-var-dart.dtsi
@@ -12,6 +12,7 @@
#include <dt-bindings/usb/pd.h>
#include "imx93.dtsi"
+#include "imx93-firmware.dtsi"
/ {
model = "Variscite DART-MX93 Module";
diff --git a/arch/arm64/boot/dts/freescale/imx93-var-som.dtsi b/arch/arm64/boot/dts/freescale/imx93-var-som.dtsi
index 24063bf8183d..50aec264f87c 100644
--- a/arch/arm64/boot/dts/freescale/imx93-var-som.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx93-var-som.dtsi
@@ -7,6 +7,7 @@
/dts-v1/;
#include "imx93.dtsi"
+#include "imx93-firmware.dtsi"
/{
model = "Variscite VAR-SOM-MX93 module";
--
2.55.0
^ permalink raw reply related
* [PATCH v4 08/11] nvmem: imx-ocotp-ele: Remove the FUSE_ELE type
From: Frieder Schrempf @ 2026-07-27 13:00 UTC (permalink / raw)
To: Srinivas Kandagatla, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Pankaj Gupta, Peng Fan (OSS)
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, linux,
Frieder Schrempf
In-Reply-To: <20260727-upstreaming-next-20260609-imx-ocotp-ele-v4-0-1a515de33093@kontron.de>
From: Frieder Schrempf <frieder.schrempf@kontron.de>
There is no use in tracking the fuses that are only accessible via
ELE API and the current lists are incomplete. If the ELE API is
available it will be used as primary access method anyway, otherwise
the fuses not listed as accessible through the FSB can be considered
invalid.
No functional changes intended.
Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
drivers/nvmem/imx-ocotp-ele.c | 19 +++++--------------
1 file changed, 5 insertions(+), 14 deletions(-)
diff --git a/drivers/nvmem/imx-ocotp-ele.c b/drivers/nvmem/imx-ocotp-ele.c
index 23e91775be5d..f691ad0cd1a1 100644
--- a/drivers/nvmem/imx-ocotp-ele.c
+++ b/drivers/nvmem/imx-ocotp-ele.c
@@ -19,8 +19,7 @@
enum fuse_type {
FUSE_FSB = BIT(0),
- FUSE_ELE = BIT(1),
- FUSE_ECC = BIT(2),
+ FUSE_ECC = BIT(1),
FUSE_INVALID = -1
};
@@ -209,7 +208,7 @@ static int imx_ocotp_reg_read(void *context, unsigned int offset, void *val, siz
}
type = imx_ocotp_fuse_type(context, i);
- if (type == FUSE_INVALID || type == FUSE_ELE) {
+ if (type == FUSE_INVALID) {
*buf++ = 0;
continue;
}
@@ -352,13 +351,9 @@ static const struct nvmem_keepout imx93_ocotp_keepout[] = {
static const struct ocotp_devtype_data imx93_ocotp_data = {
.reg_off = 0x8000,
.size = 2048,
- .num_entry = 6,
+ .num_entry = 2,
.entry = {
{ 0, 52, FUSE_FSB },
- { 63, 1, FUSE_ELE},
- { 128, 16, FUSE_ELE },
- { 182, 1, FUSE_ELE },
- { 188, 1, FUSE_ELE },
{ 312, 200, FUSE_FSB }
},
.keepout = imx93_ocotp_keepout,
@@ -368,7 +363,7 @@ static const struct ocotp_devtype_data imx93_ocotp_data = {
static const struct ocotp_devtype_data imx94_ocotp_data = {
.reg_off = 0x8000,
.size = 3296, /* 103 Banks */
- .num_entry = 10,
+ .num_entry = 9,
.entry = {
{ 0, 1, FUSE_FSB | FUSE_ECC },
{ 7, 1, FUSE_FSB | FUSE_ECC },
@@ -376,7 +371,6 @@ static const struct ocotp_devtype_data imx94_ocotp_data = {
{ 12, 24, FUSE_FSB },
{ 36, 2, FUSE_FSB | FUSE_ECC },
{ 38, 14, FUSE_FSB },
- { 59, 1, FUSE_ELE },
{ 525, 2, FUSE_FSB | FUSE_ECC },
{ 528, 7, FUSE_FSB },
{ 536, 280, FUSE_FSB },
@@ -386,7 +380,7 @@ static const struct ocotp_devtype_data imx94_ocotp_data = {
static const struct ocotp_devtype_data imx95_ocotp_data = {
.reg_off = 0x8000,
.size = 2048,
- .num_entry = 12,
+ .num_entry = 9,
.entry = {
{ 0, 1, FUSE_FSB | FUSE_ECC },
{ 7, 1, FUSE_FSB | FUSE_ECC },
@@ -394,9 +388,6 @@ static const struct ocotp_devtype_data imx95_ocotp_data = {
{ 12, 24, FUSE_FSB },
{ 36, 2, FUSE_FSB | FUSE_ECC },
{ 38, 14, FUSE_FSB },
- { 63, 1, FUSE_ELE },
- { 128, 16, FUSE_ELE },
- { 188, 1, FUSE_ELE },
{ 317, 2, FUSE_FSB | FUSE_ECC },
{ 320, 7, FUSE_FSB },
{ 328, 184, FUSE_FSB }
--
2.55.0
^ permalink raw reply related
* [PATCH v4 09/11] nvmem: imx-ocotp-ele: Rename FSB access map
From: Frieder Schrempf @ 2026-07-27 13:00 UTC (permalink / raw)
To: Srinivas Kandagatla, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Pankaj Gupta, Peng Fan (OSS)
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, linux,
Frieder Schrempf
In-Reply-To: <20260727-upstreaming-next-20260609-imx-ocotp-ele-v4-0-1a515de33093@kontron.de>
From: Frieder Schrempf <frieder.schrempf@kontron.de>
The table is used to declare which fuse registers are accessible
through the FSB block. Name it accordingly to make this clearer for
the reader.
No functional changes intended.
Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
drivers/nvmem/imx-ocotp-ele.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/nvmem/imx-ocotp-ele.c b/drivers/nvmem/imx-ocotp-ele.c
index f691ad0cd1a1..e9b579753c78 100644
--- a/drivers/nvmem/imx-ocotp-ele.c
+++ b/drivers/nvmem/imx-ocotp-ele.c
@@ -33,11 +33,11 @@ struct ocotp_devtype_data {
u32 reg_off;
char *name;
u32 size;
- u32 num_entry;
+ u32 num_fsb_map;
u32 flag;
const struct nvmem_keepout *keepout;
unsigned int nkeepout;
- struct ocotp_map_entry entry[];
+ struct ocotp_map_entry fsb_map[];
};
struct imx_ocotp_priv {
@@ -156,12 +156,12 @@ static enum fuse_type imx_ocotp_fuse_type(void *context, u32 index)
u32 start, end;
int i;
- for (i = 0; i < data->num_entry; i++) {
- start = data->entry[i].start;
- end = data->entry[i].start + data->entry[i].num;
+ for (i = 0; i < data->num_fsb_map; i++) {
+ start = data->fsb_map[i].start;
+ end = data->fsb_map[i].start + data->fsb_map[i].num;
if (index >= start && index < end)
- return data->entry[i].type;
+ return data->fsb_map[i].type;
}
return FUSE_INVALID;
@@ -351,8 +351,8 @@ static const struct nvmem_keepout imx93_ocotp_keepout[] = {
static const struct ocotp_devtype_data imx93_ocotp_data = {
.reg_off = 0x8000,
.size = 2048,
- .num_entry = 2,
- .entry = {
+ .num_fsb_map = 2,
+ .fsb_map = {
{ 0, 52, FUSE_FSB },
{ 312, 200, FUSE_FSB }
},
@@ -363,8 +363,8 @@ static const struct ocotp_devtype_data imx93_ocotp_data = {
static const struct ocotp_devtype_data imx94_ocotp_data = {
.reg_off = 0x8000,
.size = 3296, /* 103 Banks */
- .num_entry = 9,
- .entry = {
+ .num_fsb_map = 9,
+ .fsb_map = {
{ 0, 1, FUSE_FSB | FUSE_ECC },
{ 7, 1, FUSE_FSB | FUSE_ECC },
{ 9, 3, FUSE_FSB | FUSE_ECC },
@@ -380,8 +380,8 @@ static const struct ocotp_devtype_data imx94_ocotp_data = {
static const struct ocotp_devtype_data imx95_ocotp_data = {
.reg_off = 0x8000,
.size = 2048,
- .num_entry = 9,
- .entry = {
+ .num_fsb_map = 9,
+ .fsb_map = {
{ 0, 1, FUSE_FSB | FUSE_ECC },
{ 7, 1, FUSE_FSB | FUSE_ECC },
{ 9, 3, FUSE_FSB | FUSE_ECC },
--
2.55.0
^ permalink raw reply related
* [PATCH v4 10/11] arm64: dts: Add ELE firmware node and common include
From: Frieder Schrempf @ 2026-07-27 13:00 UTC (permalink / raw)
To: Srinivas Kandagatla, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Pankaj Gupta, Peng Fan (OSS)
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, linux,
Frieder Schrempf
In-Reply-To: <20260727-upstreaming-next-20260609-imx-ocotp-ele-v4-0-1a515de33093@kontron.de>
From: Frieder Schrempf <frieder.schrempf@kontron.de>
Add the firmware node to SoC dtsi and to make it easier for boards to
configure the EdgeLock Secure Enclave on i.MX93, add a common include
file that contains sane defaults. It specifies the memory node,
enables the ELE firmware node and adds a reference to NVMEM OCOTP
driver.
The 1MB memory area required for the firmware is placed in the first
256MB of the DDR. Boards that require a more specific alignment can
override this accordingly.
Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
arch/arm64/boot/dts/freescale/imx91_93_common.dtsi | 9 +++++++
arch/arm64/boot/dts/freescale/imx93-firmware.dtsi | 28 ++++++++++++++++++++++
2 files changed, 37 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/imx91_93_common.dtsi b/arch/arm64/boot/dts/freescale/imx91_93_common.dtsi
index a1a7e6a0571b..60798b216438 100644
--- a/arch/arm64/boot/dts/freescale/imx91_93_common.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx91_93_common.dtsi
@@ -46,6 +46,15 @@ A55_0: cpu@0 {
};
};
+ firmware {
+ hsm0: secure-enclave {
+ compatible = "fsl,imx93-se-ele-hsm";
+ mbox-names = "tx", "rx";
+ mboxes = <&s4muap 0 0>, <&s4muap 1 0>;
+ status = "disabled";
+ };
+ };
+
osc_32k: clock-osc-32k {
compatible = "fixed-clock";
#clock-cells = <0>;
diff --git a/arch/arm64/boot/dts/freescale/imx93-firmware.dtsi b/arch/arm64/boot/dts/freescale/imx93-firmware.dtsi
new file mode 100644
index 000000000000..58614158ef90
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx93-firmware.dtsi
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2026 Kontron Electronics GmbH
+ */
+
+/{
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ ele_memory: ele-memory {
+ compatible = "shared-dma-pool";
+ alloc-ranges = <0 0x80000000 0 0x10000000>;
+ size = <0 0x100000>;
+ no-map;
+ };
+ };
+};
+
+&hsm0 {
+ status = "okay";
+ memory-region = <&ele_memory>;
+};
+
+&ocotp {
+ secure-enclave = <&hsm0>;
+};
--
2.55.0
^ permalink raw reply related
* [PATCH v4 07/11] nvmem: imx-ocotp-ele: Support the ELE API
From: Frieder Schrempf @ 2026-07-27 13:00 UTC (permalink / raw)
To: Srinivas Kandagatla, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Pankaj Gupta, Peng Fan (OSS)
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, linux,
Frieder Schrempf
In-Reply-To: <20260727-upstreaming-next-20260609-imx-ocotp-ele-v4-0-1a515de33093@kontron.de>
From: Frieder Schrempf <frieder.schrempf@kontron.de>
The fuses inside the Edgelock Secure Enclave are currently not
accessed via its API but through the FSB block which provides
limited access to some fuses.
The ELE API allows us to access all fuses with read/write
permissions. Therefore use it as primary method and only fall
back to the limited FSB if the ELE API is not available.
Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
drivers/nvmem/imx-ocotp-ele.c | 168 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 167 insertions(+), 1 deletion(-)
diff --git a/drivers/nvmem/imx-ocotp-ele.c b/drivers/nvmem/imx-ocotp-ele.c
index 010b53001323..23e91775be5d 100644
--- a/drivers/nvmem/imx-ocotp-ele.c
+++ b/drivers/nvmem/imx-ocotp-ele.c
@@ -7,10 +7,12 @@
#include <linux/cleanup.h>
#include <linux/device.h>
+#include <linux/firmware/imx/se_api.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/nvmem-provider.h>
#include <linux/of.h>
+#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/if_ether.h> /* ETH_ALEN */
@@ -45,8 +47,109 @@ struct imx_ocotp_priv {
struct nvmem_config config;
struct mutex lock;
const struct ocotp_devtype_data *data;
+ struct se_if_priv *se_data;
};
+/* ELE commands and message sizes used for OCOTP fuse access. */
+#define ELE_READ_FUSE_REQ 0x97
+#define ELE_READ_FUSE_REQ_MSG_SZ 0x08
+#define ELE_READ_FUSE_RSP_MSG_SZ 0x0c
+
+#define ELE_WRITE_FUSE 0xd6
+#define ELE_WRITE_FUSE_REQ_MSG_SZ 0x0c
+#define ELE_WRITE_FUSE_RSP_MSG_SZ 0x0c
+
+/*
+ * imx_ocotp_se_read_fuse() - Request the secure enclave FW to read a fuse.
+ * @priv: handle to the secure-enclave interface.
+ * @fuse_id: fuse identifier to read.
+ * @value: location to store the read fuse value.
+ *
+ * Secure enclaves like the EdgeLock Enclave manage the fuses. This requests
+ * the FW to read the fuse and returns the value reported by the FW.
+ *
+ * Return: 0 on success, a negative error code otherwise.
+ */
+static int imx_ocotp_se_read_fuse(struct se_if_priv *priv, u16 fuse_id, u32 *value)
+{
+ int ret;
+
+ if (!priv)
+ return -EINVAL;
+
+ struct se_api_msg *tx_msg __free(kfree) = kzalloc(ELE_READ_FUSE_REQ_MSG_SZ, GFP_KERNEL);
+ if (!tx_msg)
+ return -ENOMEM;
+
+ struct se_api_msg *rx_msg __free(kfree) = kzalloc(ELE_READ_FUSE_RSP_MSG_SZ, GFP_KERNEL);
+ if (!rx_msg)
+ return -ENOMEM;
+
+ ret = imx_se_fill_cmd_msg_hdr(priv, &tx_msg->header, ELE_READ_FUSE_REQ,
+ ELE_READ_FUSE_REQ_MSG_SZ, true);
+ if (ret)
+ return ret;
+
+ tx_msg->data[0] = fuse_id;
+
+ ret = imx_se_msg_send_rcv(priv, tx_msg, ELE_READ_FUSE_REQ_MSG_SZ,
+ rx_msg, ELE_READ_FUSE_RSP_MSG_SZ);
+ if (ret < 0)
+ return ret;
+
+ ret = imx_se_val_rsp_hdr_n_status(priv, rx_msg, ELE_READ_FUSE_REQ,
+ ELE_READ_FUSE_RSP_MSG_SZ, true);
+ if (ret)
+ return ret;
+
+ *value = rx_msg->data[1];
+
+ return 0;
+}
+
+/*
+ * imx_ocotp_se_write_fuse() - Request the secure enclave FW to write a fuse.
+ * @priv: handle to the secure-enclave interface.
+ * @fuse_id: fuse identifier to write to.
+ * @value: value to write to the fuse.
+ *
+ * Secure enclaves like the EdgeLock Enclave manage the fuses. This requests
+ * the FW to program the fuse with the given value.
+ *
+ * Return: 0 on success, a negative error code otherwise.
+ */
+static int imx_ocotp_se_write_fuse(struct se_if_priv *priv, u16 fuse_id, u32 value)
+{
+ int ret;
+
+ if (!priv)
+ return -EINVAL;
+
+ struct se_api_msg *tx_msg __free(kfree) = kzalloc(ELE_WRITE_FUSE_REQ_MSG_SZ, GFP_KERNEL);
+ if (!tx_msg)
+ return -ENOMEM;
+
+ struct se_api_msg *rx_msg __free(kfree) = kzalloc(ELE_WRITE_FUSE_RSP_MSG_SZ, GFP_KERNEL);
+ if (!rx_msg)
+ return -ENOMEM;
+
+ ret = imx_se_fill_cmd_msg_hdr(priv, &tx_msg->header, ELE_WRITE_FUSE,
+ ELE_WRITE_FUSE_REQ_MSG_SZ, true);
+ if (ret)
+ return ret;
+
+ tx_msg->data[0] = (32 << 16) | (fuse_id << 5);
+ tx_msg->data[1] = value;
+
+ ret = imx_se_msg_send_rcv(priv, tx_msg, ELE_WRITE_FUSE_REQ_MSG_SZ,
+ rx_msg, ELE_WRITE_FUSE_RSP_MSG_SZ);
+ if (ret < 0)
+ return ret;
+
+ return imx_se_val_rsp_hdr_n_status(priv, rx_msg, ELE_WRITE_FUSE,
+ ELE_WRITE_FUSE_RSP_MSG_SZ, true);
+}
+
static enum fuse_type imx_ocotp_fuse_type(void *context, u32 index)
{
struct imx_ocotp_priv *priv = context;
@@ -72,6 +175,7 @@ static int imx_ocotp_reg_read(void *context, unsigned int offset, void *val, siz
u32 count, index, num_bytes;
enum fuse_type type;
u32 *buf;
+ int ret;
int i;
u8 skipbytes;
@@ -92,6 +196,18 @@ static int imx_ocotp_reg_read(void *context, unsigned int offset, void *val, siz
buf = p;
for (i = index; i < (index + count); i++) {
+ /*
+ * All fuse registers can be read via ELE. If the SE device is
+ * available, always prefer it.
+ */
+ if (priv->se_data) {
+ ret = imx_ocotp_se_read_fuse(priv->se_data, i, buf++);
+ if (ret)
+ return ret;
+
+ continue;
+ }
+
type = imx_ocotp_fuse_type(context, i);
if (type == FUSE_INVALID || type == FUSE_ELE) {
*buf++ = 0;
@@ -109,6 +225,29 @@ static int imx_ocotp_reg_read(void *context, unsigned int offset, void *val, siz
return 0;
};
+static int imx_ocotp_reg_write(void *context, unsigned int offset, void *val, size_t bytes)
+{
+ struct imx_ocotp_priv *priv = context;
+ u32 word = offset >> 2;
+ u32 *buf = val;
+
+ /* allow only writing one complete OTP word at a time */
+ if ((bytes != 4) || (offset % 4 != 0))
+ return -EINVAL;
+
+ /*
+ * The ELE API returns an error when writing an all-zero value. As
+ * OTP fuse bits can not be switched from 1 to 0 anyway, skip these
+ * values.
+ */
+ if (!*buf)
+ return 0;
+
+ guard(mutex)(&priv->lock);
+
+ return imx_ocotp_se_write_fuse(priv->se_data, word, *buf);
+}
+
static int imx_ocotp_cell_pp(void *context, const char *id, int index,
unsigned int offset, void *data, size_t bytes)
{
@@ -135,6 +274,7 @@ static void imx_ocotp_fixup_dt_cell_info(struct nvmem_device *nvmem,
static int imx_ele_ocotp_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ struct platform_device *se_pdev;
struct imx_ocotp_priv *priv;
struct nvmem_device *nvmem;
@@ -148,16 +288,39 @@ static int imx_ele_ocotp_probe(struct platform_device *pdev)
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
+ struct device_node *np __free(device_node) = of_parse_phandle(pdev->dev.of_node,
+ "secure-enclave", 0);
+ if (!np) {
+ dev_info(dev, "missing or invalid SE handle, using readonly FSB\n");
+ } else {
+ se_pdev = of_find_device_by_node(np);
+ if (!se_pdev)
+ return dev_err_probe(dev, -ENODEV, "failed to find SE device\n");
+
+ priv->se_data = platform_get_drvdata(se_pdev);
+ if (!priv->se_data) {
+ put_device(&se_pdev->dev);
+ return dev_err_probe(dev, -EPROBE_DEFER, "SE device not ready\n");
+ }
+
+ if (!device_link_add(dev, &se_pdev->dev, DL_FLAG_AUTOREMOVE_CONSUMER)) {
+ put_device(&se_pdev->dev);
+ return dev_err_probe(dev, -EINVAL, "failed to link to SE device\n");
+ }
+
+ put_device(&se_pdev->dev);
+ }
+
priv->config.dev = dev;
priv->config.name = "ELE-OCOTP";
priv->config.id = NVMEM_DEVID_AUTO;
priv->config.owner = THIS_MODULE;
priv->config.size = priv->data->size;
priv->config.reg_read = imx_ocotp_reg_read;
+ priv->config.reg_write = imx_ocotp_reg_write;
priv->config.word_size = 1;
priv->config.stride = 1;
priv->config.priv = priv;
- priv->config.read_only = true;
priv->config.add_legacy_fixed_of_cells = true;
priv->config.fixup_dt_cell_info = imx_ocotp_fixup_dt_cell_info;
@@ -166,6 +329,9 @@ static int imx_ele_ocotp_probe(struct platform_device *pdev)
priv->config.nkeepout = priv->data->nkeepout;
}
+ if (!priv->se_data)
+ priv->config.read_only = true;
+
mutex_init(&priv->lock);
nvmem = devm_nvmem_register(dev, &priv->config);
--
2.55.0
^ permalink raw reply related
* [PATCH v4 04/11] nvmem: imx-ocotp-ele: Add keepout table for i.MX93
From: Frieder Schrempf @ 2026-07-27 13:00 UTC (permalink / raw)
To: Srinivas Kandagatla, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Pankaj Gupta, Peng Fan (OSS)
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, linux,
Frieder Schrempf
In-Reply-To: <20260727-upstreaming-next-20260609-imx-ocotp-ele-v4-0-1a515de33093@kontron.de>
From: Frieder Schrempf <frieder.schrempf@kontron.de>
Add an overall keepout table to describe which fuse registers are
invalid and not accessible. No functional changes intended.
Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
drivers/nvmem/imx-ocotp-ele.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/nvmem/imx-ocotp-ele.c b/drivers/nvmem/imx-ocotp-ele.c
index a0d2985c6d03..dadec19ca252 100644
--- a/drivers/nvmem/imx-ocotp-ele.c
+++ b/drivers/nvmem/imx-ocotp-ele.c
@@ -34,6 +34,8 @@ struct ocotp_devtype_data {
u32 num_entry;
u32 flag;
nvmem_reg_read_t reg_read;
+ const struct nvmem_keepout *keepout;
+ unsigned int nkeepout;
struct ocotp_map_entry entry[];
};
@@ -163,6 +165,12 @@ static int imx_ele_ocotp_probe(struct platform_device *pdev)
priv->config.read_only = true;
priv->config.add_legacy_fixed_of_cells = true;
priv->config.fixup_dt_cell_info = imx_ocotp_fixup_dt_cell_info;
+
+ if (priv->data->nkeepout) {
+ priv->config.keepout = priv->data->keepout;
+ priv->config.nkeepout = priv->data->nkeepout;
+ }
+
mutex_init(&priv->lock);
nvmem = devm_nvmem_register(dev, &priv->config);
@@ -172,6 +180,14 @@ static int imx_ele_ocotp_probe(struct platform_device *pdev)
return 0;
}
+static const struct nvmem_keepout imx93_ocotp_keepout[] = {
+ {.start = 208, .end = 252},
+ {.start = 256, .end = 512},
+ {.start = 576, .end = 728},
+ {.start = 732, .end = 752},
+ {.start = 756, .end = 1248},
+};
+
static const struct ocotp_devtype_data imx93_ocotp_data = {
.reg_off = 0x8000,
.reg_read = imx_ocotp_reg_read,
@@ -185,6 +201,8 @@ static const struct ocotp_devtype_data imx93_ocotp_data = {
{ 188, 1, FUSE_ELE },
{ 312, 200, FUSE_FSB }
},
+ .keepout = imx93_ocotp_keepout,
+ .nkeepout = ARRAY_SIZE(imx93_ocotp_keepout),
};
static const struct ocotp_devtype_data imx94_ocotp_data = {
--
2.55.0
^ permalink raw reply related
* [PATCH v4 03/11] firmware: imx: ele: Export API functions
From: Frieder Schrempf @ 2026-07-27 13:00 UTC (permalink / raw)
To: Srinivas Kandagatla, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Pankaj Gupta, Peng Fan (OSS)
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, linux,
Frieder Schrempf
In-Reply-To: <20260727-upstreaming-next-20260609-imx-ocotp-ele-v4-0-1a515de33093@kontron.de>
From: Frieder Schrempf <frieder.schrempf@kontron.de>
Export generic ELE API functions to send and receive messages. This
allows drivers to implement functions based on the ELE API.
Assisted-by: Claude:claude-opus-4-8
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
drivers/firmware/imx/ele_base_msg.c | 42 ++++++++++----------
drivers/firmware/imx/ele_common.c | 35 ++++++++++++++++-
drivers/firmware/imx/ele_common.h | 14 -------
drivers/firmware/imx/se_ctrl.c | 6 +--
drivers/firmware/imx/se_ctrl.h | 14 +------
include/linux/firmware/imx/se_api.h | 78 +++++++++++++++++++++++++++++++++++++
6 files changed, 137 insertions(+), 52 deletions(-)
diff --git a/drivers/firmware/imx/ele_base_msg.c b/drivers/firmware/imx/ele_base_msg.c
index 28b835f2880f..a4ab45efdd63 100644
--- a/drivers/firmware/imx/ele_base_msg.c
+++ b/drivers/firmware/imx/ele_base_msg.c
@@ -8,6 +8,7 @@
#include <linux/cleanup.h>
#include <linux/completion.h>
#include <linux/dma-mapping.h>
+#include <linux/firmware/imx/se_api.h>
#include <linux/genalloc.h>
#include "ele_base_msg.h"
@@ -106,8 +107,8 @@ int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info)
}
}
- se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header,
- ELE_GET_INFO_REQ, ELE_GET_INFO_REQ_MSG_SZ, true);
+ imx_se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header,
+ ELE_GET_INFO_REQ, ELE_GET_INFO_REQ_MSG_SZ, true);
tx_msg->data[0] = upper_32_bits(get_info_addr);
tx_msg->data[1] = lower_32_bits(get_info_addr);
@@ -120,8 +121,8 @@ int ele_get_info(struct se_if_priv *priv, struct ele_dev_info *s_info)
return ret;
}
- ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_GET_INFO_REQ,
- ELE_GET_INFO_RSP_MSG_SZ, true);
+ ret = imx_se_val_rsp_hdr_n_status(priv, rx_msg, ELE_GET_INFO_REQ,
+ ELE_GET_INFO_RSP_MSG_SZ, true);
if (ret < 0) {
ele_get_info_cleanup(priv, get_info_data, get_info_addr, get_info_len);
return ret;
@@ -156,16 +157,16 @@ int ele_ping(struct se_if_priv *priv)
if (!rx_msg)
return -ENOMEM;
- se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header,
- ELE_PING_REQ, ELE_PING_REQ_SZ, true);
+ imx_se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header,
+ ELE_PING_REQ, ELE_PING_REQ_SZ, true);
ret = ele_msg_send_rcv(priv->priv_dev_ctx, tx_msg, ELE_PING_REQ_SZ,
rx_msg, ELE_PING_RSP_SZ);
if (ret < 0)
return ret;
- ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_PING_REQ,
- ELE_PING_RSP_SZ, true);
+ ret = imx_se_val_rsp_hdr_n_status(priv, rx_msg, ELE_PING_REQ,
+ ELE_PING_RSP_SZ, true);
return ret;
}
@@ -196,8 +197,9 @@ int ele_service_swap(struct se_if_priv *priv,
if (!rx_msg)
return -ENOMEM;
- se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header,
- ELE_SERVICE_SWAP_REQ, ELE_SERVICE_SWAP_REQ_MSG_SZ, true);
+ imx_se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header,
+ ELE_SERVICE_SWAP_REQ, ELE_SERVICE_SWAP_REQ_MSG_SZ,
+ true);
tx_msg->data[0] = flag;
tx_msg->data[1] = addr_size;
@@ -212,8 +214,8 @@ int ele_service_swap(struct se_if_priv *priv,
if (ret < 0)
return ret;
- ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_SERVICE_SWAP_REQ,
- ELE_SERVICE_SWAP_RSP_MSG_SZ, true);
+ ret = imx_se_val_rsp_hdr_n_status(priv, rx_msg, ELE_SERVICE_SWAP_REQ,
+ ELE_SERVICE_SWAP_RSP_MSG_SZ, true);
if (ret)
return ret;
@@ -248,8 +250,8 @@ int ele_fw_authenticate(struct se_if_priv *priv, dma_addr_t contnr_addr,
if (!rx_msg)
return -ENOMEM;
- se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header,
- ELE_FW_AUTH_REQ, ELE_FW_AUTH_REQ_SZ, true);
+ imx_se_fill_cmd_msg_hdr(priv, (struct se_msg_hdr *)&tx_msg->header,
+ ELE_FW_AUTH_REQ, ELE_FW_AUTH_REQ_SZ, true);
tx_msg->data[0] = lower_32_bits(contnr_addr);
tx_msg->data[1] = 0;
@@ -260,8 +262,8 @@ int ele_fw_authenticate(struct se_if_priv *priv, dma_addr_t contnr_addr,
if (ret < 0)
return ret;
- ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_FW_AUTH_REQ,
- ELE_FW_AUTH_RSP_MSG_SZ, true);
+ ret = imx_se_val_rsp_hdr_n_status(priv, rx_msg, ELE_FW_AUTH_REQ,
+ ELE_FW_AUTH_RSP_MSG_SZ, true);
return ret;
}
@@ -286,8 +288,8 @@ int ele_debug_dump(struct se_if_priv *priv)
if (!rx_msg)
return -ENOMEM;
- se_fill_cmd_msg_hdr(priv, &tx_msg->header, ELE_DEBUG_DUMP_REQ,
- ELE_DEBUG_DUMP_REQ_SZ, true);
+ imx_se_fill_cmd_msg_hdr(priv, &tx_msg->header, ELE_DEBUG_DUMP_REQ,
+ ELE_DEBUG_DUMP_REQ_SZ, true);
msg_ex_cnt = 0;
do {
@@ -298,8 +300,8 @@ int ele_debug_dump(struct se_if_priv *priv)
if (ret < 0)
return ret;
- ret = se_val_rsp_hdr_n_status(priv, rx_msg, ELE_DEBUG_DUMP_REQ,
- ELE_DEBUG_DUMP_RSP_SZ, true);
+ ret = imx_se_val_rsp_hdr_n_status(priv, rx_msg, ELE_DEBUG_DUMP_REQ,
+ ELE_DEBUG_DUMP_RSP_SZ, true);
if (ret) {
dev_err(priv->dev, "Dump_Debug_Buffer Error: %x.", ret);
break;
diff --git a/drivers/firmware/imx/ele_common.c b/drivers/firmware/imx/ele_common.c
index fbb6e584341a..f9c56fd42af0 100644
--- a/drivers/firmware/imx/ele_common.c
+++ b/drivers/firmware/imx/ele_common.c
@@ -3,11 +3,26 @@
* Copyright 2025 NXP
*/
+#include <linux/export.h>
+
#include "ele_base_msg.h"
#include "ele_common.h"
#include "ele_fw_api.h"
#include "se_ctrl.h"
+/* Fill a command message header with a given command ID and length in bytes. */
+int imx_se_fill_cmd_msg_hdr(struct se_if_priv *priv, struct se_msg_hdr *hdr,
+ u8 cmd, u32 len, bool is_base_api)
+{
+ hdr->tag = priv->if_defs->cmd_tag;
+ hdr->ver = (is_base_api) ? priv->if_defs->base_api_ver : priv->if_defs->fw_api_ver;
+ hdr->command = cmd;
+ hdr->size = len >> 2;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(imx_se_fill_cmd_msg_hdr);
+
int se_chk_tx_msg_hdr(struct se_if_device_ctx *dev_ctx, struct se_msg_hdr *header)
{
struct se_if_priv *priv = dev_ctx->priv;
@@ -261,6 +276,21 @@ int ele_msg_send_rcv(struct se_if_device_ctx *dev_ctx, void *tx_msg,
return err;
}
+/*
+ * Send/receive blocking call for external drivers, operating on the SE
+ * interface private data (the misc device context is resolved internally).
+ */
+int imx_se_msg_send_rcv(struct se_if_priv *priv, void *tx_msg, int tx_msg_sz,
+ void *rx_msg, int exp_rx_msg_sz)
+{
+ if (!priv)
+ return -EINVAL;
+
+ return ele_msg_send_rcv(priv->priv_dev_ctx, tx_msg, tx_msg_sz,
+ rx_msg, exp_rx_msg_sz);
+}
+EXPORT_SYMBOL_GPL(imx_se_msg_send_rcv);
+
static bool check_hdr_exception_for_sz(struct se_if_priv *priv,
struct se_msg_hdr *header)
{
@@ -402,8 +432,8 @@ void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg)
}
}
-int se_val_rsp_hdr_n_status(struct se_if_priv *priv, struct se_api_msg *msg,
- u8 msg_id, u8 sz, bool is_base_api)
+int imx_se_val_rsp_hdr_n_status(struct se_if_priv *priv, struct se_api_msg *msg,
+ u8 msg_id, u8 sz, bool is_base_api)
{
struct se_msg_hdr *header = &msg->header;
u32 status;
@@ -450,6 +480,7 @@ int se_val_rsp_hdr_n_status(struct se_if_priv *priv, struct se_api_msg *msg,
return 0;
}
+EXPORT_SYMBOL_GPL(imx_se_val_rsp_hdr_n_status);
int se_save_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem)
{
diff --git a/drivers/firmware/imx/ele_common.h b/drivers/firmware/imx/ele_common.h
index b63a3fbf087a..8f0739960d4d 100644
--- a/drivers/firmware/imx/ele_common.h
+++ b/drivers/firmware/imx/ele_common.h
@@ -28,20 +28,6 @@ int ele_msg_send_rcv(struct se_if_device_ctx *dev_ctx, void *tx_msg,
int tx_msg_sz, void *rx_msg, int exp_rx_msg_sz);
void se_if_rx_callback(struct mbox_client *mbox_cl, void *msg);
-
-int se_val_rsp_hdr_n_status(struct se_if_priv *priv, struct se_api_msg *msg,
- u8 msg_id, u8 sz, bool is_base_api);
-
-/* Fill a command message header with a given command ID and length in bytes. */
-static inline void se_fill_cmd_msg_hdr(struct se_if_priv *priv, struct se_msg_hdr *hdr,
- u8 cmd, u32 len, bool is_base_api)
-{
- hdr->tag = priv->if_defs->cmd_tag;
- hdr->ver = (is_base_api) ? priv->if_defs->base_api_ver : priv->if_defs->fw_api_ver;
- hdr->command = cmd;
- hdr->size = len >> 2;
-}
-
int se_save_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem);
int se_restore_imem_state(struct se_if_priv *priv, struct se_imem_buf *imem);
diff --git a/drivers/firmware/imx/se_ctrl.c b/drivers/firmware/imx/se_ctrl.c
index 3c14964830a6..53f252d2f111 100644
--- a/drivers/firmware/imx/se_ctrl.c
+++ b/drivers/firmware/imx/se_ctrl.c
@@ -911,9 +911,9 @@ static int se_ioctl_cmd_snd_rcv_rsp_handler(struct se_if_device_ctx *dev_ctx,
"message received, start transmit to user");
rsp_status_err =
- se_val_rsp_hdr_n_status(priv, rx_msg, tx_msg->header.command,
- cmd_snd_rcv_rsp_info.rx_buf_sz,
- tx_msg->header.ver == priv->if_defs->base_api_ver);
+ imx_se_val_rsp_hdr_n_status(priv, rx_msg, tx_msg->header.command,
+ cmd_snd_rcv_rsp_info.rx_buf_sz,
+ tx_msg->header.ver == priv->if_defs->base_api_ver);
if (!rsp_status_err) {
err = se_dev_ctx_cpy_out_data(dev_ctx);
diff --git a/drivers/firmware/imx/se_ctrl.h b/drivers/firmware/imx/se_ctrl.h
index af7738ad76cd..76082e8b977c 100644
--- a/drivers/firmware/imx/se_ctrl.h
+++ b/drivers/firmware/imx/se_ctrl.h
@@ -7,6 +7,7 @@
#define SE_CTRL_H
#include <linux/bitfield.h>
+#include <linux/firmware/imx/se_api.h>
#include <linux/miscdevice.h>
#include <linux/mailbox_client.h>
#include <linux/semaphore.h>
@@ -95,22 +96,9 @@ struct se_if_device_ctx {
struct kref refcount;
};
-/* Header of the messages exchange with the EdgeLock Enclave */
-struct se_msg_hdr {
- u8 ver;
- u8 size;
- u8 command;
- u8 tag;
-} __packed;
-
#define SE_MU_HDR_SZ 4
#define SE_MU_HDR_WORD_SZ 1
-struct se_api_msg {
- struct se_msg_hdr header;
- u32 data[];
-};
-
struct se_if_defines {
const u8 se_if_type;
u8 cmd_tag;
diff --git a/include/linux/firmware/imx/se_api.h b/include/linux/firmware/imx/se_api.h
index b1c4c9115d7b..90104ecaaede 100644
--- a/include/linux/firmware/imx/se_api.h
+++ b/include/linux/firmware/imx/se_api.h
@@ -11,4 +11,82 @@
#define SOC_ID_OF_IMX8ULP 0x084d
#define SOC_ID_OF_IMX93 0x9300
+/**
+ * struct se_msg_hdr - Header of the messages exchanged with the secure enclave.
+ * @ver: API version the message conforms to (base or firmware API version).
+ * @size: Message size in 32-bit words, including the header.
+ * @command: Command identifier.
+ * @tag: Message tag identifying it as a command or a response.
+ */
+struct se_msg_hdr {
+ u8 ver;
+ u8 size;
+ u8 command;
+ u8 tag;
+} __packed;
+
+/**
+ * struct se_api_msg - A message exchanged with the secure enclave.
+ * @header: Message header describing the command and its length.
+ * @data: Command or response payload, sized per @header.size.
+ */
+struct se_api_msg {
+ struct se_msg_hdr header;
+ u32 data[];
+};
+
+/* Opaque handle to a secure-enclave interface instance. */
+struct se_if_priv;
+
+/**
+ * imx_se_fill_cmd_msg_hdr() - Populate the header of a command message.
+ * @priv: Secure-enclave interface instance the command targets.
+ * @hdr: Message header to be filled in.
+ * @cmd: Command identifier to place in the header.
+ * @len: Total message length in bytes, including the header.
+ * @is_base_api: %true to tag the message with the base API version, %false to
+ * use the firmware API version.
+ *
+ * Fill in the tag, version, command and size fields of @hdr so that the message
+ * can be sent to the secure enclave.
+ *
+ * Return: 0 on success.
+ */
+int imx_se_fill_cmd_msg_hdr(struct se_if_priv *priv, struct se_msg_hdr *hdr,
+ u8 cmd, u32 len, bool is_base_api);
+
+/**
+ * imx_se_msg_send_rcv() - Send a command to the secure enclave and wait for the
+ * response.
+ * @priv: Secure-enclave interface instance to communicate with.
+ * @tx_msg: Buffer holding the command message to send.
+ * @tx_msg_sz: Size of the command message in bytes.
+ * @rx_msg: Buffer receiving the response message.
+ * @exp_rx_msg_sz: Expected size of the response message in bytes.
+ *
+ * Blocking send/receive helper for external drivers. The transaction is
+ * serialized internally and the misc device context is resolved from @priv.
+ *
+ * Return: number of bytes received on success, or a negative error code.
+ */
+int imx_se_msg_send_rcv(struct se_if_priv *priv, void *tx_msg, int tx_msg_sz,
+ void *rx_msg, int exp_rx_msg_sz);
+
+/**
+ * imx_se_val_rsp_hdr_n_status() - Validate a response header and status code.
+ * @priv: Secure-enclave interface instance the response came from.
+ * @msg: Response message to validate.
+ * @msg_id: Command identifier the response is expected to match.
+ * @sz: Expected response size in bytes.
+ * @is_base_api: %true if the command used the base API version, %false if it
+ * used the firmware API version.
+ *
+ * Check that the response tag, command identifier, size and API version match
+ * the expectations, and that the enclave reported a successful status.
+ *
+ * Return: 0 if the response is valid and successful, or a negative error code.
+ */
+int imx_se_val_rsp_hdr_n_status(struct se_if_priv *priv, struct se_api_msg *msg,
+ u8 msg_id, u8 sz, bool is_base_api);
+
#endif /* __SE_API_H__ */
--
2.55.0
^ permalink raw reply related
* [PATCH v4 00/11] Support ELE API in i.MX OCOTP NVMEM driver
From: Frieder Schrempf @ 2026-07-27 13:00 UTC (permalink / raw)
To: Srinivas Kandagatla, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Pankaj Gupta, Peng Fan (OSS)
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, linux,
Frieder Schrempf, Krzysztof Kozlowski
This patchset depends on "firmware: imx: driver for NXP
secure-enclave" [1].
The imx-ocotp-ele.c driver currently uses the limited FSB (fuseblock)
to access the fuse registers. In order to gain full read/write access
to all fuses, we need to use the Edgelock Secure Enclave firmware.
This patchset does:
* Add bindings to reference ELE device in OCOTP driver (patch 1)
* Export ELE API functions (patch 3)
* Let the OCOTP driver use the ELE API (patch 7)
* Extend the devicetree of i.MX91/i.MX93 boards for using the ELE API
(patch 10/11)
The rest of the patches contain cleanups that were implemented along
the way.
This was tested using the 'crucible' tool and by directly reading
from the nvmem device on i.MX93.
This still lacks support for the i.MX94 and i.MX95 as I don't have
the hardware for testing on these platforms. As the documentations is
incomplete it is hard to get the keepout table right without testing
on the actual hardware. If someone else can provide the data and
testing, I can add it in a future version. If not this can be done
later.
---
Changes in v4:
- Reorder allOf in bindings and extend property description (thanks Krzysztof)
- Add R-b from Krzysztof
- Add R-b from Frank
- Improve scope-based cleanup (thanks Frank)
- Move firmware node from patch 11 to 10
- Link to v3: https://patch.msgid.link/20260723-upstreaming-next-20260609-imx-ocotp-ele-v3-0-e26930345b4c@kontron.de
Changes in v3:
- Fix bindings to correctly ignore the secure-enclave property for SoCs other than i.MX93 (thanks Krzysztof)
- Rebase on latest ELE driver patchset (v29) [1]
- Enable ELE in all board devicetrees (suggested by Francesco)
- Put the reserved memory somewhere in the first 256MB of DDR
- Link to v2: https://patch.msgid.link/20260713-upstreaming-next-20260609-imx-ocotp-ele-v2-0-b8266d93514b@kontron.de
Changes in v2:
- Adjust bindings to allow secure-enclave only for i.MX93 and improve commit message (suggested by Krzysztof)
- Export generic ELE API functions to be used by drivers (suggested by Frank and Peng)
- Move the fuse read/write functions to the NVMEM driver (suggested by Frank and Peng)
- Add patch to use __free(kfree) in imx_ocotp_reg_read() to fix memory leak (reported by Sashiko)
- Use device link to prevent SE device from being unbound while referenced (reported by Sashiko)
- Link to v1: https://patch.msgid.link/20260616-upstreaming-next-20260609-imx-ocotp-ele-v1-0-cb7f3698c3e6@kontron.de
[1] https://patchwork.kernel.org/project/linux-arm-kernel/cover/20260721-imx-se-if-v29-0-04a362f4fcca@nxp.com/
To: Srinivas Kandagatla <srini@kernel.org>
To: Rob Herring <robh@kernel.org>
To: Krzysztof Kozlowski <krzk+dt@kernel.org>
To: Conor Dooley <conor+dt@kernel.org>
To: Frank Li <Frank.Li@nxp.com>
To: Sascha Hauer <s.hauer@pengutronix.de>
To: Pengutronix Kernel Team <kernel@pengutronix.de>
To: Fabio Estevam <festevam@gmail.com>
To: Shawn Guo <shawnguo@kernel.org>
To: Pankaj Gupta <pankaj.gupta@nxp.com>
To: Peng Fan (OSS) <peng.fan@oss.nxp.com>
Cc: devicetree@vger.kernel.org
Cc: imx@lists.linux.dev
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Cc: linux@ew.tq-group.com
---
Frieder Schrempf (11):
dt-bindings: nvmem: imx-ocotp: Add support for secure-enclave
firmware: imx: ele: Fix indentation in ele_base_msg.h
firmware: imx: ele: Export API functions
nvmem: imx-ocotp-ele: Add keepout table for i.MX93
nvmem: imx-ocotp-ele: Remove device-specific reg_read()
nvmem: imx-ocotp-ele: Use scope-based cleanup helpers in imx_ocotp_reg_read()
nvmem: imx-ocotp-ele: Support the ELE API
nvmem: imx-ocotp-ele: Remove the FUSE_ELE type
nvmem: imx-ocotp-ele: Rename FSB access map
arm64: dts: Add ELE firmware node and common include
arm64: dts: Enable EdgeLock Secure Enclave on all i.MX91/i.MX93 boards
.../devicetree/bindings/nvmem/imx-ocotp.yaml | 23 +-
arch/arm64/boot/dts/freescale/imx91-11x11-evk.dts | 1 +
.../boot/dts/freescale/imx91-11x11-frdm-s.dts | 1 +
arch/arm64/boot/dts/freescale/imx91-11x11-frdm.dts | 1 +
arch/arm64/boot/dts/freescale/imx91-9x9-qsb.dts | 1 +
.../boot/dts/freescale/imx91-phycore-som.dtsi | 1 +
arch/arm64/boot/dts/freescale/imx91-tqma9131.dtsi | 15 +-
arch/arm64/boot/dts/freescale/imx91-var-dart.dtsi | 1 +
arch/arm64/boot/dts/freescale/imx91-var-som.dtsi | 1 +
arch/arm64/boot/dts/freescale/imx91_93_common.dtsi | 9 +
.../boot/dts/freescale/imx93-11x11-evk-common.dtsi | 1 +
arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts | 1 +
arch/arm64/boot/dts/freescale/imx93-14x14-evk.dts | 1 +
arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts | 1 +
arch/arm64/boot/dts/freescale/imx93-firmware.dtsi | 28 +++
.../boot/dts/freescale/imx93-kontron-osm-s.dtsi | 1 +
.../boot/dts/freescale/imx93-phycore-som.dtsi | 1 +
arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi | 1 +
arch/arm64/boot/dts/freescale/imx93-var-dart.dtsi | 1 +
arch/arm64/boot/dts/freescale/imx93-var-som.dtsi | 1 +
drivers/firmware/imx/ele_base_msg.c | 42 ++--
drivers/firmware/imx/ele_base_msg.h | 16 +-
drivers/firmware/imx/ele_common.c | 35 ++-
drivers/firmware/imx/ele_common.h | 14 --
drivers/firmware/imx/se_ctrl.c | 6 +-
drivers/firmware/imx/se_ctrl.h | 14 +-
drivers/nvmem/imx-ocotp-ele.c | 239 +++++++++++++++++----
include/linux/firmware/imx/se_api.h | 78 +++++++
28 files changed, 428 insertions(+), 107 deletions(-)
---
base-commit: 6946cd5d0aa4dd10a414ddcb7a10844fdb0ad345
change-id: 20260616-upstreaming-next-20260609-imx-ocotp-ele-a512ddf96b03
prerequisite-change-id: 20240507-imx-se-if-a40055093dc6:v30
prerequisite-patch-id: 0996915f031a1d899202c5fba75a969d6ce2a53d
prerequisite-patch-id: dbed47ecb907f6b7f7e284c5c1a3c325566eafd7
prerequisite-patch-id: d27164b5932b6d7f4bd5494e4058c84841db4d77
prerequisite-patch-id: 6a9642b23090d9f1ae18bc8969e30217d053938b
prerequisite-patch-id: cdd5a258a3157d609115ccf8b8606d1fcdf520e8
prerequisite-patch-id: d6a8cd2161ea713eebeff46d12f6ae1255c24561
prerequisite-patch-id: 1d8b2e78db2815eaace41a13d571171fb58e4221
Best regards,
--
Frieder Schrempf <frieder.schrempf@kontron.de>
^ permalink raw reply
* [PATCH v4 01/11] dt-bindings: nvmem: imx-ocotp: Add support for secure-enclave
From: Frieder Schrempf @ 2026-07-27 13:00 UTC (permalink / raw)
To: Srinivas Kandagatla, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Pankaj Gupta, Peng Fan (OSS)
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, linux,
Frieder Schrempf, Krzysztof Kozlowski
In-Reply-To: <20260727-upstreaming-next-20260609-imx-ocotp-ele-v4-0-1a515de33093@kontron.de>
From: Frieder Schrempf <frieder.schrempf@kontron.de>
The driver currently uses the limited MMIO (FSB) interface to access the
OTPs. The intention is to support the firmware interface alongside the
MMIO interface so the driver can pick the interface that is available
(firmware might not be loaded) and fallback to MMIO.
Some SoCs like the i.MX9 family allow full access to the fuses only
through the secure enclave firmware API. Add a property to reference
the secure enclave node and let the driver use the API.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
.../devicetree/bindings/nvmem/imx-ocotp.yaml | 23 ++++++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml b/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml
index a8076d0e2737..f154856bcdec 100644
--- a/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml
+++ b/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml
@@ -17,10 +17,6 @@ description: |
i.MX7D/S, i.MX7ULP, i.MX8MQ, i.MX8MM, i.MX8MN i.MX8MP, i.MX93, i.MX94,
and i.MX95.
-allOf:
- - $ref: nvmem.yaml#
- - $ref: nvmem-deprecated-cells.yaml#
-
properties:
compatible:
oneOf:
@@ -56,12 +52,31 @@ properties:
clocks:
maxItems: 1
+ secure-enclave:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: A phandle to the secure enclave node for full access to
+ the fuses through firmware API.
+
required:
- "#address-cells"
- "#size-cells"
- compatible
- reg
+allOf:
+ - $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
+ - if:
+ not:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx93-ocotp
+ then:
+ properties:
+ secure-enclave: false
+
unevaluatedProperties: false
examples:
--
2.55.0
^ permalink raw reply related
* [PATCH v4 05/11] nvmem: imx-ocotp-ele: Remove device-specific reg_read()
From: Frieder Schrempf @ 2026-07-27 13:00 UTC (permalink / raw)
To: Srinivas Kandagatla, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Pankaj Gupta, Peng Fan (OSS)
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, linux,
Frieder Schrempf
In-Reply-To: <20260727-upstreaming-next-20260609-imx-ocotp-ele-v4-0-1a515de33093@kontron.de>
From: Frieder Schrempf <frieder.schrempf@kontron.de>
Remove .reg_read() callback in the device data all devices use the
same implementation.
Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
drivers/nvmem/imx-ocotp-ele.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/nvmem/imx-ocotp-ele.c b/drivers/nvmem/imx-ocotp-ele.c
index dadec19ca252..9d3f94e35508 100644
--- a/drivers/nvmem/imx-ocotp-ele.c
+++ b/drivers/nvmem/imx-ocotp-ele.c
@@ -33,7 +33,6 @@ struct ocotp_devtype_data {
u32 size;
u32 num_entry;
u32 flag;
- nvmem_reg_read_t reg_read;
const struct nvmem_keepout *keepout;
unsigned int nkeepout;
struct ocotp_map_entry entry[];
@@ -158,7 +157,7 @@ static int imx_ele_ocotp_probe(struct platform_device *pdev)
priv->config.id = NVMEM_DEVID_AUTO;
priv->config.owner = THIS_MODULE;
priv->config.size = priv->data->size;
- priv->config.reg_read = priv->data->reg_read;
+ priv->config.reg_read = imx_ocotp_reg_read;
priv->config.word_size = 1;
priv->config.stride = 1;
priv->config.priv = priv;
@@ -190,7 +189,6 @@ static const struct nvmem_keepout imx93_ocotp_keepout[] = {
static const struct ocotp_devtype_data imx93_ocotp_data = {
.reg_off = 0x8000,
- .reg_read = imx_ocotp_reg_read,
.size = 2048,
.num_entry = 6,
.entry = {
@@ -207,7 +205,6 @@ static const struct ocotp_devtype_data imx93_ocotp_data = {
static const struct ocotp_devtype_data imx94_ocotp_data = {
.reg_off = 0x8000,
- .reg_read = imx_ocotp_reg_read,
.size = 3296, /* 103 Banks */
.num_entry = 10,
.entry = {
@@ -226,7 +223,6 @@ static const struct ocotp_devtype_data imx94_ocotp_data = {
static const struct ocotp_devtype_data imx95_ocotp_data = {
.reg_off = 0x8000,
- .reg_read = imx_ocotp_reg_read,
.size = 2048,
.num_entry = 12,
.entry = {
--
2.55.0
^ permalink raw reply related
* [PATCH v4 06/11] nvmem: imx-ocotp-ele: Use scope-based cleanup helpers in imx_ocotp_reg_read()
From: Frieder Schrempf @ 2026-07-27 13:00 UTC (permalink / raw)
To: Srinivas Kandagatla, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Pankaj Gupta, Peng Fan (OSS)
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, linux,
Frieder Schrempf
In-Reply-To: <20260727-upstreaming-next-20260609-imx-ocotp-ele-v4-0-1a515de33093@kontron.de>
From: Frieder Schrempf <frieder.schrempf@kontron.de>
This simplifies the code and makes sure that buffers are cleared and
locks are released at the end of the function scope.
Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
drivers/nvmem/imx-ocotp-ele.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/drivers/nvmem/imx-ocotp-ele.c b/drivers/nvmem/imx-ocotp-ele.c
index 9d3f94e35508..010b53001323 100644
--- a/drivers/nvmem/imx-ocotp-ele.c
+++ b/drivers/nvmem/imx-ocotp-ele.c
@@ -5,6 +5,7 @@
* Copyright 2023 NXP
*/
+#include <linux/cleanup.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -71,7 +72,6 @@ static int imx_ocotp_reg_read(void *context, unsigned int offset, void *val, siz
u32 count, index, num_bytes;
enum fuse_type type;
u32 *buf;
- void *p;
int i;
u8 skipbytes;
@@ -83,11 +83,11 @@ static int imx_ocotp_reg_read(void *context, unsigned int offset, void *val, siz
num_bytes = round_up(bytes + skipbytes, 4);
count = num_bytes >> 2;
- p = kzalloc(num_bytes, GFP_KERNEL);
+ void *p __free(kfree) = kzalloc(num_bytes, GFP_KERNEL);
if (!p)
return -ENOMEM;
- mutex_lock(&priv->lock);
+ guard(mutex)(&priv->lock);
buf = p;
@@ -106,10 +106,6 @@ static int imx_ocotp_reg_read(void *context, unsigned int offset, void *val, siz
memcpy(val, ((u8 *)p) + skipbytes, bytes);
- mutex_unlock(&priv->lock);
-
- kfree(p);
-
return 0;
};
--
2.55.0
^ permalink raw reply related
* [PATCH v4 02/11] firmware: imx: ele: Fix indentation in ele_base_msg.h
From: Frieder Schrempf @ 2026-07-27 13:00 UTC (permalink / raw)
To: Srinivas Kandagatla, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Shawn Guo, Pankaj Gupta, Peng Fan (OSS)
Cc: devicetree, imx, linux-arm-kernel, linux-kernel, linux,
Frieder Schrempf
In-Reply-To: <20260727-upstreaming-next-20260609-imx-ocotp-ele-v4-0-1a515de33093@kontron.de>
From: Frieder Schrempf <frieder.schrempf@kontron.de>
The file uses mixed indentation characters. Use tabs everywhere.
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Frieder Schrempf <frieder.schrempf@kontron.de>
---
drivers/firmware/imx/ele_base_msg.h | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/firmware/imx/ele_base_msg.h b/drivers/firmware/imx/ele_base_msg.h
index 475074580dd7..5c128bf56e88 100644
--- a/drivers/firmware/imx/ele_base_msg.h
+++ b/drivers/firmware/imx/ele_base_msg.h
@@ -28,19 +28,19 @@
#define ELE_GEN_KEY_BLOB_REQ 0xaf
#define ELE_GET_FW_STATUS_REQ 0xc5
#define ELE_XIP_DECRYPT_REQ 0xc6
-#define ELE_WRITE_FUSE 0xd6
-#define ELE_DEV_ATTEST_REQ 0xdb
-#define ELE_WRITE_SHADOW_FUSE_REQ 0xf2
-#define ELE_READ_SHADOW_FUSE_REQ 0xf3
+#define ELE_WRITE_FUSE 0xd6
+#define ELE_DEV_ATTEST_REQ 0xdb
+#define ELE_WRITE_SHADOW_FUSE_REQ 0xf2
+#define ELE_READ_SHADOW_FUSE_REQ 0xf3
#define ELE_GET_INFO_REQ 0xda
#define ELE_GET_INFO_REQ_MSG_SZ 0x10
#define ELE_GET_INFO_RSP_MSG_SZ 0x08
-#define MAX_UID_SIZE (16)
-#define DEV_GETINFO_ROM_PATCH_SHA_SZ (32)
-#define DEV_GETINFO_FW_SHA_SZ (32)
-#define DEV_GETINFO_OEM_SRKH_SZ (64)
+#define MAX_UID_SIZE (16)
+#define DEV_GETINFO_ROM_PATCH_SHA_SZ (32)
+#define DEV_GETINFO_FW_SHA_SZ (32)
+#define DEV_GETINFO_OEM_SRKH_SZ (64)
#define DEV_GETINFO_MIN_VER_MASK 0xff
#define DEV_GETINFO_MAJ_VER_MASK 0xff00
#define ELE_DEV_INFO_EXTRA_SZ 0x60
--
2.55.0
^ permalink raw reply related
* [PATCH 1/9] ACPI: use a named initializer for acpi_device_id
From: Pawel Zalewski (The Capable Hub) @ 2026-07-27 12:10 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Bjorn Helgaas, Zhang Rui,
Kai-Heng Feng, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Lorenzo Pieralisi, Sudeep Holla,
Catalin Marinas, Will Deacon, Dan Williams, Vishal Verma,
Dave Jiang, Alison Schofield, Ira Weiny
Cc: linux-acpi, linux-kernel, linux-pci, linux-arm-kernel, nvdimm,
Pawel Zalewski (The Capable Hub)
In-Reply-To: <20260727-acpi-refactor-v1-0-ff900aa326ee@thegoodpenguin.co.uk>
Use a named initializer for the acpi_device_id fields which
makes the code more readable and consistent with how lists
are initialized in the rest of the kernel code base.
While we are at it - unify the list terminator to have
a single space between the brackets.
Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
drivers/acpi/acpi_apd.c | 42 ++--
drivers/acpi/acpi_platform.c | 13 +-
drivers/acpi/acpi_pnp.c | 514 +++++++++++++++++++++---------------------
drivers/acpi/acpi_processor.c | 8 +-
drivers/acpi/acpi_video.c | 2 +-
drivers/acpi/button.c | 12 +-
drivers/acpi/evged.c | 4 +-
drivers/acpi/fan_core.c | 2 +-
drivers/acpi/pfr_telemetry.c | 4 +-
drivers/acpi/pfr_update.c | 4 +-
drivers/acpi/scan.c | 46 ++--
11 files changed, 325 insertions(+), 326 deletions(-)
diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
index 008bd0552cb7..e649c93129b9 100644
--- a/drivers/acpi/acpi_apd.c
+++ b/drivers/acpi/acpi_apd.c
@@ -242,29 +242,29 @@ static int acpi_apd_create_device(struct acpi_device *adev,
static const struct acpi_device_id acpi_apd_device_ids[] = {
/* Generic apd devices */
#ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
- { "AMD0010", APD_ADDR(cz_i2c_desc) },
- { "AMD0020", APD_ADDR(cz_uart_desc) },
- { "AMD0030", },
- { "AMD0040", APD_ADDR(fch_misc_desc)},
- { "AMDI0010", APD_ADDR(wt_i2c_desc) },
- { "AMDI0015", APD_ADDR(wt_i3c_desc) },
- { "AMDI0019", APD_ADDR(wt_i2c_desc) },
- { "AMDI0020", APD_ADDR(cz_uart_desc) },
- { "AMDI0022", APD_ADDR(cz_uart_desc) },
- { "HYGO0010", APD_ADDR(wt_i2c_desc) },
+ { .id = "AMD0010", .driver_data = APD_ADDR(cz_i2c_desc) },
+ { .id = "AMD0020", .driver_data = APD_ADDR(cz_uart_desc) },
+ { .id = "AMD0030" },
+ { .id = "AMD0040", .driver_data = APD_ADDR(fch_misc_desc) },
+ { .id = "AMDI0010", .driver_data = APD_ADDR(wt_i2c_desc) },
+ { .id = "AMDI0015", .driver_data = APD_ADDR(wt_i3c_desc) },
+ { .id = "AMDI0019", .driver_data = APD_ADDR(wt_i2c_desc) },
+ { .id = "AMDI0020", .driver_data = APD_ADDR(cz_uart_desc) },
+ { .id = "AMDI0022", .driver_data = APD_ADDR(cz_uart_desc) },
+ { .id = "HYGO0010", .driver_data = APD_ADDR(wt_i2c_desc) },
#endif
#ifdef CONFIG_ARM64
- { "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
- { "BRCM900D", APD_ADDR(vulcan_spi_desc) },
- { "CAV900D", APD_ADDR(vulcan_spi_desc) },
- { "CAV9007", APD_ADDR(thunderx2_i2c_desc) },
- { "HISI02A1", APD_ADDR(hip07_i2c_desc) },
- { "HISI02A2", APD_ADDR(hip08_i2c_desc) },
- { "HISI02A3", APD_ADDR(hip08_lite_i2c_desc) },
- { "HISI0173", APD_ADDR(hip08_spi_desc) },
- { "LECA0002", APD_ADDR(leca_spi_desc) },
- { "LECA0003", APD_ADDR(leca_i2c_desc) },
- { "NXP0001", APD_ADDR(nxp_i2c_desc) },
+ { .id = "APMC0D0F", .driver_data = APD_ADDR(xgene_i2c_desc) },
+ { .id = "BRCM900D", .driver_data = APD_ADDR(vulcan_spi_desc) },
+ { .id = "CAV900D", .driver_data = APD_ADDR(vulcan_spi_desc) },
+ { .id = "CAV9007", .driver_data = APD_ADDR(thunderx2_i2c_desc) },
+ { .id = "HISI02A1", .driver_data = APD_ADDR(hip07_i2c_desc) },
+ { .id = "HISI02A2", .driver_data = APD_ADDR(hip08_i2c_desc) },
+ { .id = "HISI02A3", .driver_data = APD_ADDR(hip08_lite_i2c_desc) },
+ { .id = "HISI0173", .driver_data = APD_ADDR(hip08_spi_desc) },
+ { .id = "LECA0002", .driver_data = APD_ADDR(leca_spi_desc) },
+ { .id = "LECA0003", .driver_data = APD_ADDR(leca_i2c_desc) },
+ { .id = "NXP0001", .driver_data = APD_ADDR(nxp_i2c_desc) },
#endif
{ }
};
diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c
index a09636a4168e..cf05b4889157 100644
--- a/drivers/acpi/acpi_platform.c
+++ b/drivers/acpi/acpi_platform.c
@@ -24,12 +24,13 @@
#define ACPI_ALLOW_WO_RESOURCES BIT(0)
static const struct acpi_device_id forbidden_id_list[] = {
- {"ACPI0009", 0}, /* IOxAPIC */
- {"ACPI000A", 0}, /* IOAPIC */
- {"PNP0000", 0}, /* PIC */
- {"PNP0100", 0}, /* Timer */
- {"PNP0200", 0}, /* AT DMA Controller */
- {ACPI_SMBUS_MS_HID, ACPI_ALLOW_WO_RESOURCES}, /* ACPI SMBUS virtual device */
+ { .id = "ACPI0009" }, /* IOxAPIC */
+ { .id = "ACPI000A" }, /* IOAPIC */
+ { .id = "PNP0000" }, /* PIC */
+ { .id = "PNP0100" }, /* Timer */
+ { .id = "PNP0200" }, /* AT DMA Controller */
+ { .id = ACPI_SMBUS_MS_HID, .driver_data = ACPI_ALLOW_WO_RESOURCES },
+ /* ACPI SMBUS virtual device */
{ }
};
diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c
index da886923b008..bbacbd03d06a 100644
--- a/drivers/acpi/acpi_pnp.c
+++ b/drivers/acpi/acpi_pnp.c
@@ -15,293 +15,293 @@
static const struct acpi_device_id acpi_pnp_device_ids[] = {
/* pata_isapnp */
- {"PNP0600"}, /* Generic ESDI/IDE/ATA compatible hard disk controller */
+ { .id = "PNP0600" }, /* Generic ESDI/IDE/ATA compatible hard disk controller */
/* floppy */
- {"PNP0700"},
+ { .id = "PNP0700" },
/* tpm_inf_pnp */
- {"IFX0101"}, /* Infineon TPMs */
- {"IFX0102"}, /* Infineon TPMs */
+ { .id = "IFX0101" }, /* Infineon TPMs */
+ { .id = "IFX0102" }, /* Infineon TPMs */
/*tpm_tis */
- {"PNP0C31"}, /* TPM */
- {"ATM1200"}, /* Atmel */
- {"IFX0102"}, /* Infineon */
- {"BCM0101"}, /* Broadcom */
- {"BCM0102"}, /* Broadcom */
- {"NSC1200"}, /* National */
- {"ICO0102"}, /* Intel */
+ { .id = "PNP0C31" }, /* TPM */
+ { .id = "ATM1200" }, /* Atmel */
+ { .id = "IFX0102" }, /* Infineon */
+ { .id = "BCM0101" }, /* Broadcom */
+ { .id = "BCM0102" }, /* Broadcom */
+ { .id = "NSC1200" }, /* National */
+ { .id = "ICO0102" }, /* Intel */
/* ide */
- {"PNP0600"}, /* Generic ESDI/IDE/ATA compatible hard disk controller */
+ { .id = "PNP0600" }, /* Generic ESDI/IDE/ATA compatible hard disk controller */
/* ns558 */
- {"ASB16fd"}, /* AdLib NSC16 */
- {"AZT3001"}, /* AZT1008 */
- {"CDC0001"}, /* Opl3-SAx */
- {"CSC0001"}, /* CS4232 */
- {"CSC000f"}, /* CS4236 */
- {"CSC0101"}, /* CS4327 */
- {"CTL7001"}, /* SB16 */
- {"CTL7002"}, /* AWE64 */
- {"CTL7005"}, /* Vibra16 */
- {"ENS2020"}, /* SoundscapeVIVO */
- {"ESS0001"}, /* ES1869 */
- {"ESS0005"}, /* ES1878 */
- {"ESS6880"}, /* ES688 */
- {"IBM0012"}, /* CS4232 */
- {"OPT0001"}, /* OPTi Audio16 */
- {"YMH0006"}, /* Opl3-SA */
- {"YMH0022"}, /* Opl3-SAx */
- {"PNPb02f"}, /* Generic */
+ { .id = "ASB16fd" }, /* AdLib NSC16 */
+ { .id = "AZT3001" }, /* AZT1008 */
+ { .id = "CDC0001" }, /* Opl3-SAx */
+ { .id = "CSC0001" }, /* CS4232 */
+ { .id = "CSC000f" }, /* CS4236 */
+ { .id = "CSC0101" }, /* CS4327 */
+ { .id = "CTL7001" }, /* SB16 */
+ { .id = "CTL7002" }, /* AWE64 */
+ { .id = "CTL7005" }, /* Vibra16 */
+ { .id = "ENS2020" }, /* SoundscapeVIVO */
+ { .id = "ESS0001" }, /* ES1869 */
+ { .id = "ESS0005" }, /* ES1878 */
+ { .id = "ESS6880" }, /* ES688 */
+ { .id = "IBM0012" }, /* CS4232 */
+ { .id = "OPT0001" }, /* OPTi Audio16 */
+ { .id = "YMH0006" }, /* Opl3-SA */
+ { .id = "YMH0022" }, /* Opl3-SAx */
+ { .id = "PNPb02f" }, /* Generic */
/* i8042 kbd */
- {"PNP0300"},
- {"PNP0301"},
- {"PNP0302"},
- {"PNP0303"},
- {"PNP0304"},
- {"PNP0305"},
- {"PNP0306"},
- {"PNP0309"},
- {"PNP030a"},
- {"PNP030b"},
- {"PNP0320"},
- {"PNP0343"},
- {"PNP0344"},
- {"PNP0345"},
- {"CPQA0D7"},
+ { .id = "PNP0300" },
+ { .id = "PNP0301" },
+ { .id = "PNP0302" },
+ { .id = "PNP0303" },
+ { .id = "PNP0304" },
+ { .id = "PNP0305" },
+ { .id = "PNP0306" },
+ { .id = "PNP0309" },
+ { .id = "PNP030a" },
+ { .id = "PNP030b" },
+ { .id = "PNP0320" },
+ { .id = "PNP0343" },
+ { .id = "PNP0344" },
+ { .id = "PNP0345" },
+ { .id = "CPQA0D7" },
/* i8042 aux */
- {"AUI0200"},
- {"FJC6000"},
- {"FJC6001"},
- {"PNP0f03"},
- {"PNP0f0b"},
- {"PNP0f0e"},
- {"PNP0f12"},
- {"PNP0f13"},
- {"PNP0f19"},
- {"PNP0f1c"},
- {"SYN0801"},
+ { .id = "AUI0200" },
+ { .id = "FJC6000" },
+ { .id = "FJC6001" },
+ { .id = "PNP0f03" },
+ { .id = "PNP0f0b" },
+ { .id = "PNP0f0e" },
+ { .id = "PNP0f12" },
+ { .id = "PNP0f13" },
+ { .id = "PNP0f19" },
+ { .id = "PNP0f1c" },
+ { .id = "SYN0801" },
/* fcpnp */
- {"AVM0900"},
+ { .id = "AVM0900" },
/* radio-cadet */
- {"MSM0c24"}, /* ADS Cadet AM/FM Radio Card */
+ { .id = "MSM0c24" }, /* ADS Cadet AM/FM Radio Card */
/* radio-gemtek */
- {"ADS7183"}, /* AOpen FX-3D/Pro Radio */
+ { .id = "ADS7183" }, /* AOpen FX-3D/Pro Radio */
/* radio-sf16fmr2 */
- {"MFRad13"}, /* tuner subdevice of SF16-FMD2 */
+ { .id = "MFRad13" }, /* tuner subdevice of SF16-FMD2 */
/* ene_ir */
- {"ENE0100"},
- {"ENE0200"},
- {"ENE0201"},
- {"ENE0202"},
+ { .id = "ENE0100" },
+ { .id = "ENE0200" },
+ { .id = "ENE0201" },
+ { .id = "ENE0202" },
/* fintek-cir */
- {"FIT0002"}, /* CIR */
+ { .id = "FIT0002" }, /* CIR */
/* ite-cir */
- {"ITE8704"}, /* Default model */
- {"ITE8713"}, /* CIR found in EEEBox 1501U */
- {"ITE8708"}, /* Bridged IT8512 */
- {"ITE8709"}, /* SRAM-Bridged IT8512 */
+ { .id = "ITE8704" }, /* Default model */
+ { .id = "ITE8713" }, /* CIR found in EEEBox 1501U */
+ { .id = "ITE8708" }, /* Bridged IT8512 */
+ { .id = "ITE8709" }, /* SRAM-Bridged IT8512 */
/* nuvoton-cir */
- {"WEC0530"}, /* CIR */
- {"NTN0530"}, /* CIR for new chip's pnp id */
+ { .id = "WEC0530" }, /* CIR */
+ { .id = "NTN0530" }, /* CIR for new chip's pnp id */
/* Winbond CIR */
- {"WEC1022"},
+ { .id = "WEC1022" },
/* wbsd */
- {"WEC0517"},
- {"WEC0518"},
+ { .id = "WEC0517" },
+ { .id = "WEC0518" },
/* Winbond CIR */
- {"TCM5090"}, /* 3Com Etherlink III (TP) */
- {"TCM5091"}, /* 3Com Etherlink III */
- {"TCM5094"}, /* 3Com Etherlink III (combo) */
- {"TCM5095"}, /* 3Com Etherlink III (TPO) */
- {"TCM5098"}, /* 3Com Etherlink III (TPC) */
- {"PNP80f7"}, /* 3Com Etherlink III compatible */
- {"PNP80f8"}, /* 3Com Etherlink III compatible */
+ { .id = "TCM5090" }, /* 3Com Etherlink III (TP) */
+ { .id = "TCM5091" }, /* 3Com Etherlink III */
+ { .id = "TCM5094" }, /* 3Com Etherlink III (combo) */
+ { .id = "TCM5095" }, /* 3Com Etherlink III (TPO) */
+ { .id = "TCM5098" }, /* 3Com Etherlink III (TPC) */
+ { .id = "PNP80f7" }, /* 3Com Etherlink III compatible */
+ { .id = "PNP80f8" }, /* 3Com Etherlink III compatible */
/* nsc-ircc */
- {"NSC6001"},
- {"HWPC224"},
- {"IBM0071"},
+ { .id = "NSC6001" },
+ { .id = "HWPC224" },
+ { .id = "IBM0071" },
/* smsc-ircc2 */
- {"SMCf010"},
+ { .id = "SMCf010" },
/* parport_pc */
- {"PNP0400"}, /* Standard LPT Printer Port */
- {"PNP0401"}, /* ECP Printer Port */
+ { .id = "PNP0400" }, /* Standard LPT Printer Port */
+ { .id = "PNP0401" }, /* ECP Printer Port */
/* apple-gmux */
- {"APP000B"},
+ { .id = "APP000B" },
/* c6xdigio */
- {"PNP0400"}, /* Standard LPT Printer Port */
- {"PNP0401"}, /* ECP Printer Port */
+ { .id = "PNP0400" }, /* Standard LPT Printer Port */
+ { .id = "PNP0401" }, /* ECP Printer Port */
/* ni_atmio.c */
- {"NIC1900"},
- {"NIC2400"},
- {"NIC2500"},
- {"NIC2600"},
- {"NIC2700"},
+ { .id = "NIC1900" },
+ { .id = "NIC2400" },
+ { .id = "NIC2500" },
+ { .id = "NIC2600" },
+ { .id = "NIC2700" },
/* serial */
- {"AAC000F"}, /* Archtek America Corp. Archtek SmartLink Modem 3334BT Plug & Play */
- {"ADC0001"}, /* Anchor Datacomm BV. SXPro 144 External Data Fax Modem Plug & Play */
- {"ADC0002"}, /* SXPro 288 External Data Fax Modem Plug & Play */
- {"AEI0250"}, /* PROLiNK 1456VH ISA PnP K56flex Fax Modem */
- {"AEI1240"}, /* Actiontec ISA PNP 56K X2 Fax Modem */
- {"AKY1021"}, /* Rockwell 56K ACF II Fax+Data+Voice Modem */
- {"ALI5123"}, /* ALi Fast Infrared Controller */
- {"AZT4001"}, /* AZT3005 PnP SOUND DEVICE */
- {"BDP3336"}, /* Best Data Products Inc. Smart One 336F PnP Modem */
- {"BRI0A49"}, /* Boca Complete Ofc Communicator 14.4 Data-FAX */
- {"BRI1400"}, /* Boca Research 33,600 ACF Modem */
- {"BRI3400"}, /* Boca 33.6 Kbps Internal FD34FSVD */
- {"CPI4050"}, /* Computer Peripherals Inc. EuroViVa CommCenter-33.6 SP PnP */
- {"CTL3001"}, /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */
- {"CTL3011"}, /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
- {"DAV0336"}, /* Davicom ISA 33.6K Modem */
- {"DMB1032"}, /* Creative Modem Blaster Flash56 DI5601-1 */
- {"DMB2001"}, /* Creative Modem Blaster V.90 DI5660 */
- {"ETT0002"}, /* E-Tech CyberBULLET PC56RVP */
- {"FUJ0202"}, /* Fujitsu 33600 PnP-I2 R Plug & Play */
- {"FUJ0205"}, /* Fujitsu FMV-FX431 Plug & Play */
- {"FUJ0206"}, /* Fujitsu 33600 PnP-I4 R Plug & Play */
- {"FUJ0209"}, /* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */
- {"GVC000F"}, /* Archtek SmartLink Modem 3334BT Plug & Play */
- {"GVC0303"}, /* Archtek SmartLink Modem 3334BRV 33.6K Data Fax Voice */
- {"HAY0001"}, /* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */
- {"HAY000C"}, /* Hayes Optima 336 V.34 + FAX + Voice PnP */
- {"HAY000D"}, /* Hayes Optima 336B V.34 + FAX + Voice PnP */
- {"HAY5670"}, /* Hayes Accura 56K Ext Fax Modem PnP */
- {"HAY5674"}, /* Hayes Accura 56K Ext Fax Modem PnP */
- {"HAY5675"}, /* Hayes Accura 56K Fax Modem PnP */
- {"HAYF000"}, /* Hayes 288, V.34 + FAX */
- {"HAYF001"}, /* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */
- {"IBM0033"}, /* IBM Thinkpad 701 Internal Modem Voice */
- {"PNP4972"}, /* Intermec CV60 touchscreen port */
- {"IXDC801"}, /* Intertex 28k8 33k6 Voice EXT PnP */
- {"IXDC901"}, /* Intertex 33k6 56k Voice EXT PnP */
- {"IXDD801"}, /* Intertex 28k8 33k6 Voice SP EXT PnP */
- {"IXDD901"}, /* Intertex 33k6 56k Voice SP EXT PnP */
- {"IXDF401"}, /* Intertex 28k8 33k6 Voice SP INT PnP */
- {"IXDF801"}, /* Intertex 28k8 33k6 Voice SP EXT PnP */
- {"IXDF901"}, /* Intertex 33k6 56k Voice SP EXT PnP */
- {"KOR4522"}, /* KORTEX 28800 Externe PnP */
- {"KORF661"}, /* KXPro 33.6 Vocal ASVD PnP */
- {"LAS4040"}, /* LASAT Internet 33600 PnP */
- {"LAS4540"}, /* Lasat Safire 560 PnP */
- {"LAS5440"}, /* Lasat Safire 336 PnP */
- {"MNP0281"}, /* Microcom TravelPorte FAST V.34 Plug & Play */
- {"MNP0336"}, /* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */
- {"MNP0339"}, /* Microcom DeskPorte FAST EP 28.8 Plug & Play */
- {"MNP0342"}, /* Microcom DeskPorte 28.8P Plug & Play */
- {"MNP0500"}, /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
- {"MNP0501"}, /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
- {"MNP0502"}, /* Microcom DeskPorte 28.8S Internal Plug & Play */
- {"MOT1105"}, /* Motorola BitSURFR Plug & Play */
- {"MOT1111"}, /* Motorola TA210 Plug & Play */
- {"MOT1114"}, /* Motorola HMTA 200 (ISDN) Plug & Play */
- {"MOT1115"}, /* Motorola BitSURFR Plug & Play */
- {"MOT1190"}, /* Motorola Lifestyle 28.8 Internal */
- {"MOT1501"}, /* Motorola V.3400 Plug & Play */
- {"MOT1502"}, /* Motorola Lifestyle 28.8 V.34 Plug & Play */
- {"MOT1505"}, /* Motorola Power 28.8 V.34 Plug & Play */
- {"MOT1509"}, /* Motorola ModemSURFR External 28.8 Plug & Play */
- {"MOT150A"}, /* Motorola Premier 33.6 Desktop Plug & Play */
- {"MOT150F"}, /* Motorola VoiceSURFR 56K External PnP */
- {"MOT1510"}, /* Motorola ModemSURFR 56K External PnP */
- {"MOT1550"}, /* Motorola ModemSURFR 56K Internal PnP */
- {"MOT1560"}, /* Motorola ModemSURFR Internal 28.8 Plug & Play */
- {"MOT1580"}, /* Motorola Premier 33.6 Internal Plug & Play */
- {"MOT15B0"}, /* Motorola OnlineSURFR 28.8 Internal Plug & Play */
- {"MOT15F0"}, /* Motorola VoiceSURFR 56K Internal PnP */
- {"MVX00A1"}, /* Deskline K56 Phone System PnP */
- {"MVX00F2"}, /* PC Rider K56 Phone System PnP */
- {"nEC8241"}, /* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */
- {"PMC2430"}, /* Pace 56 Voice Internal Plug & Play Modem */
- {"PNP0500"}, /* Generic standard PC COM port */
- {"PNP0501"}, /* Generic 16550A-compatible COM port */
- {"PNPC000"}, /* Compaq 14400 Modem */
- {"PNPC001"}, /* Compaq 2400/9600 Modem */
- {"PNPC031"}, /* Dial-Up Networking Serial Cable between 2 PCs */
- {"PNPC032"}, /* Dial-Up Networking Parallel Cable between 2 PCs */
- {"PNPC100"}, /* Standard 9600 bps Modem */
- {"PNPC101"}, /* Standard 14400 bps Modem */
- {"PNPC102"}, /* Standard 28800 bps Modem */
- {"PNPC103"}, /* Standard Modem */
- {"PNPC104"}, /* Standard 9600 bps Modem */
- {"PNPC105"}, /* Standard 14400 bps Modem */
- {"PNPC106"}, /* Standard 28800 bps Modem */
- {"PNPC107"}, /* Standard Modem */
- {"PNPC108"}, /* Standard 9600 bps Modem */
- {"PNPC109"}, /* Standard 14400 bps Modem */
- {"PNPC10A"}, /* Standard 28800 bps Modem */
- {"PNPC10B"}, /* Standard Modem */
- {"PNPC10C"}, /* Standard 9600 bps Modem */
- {"PNPC10D"}, /* Standard 14400 bps Modem */
- {"PNPC10E"}, /* Standard 28800 bps Modem */
- {"PNPC10F"}, /* Standard Modem */
- {"PNP2000"}, /* Standard PCMCIA Card Modem */
- {"ROK0030"}, /* Rockwell 33.6 DPF Internal PnP, Modular Technology 33.6 Internal PnP */
- {"ROK0100"}, /* KORTEX 14400 Externe PnP */
- {"ROK4120"}, /* Rockwell 28.8 */
- {"ROK4920"}, /* Viking 28.8 INTERNAL Fax+Data+Voice PnP */
- {"RSS00A0"}, /* Rockwell 33.6 DPF External PnP, BT Prologue 33.6 External PnP, Modular Technology 33.6 External PnP */
- {"RSS0262"}, /* Viking 56K FAX INT */
- {"RSS0250"}, /* K56 par,VV,Voice,Speakphone,AudioSpan,PnP */
- {"SUP1310"}, /* SupraExpress 28.8 Data/Fax PnP modem */
- {"SUP1381"}, /* SupraExpress 336i PnP Voice Modem */
- {"SUP1421"}, /* SupraExpress 33.6 Data/Fax PnP modem */
- {"SUP1590"}, /* SupraExpress 33.6 Data/Fax PnP modem */
- {"SUP1620"}, /* SupraExpress 336i Sp ASVD */
- {"SUP1760"}, /* SupraExpress 33.6 Data/Fax PnP modem */
- {"SUP2171"}, /* SupraExpress 56i Sp Intl */
- {"TEX0011"}, /* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */
- {"UAC000F"}, /* Archtek SmartLink Modem 3334BT Plug & Play */
- {"USR0000"}, /* 3Com Corp. Gateway Telepath IIvi 33.6 */
- {"USR0002"}, /* U.S. Robotics Sporster 33.6K Fax INT PnP */
- {"USR0004"}, /* Sportster Vi 14.4 PnP FAX Voicemail */
- {"USR0006"}, /* U.S. Robotics 33.6K Voice INT PnP */
- {"USR0007"}, /* U.S. Robotics 33.6K Voice EXT PnP */
- {"USR0009"}, /* U.S. Robotics Courier V.Everything INT PnP */
- {"USR2002"}, /* U.S. Robotics 33.6K Voice INT PnP */
- {"USR2070"}, /* U.S. Robotics 56K Voice INT PnP */
- {"USR2080"}, /* U.S. Robotics 56K Voice EXT PnP */
- {"USR3031"}, /* U.S. Robotics 56K FAX INT */
- {"USR3050"}, /* U.S. Robotics 56K FAX INT */
- {"USR3070"}, /* U.S. Robotics 56K Voice INT PnP */
- {"USR3080"}, /* U.S. Robotics 56K Voice EXT PnP */
- {"USR3090"}, /* U.S. Robotics 56K Voice INT PnP */
- {"USR9100"}, /* U.S. Robotics 56K Message */
- {"USR9160"}, /* U.S. Robotics 56K FAX EXT PnP */
- {"USR9170"}, /* U.S. Robotics 56K FAX INT PnP */
- {"USR9180"}, /* U.S. Robotics 56K Voice EXT PnP */
- {"USR9190"}, /* U.S. Robotics 56K Voice INT PnP */
- {"WACFXXX"}, /* Wacom tablets */
- {"FPI2002"}, /* Compaq touchscreen */
- {"FUJ02B2"}, /* Fujitsu Stylistic touchscreens */
- {"FUJ02B3"},
- {"FUJ02B4"}, /* Fujitsu Stylistic LT touchscreens */
- {"FUJ02B6"}, /* Passive Fujitsu Stylistic touchscreens */
- {"FUJ02B7"},
- {"FUJ02B8"},
- {"FUJ02B9"},
- {"FUJ02BC"},
- {"FUJ02E5"}, /* Fujitsu Wacom Tablet PC device */
- {"FUJ02E6"}, /* Fujitsu P-series tablet PC device */
- {"FUJ02E7"}, /* Fujitsu Wacom 2FGT Tablet PC device */
- {"FUJ02E9"}, /* Fujitsu Wacom 1FGT Tablet PC device */
- {"LTS0001"}, /* LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in disguise) */
- {"WCI0003"}, /* Rockwell's (PORALiNK) 33600 INT PNP */
- {"WEC1022"}, /* Winbond CIR port, should not be probed. We should keep track of it to prevent the legacy serial driver from probing it */
+ { .id = "AAC000F" }, /* Archtek America Corp. Archtek SmartLink Modem 3334BT Plug & Play */
+ { .id = "ADC0001" }, /* Anchor Datacomm BV. SXPro 144 External Data Fax Modem Plug & Play */
+ { .id = "ADC0002" }, /* SXPro 288 External Data Fax Modem Plug & Play */
+ { .id = "AEI0250" }, /* PROLiNK 1456VH ISA PnP K56flex Fax Modem */
+ { .id = "AEI1240" }, /* Actiontec ISA PNP 56K X2 Fax Modem */
+ { .id = "AKY1021" }, /* Rockwell 56K ACF II Fax+Data+Voice Modem */
+ { .id = "ALI5123" }, /* ALi Fast Infrared Controller */
+ { .id = "AZT4001" }, /* AZT3005 PnP SOUND DEVICE */
+ { .id = "BDP3336" }, /* Best Data Products Inc. Smart One 336F PnP Modem */
+ { .id = "BRI0A49" }, /* Boca Complete Ofc Communicator 14.4 Data-FAX */
+ { .id = "BRI1400" }, /* Boca Research 33,600 ACF Modem */
+ { .id = "BRI3400" }, /* Boca 33.6 Kbps Internal FD34FSVD */
+ { .id = "CPI4050" }, /* Computer Peripherals Inc. EuroViVa CommCenter-33.6 SP PnP */
+ { .id = "CTL3001" }, /* Creative Labs Phone Blaster 28.8 DSVD PnP Voice */
+ { .id = "CTL3011" }, /* Creative Labs Modem Blaster 28.8 DSVD PnP Voice */
+ { .id = "DAV0336" }, /* Davicom ISA 33.6K Modem */
+ { .id = "DMB1032" }, /* Creative Modem Blaster Flash56 DI5601-1 */
+ { .id = "DMB2001" }, /* Creative Modem Blaster V.90 DI5660 */
+ { .id = "ETT0002" }, /* E-Tech CyberBULLET PC56RVP */
+ { .id = "FUJ0202" }, /* Fujitsu 33600 PnP-I2 R Plug & Play */
+ { .id = "FUJ0205" }, /* Fujitsu FMV-FX431 Plug & Play */
+ { .id = "FUJ0206" }, /* Fujitsu 33600 PnP-I4 R Plug & Play */
+ { .id = "FUJ0209" }, /* Fujitsu Fax Voice 33600 PNP-I5 R Plug & Play */
+ { .id = "GVC000F" }, /* Archtek SmartLink Modem 3334BT Plug & Play */
+ { .id = "GVC0303" }, /* Archtek SmartLink Modem 3334BRV 33.6K Data Fax Voice */
+ { .id = "HAY0001" }, /* Hayes Optima 288 V.34-V.FC + FAX + Voice Plug & Play */
+ { .id = "HAY000C" }, /* Hayes Optima 336 V.34 + FAX + Voice PnP */
+ { .id = "HAY000D" }, /* Hayes Optima 336B V.34 + FAX + Voice PnP */
+ { .id = "HAY5670" }, /* Hayes Accura 56K Ext Fax Modem PnP */
+ { .id = "HAY5674" }, /* Hayes Accura 56K Ext Fax Modem PnP */
+ { .id = "HAY5675" }, /* Hayes Accura 56K Fax Modem PnP */
+ { .id = "HAYF000" }, /* Hayes 288, V.34 + FAX */
+ { .id = "HAYF001" }, /* Hayes Optima 288 V.34 + FAX + Voice, Plug & Play */
+ { .id = "IBM0033" }, /* IBM Thinkpad 701 Internal Modem Voice */
+ { .id = "PNP4972" }, /* Intermec CV60 touchscreen port */
+ { .id = "IXDC801" }, /* Intertex 28k8 33k6 Voice EXT PnP */
+ { .id = "IXDC901" }, /* Intertex 33k6 56k Voice EXT PnP */
+ { .id = "IXDD801" }, /* Intertex 28k8 33k6 Voice SP EXT PnP */
+ { .id = "IXDD901" }, /* Intertex 33k6 56k Voice SP EXT PnP */
+ { .id = "IXDF401" }, /* Intertex 28k8 33k6 Voice SP INT PnP */
+ { .id = "IXDF801" }, /* Intertex 28k8 33k6 Voice SP EXT PnP */
+ { .id = "IXDF901" }, /* Intertex 33k6 56k Voice SP EXT PnP */
+ { .id = "KOR4522" }, /* KORTEX 28800 Externe PnP */
+ { .id = "KORF661" }, /* KXPro 33.6 Vocal ASVD PnP */
+ { .id = "LAS4040" }, /* LASAT Internet 33600 PnP */
+ { .id = "LAS4540" }, /* Lasat Safire 560 PnP */
+ { .id = "LAS5440" }, /* Lasat Safire 336 PnP */
+ { .id = "MNP0281" }, /* Microcom TravelPorte FAST V.34 Plug & Play */
+ { .id = "MNP0336" }, /* Microcom DeskPorte V.34 FAST or FAST+ Plug & Play */
+ { .id = "MNP0339" }, /* Microcom DeskPorte FAST EP 28.8 Plug & Play */
+ { .id = "MNP0342" }, /* Microcom DeskPorte 28.8P Plug & Play */
+ { .id = "MNP0500" }, /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
+ { .id = "MNP0501" }, /* Microcom DeskPorte FAST ES 28.8 Plug & Play */
+ { .id = "MNP0502" }, /* Microcom DeskPorte 28.8S Internal Plug & Play */
+ { .id = "MOT1105" }, /* Motorola BitSURFR Plug & Play */
+ { .id = "MOT1111" }, /* Motorola TA210 Plug & Play */
+ { .id = "MOT1114" }, /* Motorola HMTA 200 (ISDN) Plug & Play */
+ { .id = "MOT1115" }, /* Motorola BitSURFR Plug & Play */
+ { .id = "MOT1190" }, /* Motorola Lifestyle 28.8 Internal */
+ { .id = "MOT1501" }, /* Motorola V.3400 Plug & Play */
+ { .id = "MOT1502" }, /* Motorola Lifestyle 28.8 V.34 Plug & Play */
+ { .id = "MOT1505" }, /* Motorola Power 28.8 V.34 Plug & Play */
+ { .id = "MOT1509" }, /* Motorola ModemSURFR External 28.8 Plug & Play */
+ { .id = "MOT150A" }, /* Motorola Premier 33.6 Desktop Plug & Play */
+ { .id = "MOT150F" }, /* Motorola VoiceSURFR 56K External PnP */
+ { .id = "MOT1510" }, /* Motorola ModemSURFR 56K External PnP */
+ { .id = "MOT1550" }, /* Motorola ModemSURFR 56K Internal PnP */
+ { .id = "MOT1560" }, /* Motorola ModemSURFR Internal 28.8 Plug & Play */
+ { .id = "MOT1580" }, /* Motorola Premier 33.6 Internal Plug & Play */
+ { .id = "MOT15B0" }, /* Motorola OnlineSURFR 28.8 Internal Plug & Play */
+ { .id = "MOT15F0" }, /* Motorola VoiceSURFR 56K Internal PnP */
+ { .id = "MVX00A1" }, /* Deskline K56 Phone System PnP */
+ { .id = "MVX00F2" }, /* PC Rider K56 Phone System PnP */
+ { .id = "nEC8241" }, /* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */
+ { .id = "PMC2430" }, /* Pace 56 Voice Internal Plug & Play Modem */
+ { .id = "PNP0500" }, /* Generic standard PC COM port */
+ { .id = "PNP0501" }, /* Generic 16550A-compatible COM port */
+ { .id = "PNPC000" }, /* Compaq 14400 Modem */
+ { .id = "PNPC001" }, /* Compaq 2400/9600 Modem */
+ { .id = "PNPC031" }, /* Dial-Up Networking Serial Cable between 2 PCs */
+ { .id = "PNPC032" }, /* Dial-Up Networking Parallel Cable between 2 PCs */
+ { .id = "PNPC100" }, /* Standard 9600 bps Modem */
+ { .id = "PNPC101" }, /* Standard 14400 bps Modem */
+ { .id = "PNPC102" }, /* Standard 28800 bps Modem */
+ { .id = "PNPC103" }, /* Standard Modem */
+ { .id = "PNPC104" }, /* Standard 9600 bps Modem */
+ { .id = "PNPC105" }, /* Standard 14400 bps Modem */
+ { .id = "PNPC106" }, /* Standard 28800 bps Modem */
+ { .id = "PNPC107" }, /* Standard Modem */
+ { .id = "PNPC108" }, /* Standard 9600 bps Modem */
+ { .id = "PNPC109" }, /* Standard 14400 bps Modem */
+ { .id = "PNPC10A" }, /* Standard 28800 bps Modem */
+ { .id = "PNPC10B" }, /* Standard Modem */
+ { .id = "PNPC10C" }, /* Standard 9600 bps Modem */
+ { .id = "PNPC10D" }, /* Standard 14400 bps Modem */
+ { .id = "PNPC10E" }, /* Standard 28800 bps Modem */
+ { .id = "PNPC10F" }, /* Standard Modem */
+ { .id = "PNP2000" }, /* Standard PCMCIA Card Modem */
+ { .id = "ROK0030" }, /* Rockwell 33.6 DPF Internal PnP, Modular Technology 33.6 Internal PnP */
+ { .id = "ROK0100" }, /* KORTEX 14400 Externe PnP */
+ { .id = "ROK4120" }, /* Rockwell 28.8 */
+ { .id = "ROK4920" }, /* Viking 28.8 INTERNAL Fax+Data+Voice PnP */
+ { .id = "RSS00A0" }, /* Rockwell 33.6 DPF External PnP, BT Prologue 33.6 External PnP, Modular Technology 33.6 External PnP */
+ { .id = "RSS0262" }, /* Viking 56K FAX INT */
+ { .id = "RSS0250" }, /* K56 par,VV,Voice,Speakphone,AudioSpan,PnP */
+ { .id = "SUP1310" }, /* SupraExpress 28.8 Data/Fax PnP modem */
+ { .id = "SUP1381" }, /* SupraExpress 336i PnP Voice Modem */
+ { .id = "SUP1421" }, /* SupraExpress 33.6 Data/Fax PnP modem */
+ { .id = "SUP1590" }, /* SupraExpress 33.6 Data/Fax PnP modem */
+ { .id = "SUP1620" }, /* SupraExpress 336i Sp ASVD */
+ { .id = "SUP1760" }, /* SupraExpress 33.6 Data/Fax PnP modem */
+ { .id = "SUP2171" }, /* SupraExpress 56i Sp Intl */
+ { .id = "TEX0011" }, /* Phoebe Micro 33.6 Data Fax 1433VQH Plug & Play */
+ { .id = "UAC000F" }, /* Archtek SmartLink Modem 3334BT Plug & Play */
+ { .id = "USR0000" }, /* 3Com Corp. Gateway Telepath IIvi 33.6 */
+ { .id = "USR0002" }, /* U.S. Robotics Sporster 33.6K Fax INT PnP */
+ { .id = "USR0004" }, /* Sportster Vi 14.4 PnP FAX Voicemail */
+ { .id = "USR0006" }, /* U.S. Robotics 33.6K Voice INT PnP */
+ { .id = "USR0007" }, /* U.S. Robotics 33.6K Voice EXT PnP */
+ { .id = "USR0009" }, /* U.S. Robotics Courier V.Everything INT PnP */
+ { .id = "USR2002" }, /* U.S. Robotics 33.6K Voice INT PnP */
+ { .id = "USR2070" }, /* U.S. Robotics 56K Voice INT PnP */
+ { .id = "USR2080" }, /* U.S. Robotics 56K Voice EXT PnP */
+ { .id = "USR3031" }, /* U.S. Robotics 56K FAX INT */
+ { .id = "USR3050" }, /* U.S. Robotics 56K FAX INT */
+ { .id = "USR3070" }, /* U.S. Robotics 56K Voice INT PnP */
+ { .id = "USR3080" }, /* U.S. Robotics 56K Voice EXT PnP */
+ { .id = "USR3090" }, /* U.S. Robotics 56K Voice INT PnP */
+ { .id = "USR9100" }, /* U.S. Robotics 56K Message */
+ { .id = "USR9160" }, /* U.S. Robotics 56K FAX EXT PnP */
+ { .id = "USR9170" }, /* U.S. Robotics 56K FAX INT PnP */
+ { .id = "USR9180" }, /* U.S. Robotics 56K Voice EXT PnP */
+ { .id = "USR9190" }, /* U.S. Robotics 56K Voice INT PnP */
+ { .id = "WACFXXX" }, /* Wacom tablets */
+ { .id = "FPI2002" }, /* Compaq touchscreen */
+ { .id = "FUJ02B2" }, /* Fujitsu Stylistic touchscreens */
+ { .id = "FUJ02B3" },
+ { .id = "FUJ02B4" }, /* Fujitsu Stylistic LT touchscreens */
+ { .id = "FUJ02B6" }, /* Passive Fujitsu Stylistic touchscreens */
+ { .id = "FUJ02B7" },
+ { .id = "FUJ02B8" },
+ { .id = "FUJ02B9" },
+ { .id = "FUJ02BC" },
+ { .id = "FUJ02E5" }, /* Fujitsu Wacom Tablet PC device */
+ { .id = "FUJ02E6" }, /* Fujitsu P-series tablet PC device */
+ { .id = "FUJ02E7" }, /* Fujitsu Wacom 2FGT Tablet PC device */
+ { .id = "FUJ02E9" }, /* Fujitsu Wacom 1FGT Tablet PC device */
+ { .id = "LTS0001" }, /* LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in disguise) */
+ { .id = "WCI0003" }, /* Rockwell's (PORALiNK) 33600 INT PNP */
+ { .id = "WEC1022" }, /* Winbond CIR port, should not be probed. We should keep track of it to prevent the legacy serial driver from probing it */
/* scl200wdt */
- {"NSC0800"}, /* National Semiconductor PC87307/PC97307 watchdog component */
+ { .id = "NSC0800" }, /* National Semiconductor PC87307/PC97307 watchdog component */
/* mpu401 */
- {"PNPb006"},
+ { .id = "PNPb006" },
/* cs423x-pnpbios */
- {"CSC0100"},
- {"CSC0103"},
- {"CSC0110"},
- {"CSC0000"},
- {"GIM0100"}, /* Guillemot Turtlebeach something appears to be cs4232 compatible */
+ { .id = "CSC0100" },
+ { .id = "CSC0103" },
+ { .id = "CSC0110" },
+ { .id = "CSC0000" },
+ { .id = "GIM0100" }, /* Guillemot Turtlebeach something appears to be cs4232 compatible */
/* es18xx-pnpbios */
- {"ESS1869"},
- {"ESS1879"},
+ { .id = "ESS1869" },
+ { .id = "ESS1879" },
/* snd-opl3sa2-pnpbios */
- {"YMH0021"},
- {"NMX2210"}, /* Gateway Solo 2500 */
- {""},
+ { .id = "YMH0021" },
+ { .id = "NMX2210" }, /* Gateway Solo 2500 */
+ { }
};
static bool matching_id(const char *idstr, const char *list_id)
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c
index 00775b91bd41..4f206681070e 100644
--- a/drivers/acpi/acpi_processor.c
+++ b/drivers/acpi/acpi_processor.c
@@ -630,10 +630,8 @@ void __init acpi_early_processor_control_setup(void)
* processor devices.
*/
static const struct acpi_device_id processor_device_ids[] = {
-
- { ACPI_PROCESSOR_OBJECT_HID, },
- { ACPI_PROCESSOR_DEVICE_HID, },
-
+ { .id = ACPI_PROCESSOR_OBJECT_HID },
+ { .id = ACPI_PROCESSOR_DEVICE_HID },
{ }
};
@@ -655,7 +653,7 @@ static int acpi_processor_container_attach(struct acpi_device *dev,
}
static const struct acpi_device_id processor_container_ids[] = {
- { ACPI_PROCESSOR_CONTAINER_HID, },
+ { .id = ACPI_PROCESSOR_CONTAINER_HID },
{ }
};
diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c
index f93e877f87f6..c10f07ac8d61 100644
--- a/drivers/acpi/acpi_video.c
+++ b/drivers/acpi/acpi_video.c
@@ -92,7 +92,7 @@ enum acpi_video_level_idx {
static const struct auxiliary_device_id video_bus_auxiliary_id_table[] = {
{ .name = "acpi.video_bus" },
- {},
+ { }
};
MODULE_DEVICE_TABLE(auxiliary, video_bus_auxiliary_id_table);
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 3836ee75dd66..4b3b2dbf0d27 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -60,12 +60,12 @@ MODULE_DESCRIPTION("ACPI Button Driver");
MODULE_LICENSE("GPL");
static const struct acpi_device_id button_device_ids[] = {
- {ACPI_BUTTON_HID_LID, ACPI_BUTTON_TYPE_LID},
- {ACPI_BUTTON_HID_SLEEP, ACPI_BUTTON_TYPE_SLEEP},
- {ACPI_BUTTON_HID_SLEEPF, ACPI_BUTTON_TYPE_SLEEP},
- {ACPI_BUTTON_HID_POWER, ACPI_BUTTON_TYPE_POWER},
- {ACPI_BUTTON_HID_POWERF, ACPI_BUTTON_TYPE_POWER},
- {"", 0},
+ { .id = ACPI_BUTTON_HID_LID, .driver_data = ACPI_BUTTON_TYPE_LID },
+ { .id = ACPI_BUTTON_HID_SLEEP, .driver_data = ACPI_BUTTON_TYPE_SLEEP },
+ { .id = ACPI_BUTTON_HID_SLEEPF, .driver_data = ACPI_BUTTON_TYPE_SLEEP },
+ { .id = ACPI_BUTTON_HID_POWER, .driver_data = ACPI_BUTTON_TYPE_POWER },
+ { .id = ACPI_BUTTON_HID_POWERF, .driver_data = ACPI_BUTTON_TYPE_POWER },
+ { }
};
MODULE_DEVICE_TABLE(acpi, button_device_ids);
diff --git a/drivers/acpi/evged.c b/drivers/acpi/evged.c
index 5c35cbc7f6ff..c7a00dc62247 100644
--- a/drivers/acpi/evged.c
+++ b/drivers/acpi/evged.c
@@ -179,8 +179,8 @@ static void ged_remove(struct platform_device *pdev)
}
static const struct acpi_device_id ged_acpi_ids[] = {
- {"ACPI0013"},
- {},
+ { .id = "ACPI0013" },
+ { }
};
static struct platform_driver ged_driver = {
diff --git a/drivers/acpi/fan_core.c b/drivers/acpi/fan_core.c
index fb08b8549ed7..5f42cb487206 100644
--- a/drivers/acpi/fan_core.c
+++ b/drivers/acpi/fan_core.c
@@ -46,7 +46,7 @@ MODULE_PARM_DESC(min_trip_distance, "Minimum distance between fan speed trip poi
static const struct acpi_device_id fan_device_ids[] = {
ACPI_FAN_DEVICE_IDS,
- {"", 0},
+ { }
};
MODULE_DEVICE_TABLE(acpi, fan_device_ids);
diff --git a/drivers/acpi/pfr_telemetry.c b/drivers/acpi/pfr_telemetry.c
index 2387376832a1..ea6db4be4deb 100644
--- a/drivers/acpi/pfr_telemetry.c
+++ b/drivers/acpi/pfr_telemetry.c
@@ -415,8 +415,8 @@ static int acpi_pfrt_log_probe(struct platform_device *pdev)
}
static const struct acpi_device_id acpi_pfrt_log_ids[] = {
- {"INTC1081"},
- {}
+ { .id = "INTC1081" },
+ { }
};
MODULE_DEVICE_TABLE(acpi, acpi_pfrt_log_ids);
diff --git a/drivers/acpi/pfr_update.c b/drivers/acpi/pfr_update.c
index 6283105bb0e8..80bef3af35c5 100644
--- a/drivers/acpi/pfr_update.c
+++ b/drivers/acpi/pfr_update.c
@@ -591,8 +591,8 @@ static int acpi_pfru_probe(struct platform_device *pdev)
}
static const struct acpi_device_id acpi_pfru_ids[] = {
- {"INTC1080"},
- {}
+ { .id = "INTC1080" },
+ { }
};
MODULE_DEVICE_TABLE(acpi, acpi_pfru_ids);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 9a7ac2eb9ce0..e92473bcd586 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1005,9 +1005,9 @@ static int acpi_bus_extract_wakeup_device_power_package(struct acpi_device *dev)
static bool acpi_wakeup_gpe_init(struct acpi_device *device)
{
static const struct acpi_device_id button_device_ids[] = {
- {"PNP0C0D", 0}, /* Lid */
- {"PNP0C0E", 0}, /* Sleep button */
- {"", 0},
+ { .id = "PNP0C0D" }, /* Lid */
+ { .id = "PNP0C0E" }, /* Sleep button */
+ { }
};
struct acpi_device_wakeup *wakeup = &device->wakeup;
const struct acpi_device_id *match;
@@ -1731,8 +1731,8 @@ static bool acpi_is_indirect_io_slave(struct acpi_device *device)
{
struct acpi_device *parent = acpi_dev_parent(device);
static const struct acpi_device_id indirect_io_hosts[] = {
- {"HISI0191", 0},
- {}
+ { .id = "HISI0191" },
+ { }
};
return parent && !acpi_match_device_ids(parent, indirect_io_hosts);
@@ -1752,33 +1752,33 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
* by the drivers/platform/x86/serial-multi-instantiate.c driver, which
* knows which client device id to use for each resource.
*/
- {"BSG1160", },
- {"BSG2150", },
- {"CSC3551", },
- {"CSC3554", },
- {"CSC3556", },
- {"CSC3557", },
- {"INT33FE", },
- {"INT3515", },
- {"TXNW2781", },
+ { .id = "BSG1160" },
+ { .id = "BSG2150" },
+ { .id = "CSC3551" },
+ { .id = "CSC3554" },
+ { .id = "CSC3556" },
+ { .id = "CSC3557" },
+ { .id = "INT33FE" },
+ { .id = "INT3515" },
+ { .id = "TXNW2781" },
/* Non-conforming _HID for Cirrus Logic already released */
- {"CLSA0100", },
- {"CLSA0101", },
+ { .id = "CLSA0100" },
+ { .id = "CLSA0101" },
/*
* Some ACPI devs contain SerialBus resources even though they are not
* attached to a serial bus at all.
*/
- {ACPI_VIDEO_HID, },
- {"MSHW0028", },
+ { .id = ACPI_VIDEO_HID },
+ { .id = "MSHW0028" },
/*
* HIDs of device with an UartSerialBusV2 resource for which userspace
* expects a regular tty cdev to be created (instead of the in kernel
* serdev) and which have a kernel driver which expects a platform_dev
* such as the rfkill-gpio driver.
*/
- {"BCM4752", },
- {"LNV4752", },
- {}
+ { .id = "BCM4752", },
+ { .id = "LNV4752", },
+ { }
};
if (acpi_is_indirect_io_slave(device))
@@ -2284,8 +2284,8 @@ static void acpi_default_enumeration(struct acpi_device *device)
}
static const struct acpi_device_id generic_device_ids[] = {
- {ACPI_DT_NAMESPACE_HID, },
- {"", },
+ { .id = ACPI_DT_NAMESPACE_HID },
+ { }
};
static int acpi_generic_device_attach(struct acpi_device *adev,
--
2.43.0
^ permalink raw reply related
* Re: [PATCH 2/3] usb: typec: tipd: Factor out i2c specifics
From: Heikki Krogerus @ 2026-07-27 12:56 UTC (permalink / raw)
To: Sasha Finkelstein
Cc: Sven Peter, Janne Grunau, Neal Gompa, Greg Kroah-Hartman,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, asahi,
linux-arm-kernel, linux-usb, devicetree, linux-kernel,
Alyssa Milburn
In-Reply-To: <20260725-tipd-ace3-v1-2-73202d36138a@chaosmail.tech>
Hi,
On Sat, Jul 25, 2026 at 06:20:57PM +0200, Sasha Finkelstein wrote:
> From: Alyssa Milburn <amilburn@zall.org>
>
> Make the core driver more bus-agnostic to prepare for SPMI variants of
> the tipd chip
>
> Signed-off-by: Alyssa Milburn <amilburn@zall.org>
> Signed-off-by: Sasha Finkelstein <k@chaosmail.tech>
> ---
> drivers/usb/typec/tipd/Makefile | 2 +-
> drivers/usb/typec/tipd/{core.c => core.h} | 109 ++++++++++++++++++++++++++++---------------------------------------------------------------------------------
That has to be a mistake, right? You don't move code into a header
like that.
> drivers/usb/typec/tipd/i2c.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 115 insertions(+), 82 deletions(-)
>
> diff --git a/drivers/usb/typec/tipd/Makefile b/drivers/usb/typec/tipd/Makefile
> index aa439f80a889..ba38daee9e72 100644
> --- a/drivers/usb/typec/tipd/Makefile
> +++ b/drivers/usb/typec/tipd/Makefile
> @@ -2,5 +2,5 @@
> CFLAGS_trace.o := -I$(src)
>
> obj-$(CONFIG_TYPEC_TPS6598X) += tps6598x.o
> -tps6598x-y := core.o
> +tps6598x-y := i2c.o
Now I'm worried. Are you really planning on putting the code into the
header?
You should keep the core independent of the glue drivers, even if core
is just a library. I'm expecting to see something like this here:
obj-$(CONFIG_TYPEC_TPS6598X) += tps6598x.o
tps6598x-y := core.o
+tps6598x-$(CONFIG_I2C) += i2c.o
> tps6598x-$(CONFIG_TRACING) += trace.o
> diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.h
> similarity index 95%
> rename from drivers/usb/typec/tipd/core.c
> rename to drivers/usb/typec/tipd/core.h
> index d5ee0af9058b..1ba29e439e01 100644
> --- a/drivers/usb/typec/tipd/core.c
> +++ b/drivers/usb/typec/tipd/core.h
> @@ -9,7 +9,6 @@
> #include <linux/i2c.h>
> #include <linux/acpi.h>
> #include <linux/gpio/consumer.h>
> -#include <linux/module.h>
> #include <linux/of.h>
> #include <linux/power_supply.h>
> #include <linux/regmap.h>
> @@ -167,6 +166,7 @@ struct tps6598x {
> struct device *dev;
> struct regmap *regmap;
> struct mutex lock; /* device lock */
> + int irq;
> u8 i2c_protocol:1;
>
> struct gpio_desc *reset;
> @@ -231,6 +231,13 @@ static const char *tps6598x_psy_name_prefix = "tps6598x-source-psy-";
> */
> #define TPS_MAX_LEN 64
>
> +static struct tps6598x *tps6598x_from_device(struct device *dev)
> +{
> + struct i2c_client *client = i2c_verify_client(dev);
> + struct tps6598x *tps = i2c_get_clientdata(client);
> + return tps;
> +}
You should not need anything like that.
> static int
> tps6598x_block_read(struct tps6598x *tps, u8 reg, void *val, size_t len)
> {
> @@ -1738,27 +1745,13 @@ static void cd321x_remove(struct tps6598x *tps)
> cancel_delayed_work_sync(&cd321x->update_work);
> }
>
> -static int tps6598x_probe(struct i2c_client *client)
> +static int tps6598x_probe(struct tps6598x *tps)
So you really were planning on putting this into a header :(
The header will have only the definitions and prototypes that the
glue drivers such as that i2c.c need. The implementation of this
functions stays in core.c. It just not static anymore.
You should have something like this in core.c:
-static int tps6598x_probe(struct i2c_client *client)
+int tipd_init(struct tps6598x *tps)
{
...
}
+EXPORT_SYMBOL_GPL(tipd_init);
> {
> - const struct tipd_data *data;
> - struct tps6598x *tps;
> struct fwnode_handle *fwnode;
> u32 status;
> u32 vid;
> int ret;
>
> - data = i2c_get_match_data(client);
> - if (!data)
> - return -EINVAL;
> -
> - tps = devm_kzalloc(&client->dev, data->tps_struct_size, GFP_KERNEL);
> - if (!tps)
> - return -ENOMEM;
> -
> - mutex_init(&tps->lock);
> - tps->dev = &client->dev;
> - tps->data = data;
> -
> tps->reset = devm_gpiod_get_optional(tps->dev, "reset", GPIOD_OUT_LOW);
> if (IS_ERR(tps->reset))
> return dev_err_probe(tps->dev, PTR_ERR(tps->reset),
> @@ -1766,23 +1759,12 @@ static int tps6598x_probe(struct i2c_client *client)
> if (tps->reset)
> msleep(TPS_SETUP_MS);
>
> - tps->regmap = devm_regmap_init_i2c(client, &tps6598x_regmap_config);
> - if (IS_ERR(tps->regmap))
> - return PTR_ERR(tps->regmap);
> -
> if (!device_is_compatible(tps->dev, "ti,tps25750")) {
> ret = tps6598x_read32(tps, TPS_REG_VID, &vid);
> if (ret < 0 || !vid)
> return -ENODEV;
> }
>
> - /*
> - * Checking can the adapter handle SMBus protocol. If it can not, the
> - * driver needs to take care of block reads separately.
> - */
> - if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
> - tps->i2c_protocol = true;
> -
> if (tps->data->switch_power_state) {
> ret = tps->data->switch_power_state(tps, TPS_SYSTEM_POWER_STATE_S0);
> if (ret)
> @@ -1816,7 +1798,7 @@ static int tps6598x_probe(struct i2c_client *client)
> * with existing DT files, we work around this by deleting any
> * fwnode_links to/from this fwnode.
> */
> - fwnode = device_get_named_child_node(&client->dev, "connector");
> + fwnode = device_get_named_child_node(tps->dev, "connector");
> if (fwnode)
> fw_devlink_purge_absent_suppliers(fwnode);
>
> @@ -1842,14 +1824,14 @@ static int tps6598x_probe(struct i2c_client *client)
> goto err_unregister_port;
> ret = tps->data->connect(tps, status);
> if (ret)
> - dev_err(&client->dev, "failed to register partner\n");
> + dev_err(tps->dev, "failed to register partner\n");
> }
>
> - if (client->irq) {
> - ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
> + if (tps->irq) {
> + ret = devm_request_threaded_irq(tps->dev, tps->irq, NULL,
> tps->data->irq_handler,
> IRQF_SHARED | IRQF_ONESHOT,
> - dev_name(&client->dev), tps);
> + dev_name(tps->dev), tps);
> } else {
> dev_warn(tps->dev, "Unable to find the interrupt, switching to polling\n");
> INIT_DELAYED_WORK(&tps->wq_poll, tps6598x_poll_work);
> @@ -1860,13 +1842,12 @@ static int tps6598x_probe(struct i2c_client *client)
> if (ret)
> goto err_disconnect;
>
> - i2c_set_clientdata(client, tps);
> fwnode_handle_put(fwnode);
>
> tps->wakeup = device_property_read_bool(tps->dev, "wakeup-source");
> - if (tps->wakeup && client->irq) {
> - devm_device_init_wakeup(&client->dev);
> - enable_irq_wake(client->irq);
> + if (tps->wakeup && tps->irq) {
> + devm_device_init_wakeup(tps->dev);
> + enable_irq_wake(tps->irq);
> }
>
> return 0;
> @@ -1888,14 +1869,12 @@ static int tps6598x_probe(struct i2c_client *client)
> return ret;
> }
>
> -static void tps6598x_remove(struct i2c_client *client)
> +static void tps6598x_remove(struct tps6598x *tps)
> {
> - struct tps6598x *tps = i2c_get_clientdata(client);
> -
> - if (!client->irq)
> + if (!tps->irq)
> cancel_delayed_work_sync(&tps->wq_poll);
> else
> - devm_free_irq(tps->dev, client->irq, tps);
> + devm_free_irq(tps->dev, tps->irq, tps);
>
> if (tps->data->remove)
> tps->data->remove(tps);
> @@ -1913,17 +1892,16 @@ static void tps6598x_remove(struct i2c_client *client)
>
> static int __maybe_unused tps6598x_suspend(struct device *dev)
> {
> - struct i2c_client *client = to_i2c_client(dev);
> - struct tps6598x *tps = i2c_get_clientdata(client);
> + struct tps6598x *tps = tps6598x_from_device(dev);
>
> if (tps->wakeup) {
> - disable_irq(client->irq);
> - enable_irq_wake(client->irq);
> + disable_irq(tps->irq);
> + enable_irq_wake(tps->irq);
> } else if (tps->reset) {
> gpiod_set_value_cansleep(tps->reset, 1);
> }
>
> - if (!client->irq)
> + if (!tps->irq)
> cancel_delayed_work_sync(&tps->wq_poll);
>
> return 0;
> @@ -1931,8 +1909,7 @@ static int __maybe_unused tps6598x_suspend(struct device *dev)
>
> static int __maybe_unused tps6598x_resume(struct device *dev)
> {
> - struct i2c_client *client = to_i2c_client(dev);
> - struct tps6598x *tps = i2c_get_clientdata(client);
> + struct tps6598x *tps = tps6598x_from_device(dev);
> int ret;
>
> ret = tps6598x_check_mode(tps);
> @@ -1946,14 +1923,14 @@ static int __maybe_unused tps6598x_resume(struct device *dev)
> }
>
> if (tps->wakeup) {
> - disable_irq_wake(client->irq);
> - enable_irq(client->irq);
> + disable_irq_wake(tps->irq);
> + enable_irq(tps->irq);
> } else if (tps->reset) {
> gpiod_set_value_cansleep(tps->reset, 0);
> msleep(TPS_SETUP_MS);
> }
>
> - if (!client->irq)
> + if (!tps->irq)
> queue_delayed_work(system_power_efficient_wq, &tps->wq_poll,
> msecs_to_jiffies(POLL_INTERVAL));
The PM callbacks should be in the glue drivers. You can provide
separate suspend and resume functions here that the glue drivers can
call from their PM callbacks:
int tipd_suspend(struct tps6598x *tps)
{
...
}
EXPORT_SYMBOL_GPL(tipd_suspend);
int tipd_resume(struct tps6598x *tps)
{
...
}
EXPORT_SYMBOL_GPL(tipd_suspend);
> @@ -2018,33 +1995,3 @@ static const struct tipd_data tps25750_data = {
> .reset = tps25750_reset,
> .connect = tps6598x_connect,
> };
> -
> -static const struct of_device_id tps6598x_of_match[] = {
> - { .compatible = "ti,tps6598x", &tps6598x_data},
> - { .compatible = "apple,cd321x", &cd321x_data},
> - { .compatible = "ti,tps25750", &tps25750_data},
> - {}
> -};
> -MODULE_DEVICE_TABLE(of, tps6598x_of_match);
> -
> -static const struct i2c_device_id tps6598x_id[] = {
> - { .name = "tps6598x", .driver_data = (kernel_ulong_t)&tps6598x_data },
> - { }
> -};
> -MODULE_DEVICE_TABLE(i2c, tps6598x_id);
> -
> -static struct i2c_driver tps6598x_i2c_driver = {
> - .driver = {
> - .name = "tps6598x",
> - .pm = &tps6598x_pm_ops,
> - .of_match_table = tps6598x_of_match,
> - },
> - .probe = tps6598x_probe,
> - .remove = tps6598x_remove,
> - .id_table = tps6598x_id,
> -};
> -module_i2c_driver(tps6598x_i2c_driver);
> -
> -MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>");
> -MODULE_LICENSE("GPL v2");
> -MODULE_DESCRIPTION("TI TPS6598x USB Power Delivery Controller Driver");
> diff --git a/drivers/usb/typec/tipd/i2c.c b/drivers/usb/typec/tipd/i2c.c
> new file mode 100644
> index 000000000000..0233e19290ea
> --- /dev/null
> +++ b/drivers/usb/typec/tipd/i2c.c
> @@ -0,0 +1,86 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Driver for TI TPS6598x USB Power Delivery controller family
> + *
> + * Copyright (C) 2017, Intel Corporation
> + * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> + */
This driver is not coming from me.
> +#include <linux/module.h>
> +
> +#include "core.h"
> +
> +static int tps6598x_probe_i2c(struct i2c_client *client)
> +{
> + const struct tipd_data *data;
> + struct tps6598x *tps;
> + int ret;
> +
> + data = i2c_get_match_data(client);
> + if (!data)
> + return -EINVAL;
> +
> + tps = devm_kzalloc(&client->dev, data->tps_struct_size, GFP_KERNEL);
> + if (!tps)
> + return -ENOMEM;
> +
> + mutex_init(&tps->lock);
> + tps->dev = &client->dev;
> + tps->data = data;
> + tps->irq = client->irq;
> +
> + tps->regmap = devm_regmap_init_i2c(client, &tps6598x_regmap_config);
> + if (IS_ERR(tps->regmap))
> + return PTR_ERR(tps->regmap);
> +
> + /*
> + * Checking can the adapter handle SMBus protocol. If it can not, the
> + * driver needs to take care of block reads separately.
> + */
> + if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
> + tps->i2c_protocol = true;
> +
> + ret = tps6598x_probe(tps);
> +
> + if (ret == 0)
> + i2c_set_clientdata(client, tps);
> +
> + return ret;
> +}
> +
> +static void tps6598x_remove_i2c(struct i2c_client *client)
> +{
> + struct tps6598x *tps = i2c_get_clientdata(client);
> +
> + tps6598x_remove(tps);
> +}
> +
> +static const struct of_device_id tps6598x_of_match[] = {
> + { .compatible = "ti,tps6598x", &tps6598x_data},
> + { .compatible = "apple,cd321x", &cd321x_data},
> + { .compatible = "ti,tps25750", &tps25750_data},
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, tps6598x_of_match);
> +
> +static const struct i2c_device_id tps6598x_id[] = {
> + { .name = "tps6598x", .driver_data = (kernel_ulong_t)&tps6598x_data },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, tps6598x_id);
> +
> +static struct i2c_driver tps6598x_i2c_driver = {
> + .driver = {
> + .name = "tps6598x",
> + .pm = &tps6598x_pm_ops,
> + .of_match_table = tps6598x_of_match,
> + },
> + .probe = tps6598x_probe_i2c,
> + .remove = tps6598x_remove_i2c,
> + .id_table = tps6598x_id,
> +};
> +module_i2c_driver(tps6598x_i2c_driver);
> +
> +MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>");
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("TI TPS6598x USB Power Delivery Controller Driver");
You need to change that too. The glue drivers will be separate
modules and the core will stay as its own module.
Thanks,
--
heikki
^ permalink raw reply
* [PATCH 4/9] ACPI: ghes-nvidia: use a named initializer for acpi_device_id::id
From: Pawel Zalewski (The Capable Hub) @ 2026-07-27 12:10 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Bjorn Helgaas, Zhang Rui,
Kai-Heng Feng, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Lorenzo Pieralisi, Sudeep Holla,
Catalin Marinas, Will Deacon, Dan Williams, Vishal Verma,
Dave Jiang, Alison Schofield, Ira Weiny
Cc: linux-acpi, linux-kernel, linux-pci, linux-arm-kernel, nvdimm,
Pawel Zalewski (The Capable Hub)
In-Reply-To: <20260727-acpi-refactor-v1-0-ff900aa326ee@thegoodpenguin.co.uk>
Use a named initializer for the acpi_device_id::id field for
readability.
Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
drivers/acpi/apei/ghes-nvidia.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/acpi/apei/ghes-nvidia.c b/drivers/acpi/apei/ghes-nvidia.c
index 597275d81de8..1d3a6997a019 100644
--- a/drivers/acpi/apei/ghes-nvidia.c
+++ b/drivers/acpi/apei/ghes-nvidia.c
@@ -130,7 +130,7 @@ static int nvidia_ghes_probe(struct platform_device *pdev)
}
static const struct acpi_device_id nvidia_ghes_acpi_match[] = {
- { "NVDA2012" },
+ { .id = "NVDA2012" },
{ }
};
MODULE_DEVICE_TABLE(acpi, nvidia_ghes_acpi_match);
--
2.43.0
^ permalink raw reply related
* Re: [v2 1/2] soc: fsl: dpio: Use scope-based resource management in dpaa2_io_store_create()
From: Markus Elfring @ 2026-07-27 12:52 UTC (permalink / raw)
To: Ioana Ciornei, linux-arm-kernel, linuxppc-dev
Cc: Christophe Leroy, Roy Pledge, LKML, kernel-janitors
In-Reply-To: <55dkpjlibtfurmrrzxzznq6e3dhxvo76rsrjnokkaquwktl74r@omft73n4kp52>
>>>> * Omit the local variable “size” (for another memory allocation).
>>>
>>> Please remove this change, not related to the intention of the patch.
>> What does hinder to perform the required size determination as a direct parameter
>> for a kzalloc() call?
>
> Nothing, but it's a different change. On top of this, it's just churning
> the code without an added benefit.
It influences development concerns also according to preferred variable scopes.
Regards,
Markus
^ permalink raw reply
* Re: [PATCH] drm/mediatek: mtk_dsi: enable hs clock during pre-enable
From: Adam Thiede @ 2026-07-27 12:52 UTC (permalink / raw)
To: Gary Bisson, Thorsten Leemhuis
Cc: AngeloGioacchino Del Regno, Chun-Kuang Hu, Esben Haabendal,
Philipp Zabel, David Airlie, Simona Vetter, Matthias Brugger,
dri-devel, linux-mediatek, linux-kernel, linux-arm-kernel,
Linux kernel regressions list
In-Reply-To: <amdTnudq48tZUTG2@owl5>
On 7/27/26 07:48, Gary Bisson wrote:
> Hi Thorsten,
>
> On Mon, Jul 27, 2026 at 02:28:56PM +0200, Thorsten Leemhuis wrote:
>> [top-posting to facilitate]
>>
>> Gary, Angelo, what's the status here? It looks like this fell through
>> the cracks -- or was this issue fixed in between somehow? If yes: great!
>> If not: Would be good to finally resolve this, as we are long past "fix
>> within a week" rule of thumb from Linus:
>> https://www.kernel.org/doc/html/latest/process/handling-regressions.html#on-how-quickly-regressions-should-be-fixed
>
> Not much happened I'm afraid. The status as I see is:
> - this patch is necessary to have TI SN65DSI83 working
> - this patch also follows the DRM guidelines saying that HS clock must
> be enabled during pre_enable (see previous answer / [1])
> - this patch has been successfully tested against MIPI-DSI panels (by
> Angelo) and LVDS panels via TI bridge (by myself)
> - Adam reported an issue with another bridge (PS8640) where resume is
> broken
> - Esben offered a patch to the TI bridge that would fix the issue we
> were seeing in the first place.
>
> But for the last two points, I'm not sure this calls for a revert yet:
> - enabling HS clock in pre_enable still is what should be done [1]
> - maybe the issue Adam is facing is due to the bridge driver instead as
> it could not be reproduced with another setup
> - Esben patch would break the SN65DSI83 init sequence, suggesting that
> the culprit really is the MIPI bridge for not following the HS clock
> requirement in pre_enable instead [2]
>
> So if we agree on the fact that HS clock must be set during pre_enable
> then I don't see a reason to revert that commit.
>
> Regards,
> Gary
>
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/drm_bridge.c#n169
> [2] https://patchwork.kernel.org/project/dri-devel/patch/20260711-ti-sn65dsi83-fixes-v1-2-d85eb5342b98@geanix.com/
I'm also happy to try out any patches and report back, too! Just point
me to it and let me know which release/RC I should apply it to.
^ permalink raw reply
* Re: [PATCH v4 10/10] arm_mpam: detect and enable MPAM-Fb PCC support
From: Lorenzo Pieralisi @ 2026-07-27 12:48 UTC (permalink / raw)
To: Sudeep Holla
Cc: Andre Przywara, Hanjun Guo, Catalin Marinas, Will Deacon,
Rafael J . Wysocki, Len Brown, James Morse, Ben Horgan,
Reinette Chatre, Fenghua Yu, Jonathan Cameron, Srivathsa L Rao,
Ganapatrao Kulkarni, Trilok Soni, Srinivas Ramana, Niyas Sait,
Lee Trager, linux-acpi, linux-arm-kernel, linux-kernel
In-Reply-To: <20260724-finicky-knowing-foxhound-df1e56@sudeepholla>
On Fri, Jul 24, 2026 at 11:18:32AM +0100, Sudeep Holla wrote:
> On Thu, Jul 23, 2026 at 05:54:54PM +0200, Andre Przywara wrote:
> > The Arm MPAM-Fb specification [1] describes a protocol to access MSC
> > registers through a firmware interface. This requires a shared memory
> > region to hold the message, and a mailbox to trigger the access.
> > For ACPI this is wrapped as a PCC channel, described using existing
> > ACPI abstractions.
> >
> > Add code to parse those PCC table descriptions associated with an MSC,
> > and store the parsed information in the MSC struct.
> > There can be multiple PCC channels, and each channel can serve multiple
> > MSCs, so we need to keep track of the channel usage, using a list and
> > a refcount.
> > This will be used by the MPAM-Fb access wrapper code.
> >
> > [1] https://developer.arm.com/documentation/den0144/latest
> >
> > Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> > ---
> > drivers/acpi/arm64/mpam.c | 6 +-
> > drivers/resctrl/mpam_devices.c | 127 ++++++++++++++++++++++++++++++++-
> > 2 files changed, 129 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/acpi/arm64/mpam.c b/drivers/acpi/arm64/mpam.c
> > index 84963a20c3e7..ca9b8754ae5f 100644
> > --- a/drivers/acpi/arm64/mpam.c
> > +++ b/drivers/acpi/arm64/mpam.c
> > @@ -220,8 +220,8 @@ static struct platform_device * __init acpi_mpam_parse_msc(struct acpi_mpam_msc_
> > struct platform_device *pdev __free(platform_device_put) =
> > platform_device_alloc("mpam_msc", tbl_msc->identifier);
>
> Looks like tbl_msc->identifier is getting stashed as pdev->id...
>
>
> > int next_res = 0, next_prop = 0, err;
> > - /* pcc, nrdy, affinity and a sentinel */
> > - struct property_entry props[4] = { 0 };
> > + /* pcc, msc-id, nrdy, affinity and a sentinel */
> > + struct property_entry props[5] = { 0 };
> > /* mmio, 2xirq, no sentinel. */
> > struct resource res[3] = { 0 };
> > struct acpi_device *companion;
> > @@ -256,6 +256,8 @@ static struct platform_device * __init acpi_mpam_parse_msc(struct acpi_mpam_msc_
> > } else if (iface == MPAM_IFACE_PCC) {
> > props[next_prop++] = PROPERTY_ENTRY_U32("pcc-channel",
> > tbl_msc->base_address);
> > + props[next_prop++] = PROPERTY_ENTRY_U32("msc-id",
> > + tbl_msc->identifier);
>
> Why is this needed then as you can fetch it as pdev->id ?
I suppose it is to have properties parity between OF and ACPI without
having to change the driver property parsing path.
Lorenzo
^ permalink raw reply
* Re: [PATCH] drm/mediatek: mtk_dsi: enable hs clock during pre-enable
From: Gary Bisson @ 2026-07-27 12:48 UTC (permalink / raw)
To: Thorsten Leemhuis
Cc: AngeloGioacchino Del Regno, Chun-Kuang Hu, Esben Haabendal,
Philipp Zabel, David Airlie, Simona Vetter, Matthias Brugger,
dri-devel, linux-mediatek, linux-kernel, linux-arm-kernel,
Adam Thiede, Linux kernel regressions list
In-Reply-To: <b26a4890-12e9-4995-a71d-d0b7458b1570@leemhuis.info>
Hi Thorsten,
On Mon, Jul 27, 2026 at 02:28:56PM +0200, Thorsten Leemhuis wrote:
> [top-posting to facilitate]
>
> Gary, Angelo, what's the status here? It looks like this fell through
> the cracks -- or was this issue fixed in between somehow? If yes: great!
> If not: Would be good to finally resolve this, as we are long past "fix
> within a week" rule of thumb from Linus:
> https://www.kernel.org/doc/html/latest/process/handling-regressions.html#on-how-quickly-regressions-should-be-fixed
Not much happened I'm afraid. The status as I see is:
- this patch is necessary to have TI SN65DSI83 working
- this patch also follows the DRM guidelines saying that HS clock must
be enabled during pre_enable (see previous answer / [1])
- this patch has been successfully tested against MIPI-DSI panels (by
Angelo) and LVDS panels via TI bridge (by myself)
- Adam reported an issue with another bridge (PS8640) where resume is
broken
- Esben offered a patch to the TI bridge that would fix the issue we
were seeing in the first place.
But for the last two points, I'm not sure this calls for a revert yet:
- enabling HS clock in pre_enable still is what should be done [1]
- maybe the issue Adam is facing is due to the bridge driver instead as
it could not be reproduced with another setup
- Esben patch would break the SN65DSI83 init sequence, suggesting that
the culprit really is the MIPI bridge for not following the HS clock
requirement in pre_enable instead [2]
So if we agree on the fact that HS clock must be set during pre_enable
then I don't see a reason to revert that commit.
Regards,
Gary
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/gpu/drm/drm_bridge.c#n169
[2] https://patchwork.kernel.org/project/dri-devel/patch/20260711-ti-sn65dsi83-fixes-v1-2-d85eb5342b98@geanix.com/
^ permalink raw reply
* Re: [v2 1/2] soc: fsl: dpio: Use scope-based resource management in dpaa2_io_store_create()
From: Ioana Ciornei @ 2026-07-27 12:46 UTC (permalink / raw)
To: Markus Elfring
Cc: linux-arm-kernel, linuxppc-dev, Christophe Leroy, Roy Pledge,
LKML, kernel-janitors
In-Reply-To: <802ea627-4bae-4267-b1fa-7da2499f2ab6@web.de>
On Mon, Jul 27, 2026 at 02:24:55PM +0200, Markus Elfring wrote:
> >> Scope-based resource management became supported for some
> >> programming interfaces by contributions of Peter Zijlstra on 2023-05-26.
> >> See also the commit 54da6a0924311c7cf5015533991e44fb8eb12773 ("locking:
> >> Introduce __cleanup() based infrastructure").
> >>
> >> * Thus use the attribute “__free(kfree)”.
> >>
> >> * Reduce the scope for the local variable “ret”.
> >
> > Please don't. Let all the variables be defined at the start of each function.
>
> Do we stumble on another coding style preferences conflict here?
Yes, especially when moving the variable definition is unnecessary.
> https://elixir.bootlin.com/linux/v7.2-rc4/source/include/linux/cleanup.h#L142-L146
The context for the recommendation linked by you is (also from
cleanup.h):
* "When multiple variables in the same scope have cleanup attributes,
* at exit from the scope their associated cleanup functions are run in
* reverse order of definition (last defined, first cleanup)."
*
* When the unwind order matters it requires that variables be defined
* mid-function scope rather than at the top of the file. Take the
* following example and notice the bug highlighted by "!!"::
Which is not the case of these simple functions which only need a kfree.
>
>
> >> * Omit two kfree() calls accordingly.
> >>
> >> * Omit the local variable “size” (for another memory allocation).
> >
> > Please remove this change, not related to the intention of the patch.
> What does hinder to perform the required size determination as a direct parameter
> for a kzalloc() call?
Nothing, but it's a different change. On top of this, it's just churning
the code without an added benefit.
Ioana
^ permalink raw reply
* Re: [PATCH 1/3] drivers/perf: hisi: Consolidate uncore PMU cpuhp states
From: Robin Murphy @ 2026-07-27 12:41 UTC (permalink / raw)
To: Yushan Wang, will, mark.rutland, linux-arm-kernel, linux-kernel
Cc: u.kleine-koenig, linuxarm, liuyonglong, prime.zeng, wangzhou1,
wuyifan50
In-Reply-To: <20260724025238.3411328-2-wangyushan12@huawei.com>
On 24/07/2026 3:52 am, Yushan Wang wrote:
> Every HiSilicon uncore PMU driver allocates its own static cpuhp state
> even though they all register identical online/offline callbacks. This
> wastes slots in the cpuhp state enum and needlessly fragments the
> hotplug state space.
>
> Move the cpuhp state setup into the shared hisi_uncore_pmu framework:
> register a single dynamic state (CPUHP_AP_ONLINE_DYN) at framework
> module init and export it for all HiSilicon uncore PMU drivers to use.
> Drop the now-unused static CPUHP_AP_PERF_ARM_HISI_* entries from
> include/linux/cpuhotplug.h.
>
> The L3C PMU driver keeps a private dynamic state because it has its own
> hotplug callbacks for migrating multiple per-CPU interrupt affinities,
> but switches from its former static slot to CPUHP_AP_ONLINE_DYN for
> consistency.
>
> No intended functional changes.
>
> Signed-off-by: Yushan Wang <wangyushan12@huawei.com>
> ---
> drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c | 34 +++---------------
> drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 34 +++---------------
> drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 34 +++---------------
> drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c | 21 +++++------
> drivers/perf/hisilicon/hisi_uncore_mn_pmu.c | 35 ++----------------
> drivers/perf/hisilicon/hisi_uncore_noc_pmu.c | 35 ++----------------
> drivers/perf/hisilicon/hisi_uncore_pa_pmu.c | 34 +++---------------
> drivers/perf/hisilicon/hisi_uncore_pmu.c | 25 +++++++++++++
> drivers/perf/hisilicon/hisi_uncore_pmu.h | 2 ++
> drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 34 +++---------------
> drivers/perf/hisilicon/hisi_uncore_uc_pmu.c | 36 ++-----------------
> include/linux/cpuhotplug.h | 6 ----
> 12 files changed, 67 insertions(+), 263 deletions(-)
Neat! Seems like a pretty nice win already, plus it only makes a
conversion easier if my generic hotplug idea takes off :)
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
> diff --git a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
> index b879b81adfdd..83967725c51c 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_cpa_pmu.c
> @@ -295,7 +295,7 @@ static int hisi_cpa_pmu_probe(struct platform_device *pdev)
>
> /* Power Management should be disabled before using CPA PMU. */
> hisi_cpa_pmu_disable_pm(cpa_pmu);
> - ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE,
> + ret = cpuhp_state_add_instance(hisi_uncore_pmu_cpuhp_state,
> &cpa_pmu->node);
> if (ret) {
> dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
> @@ -307,7 +307,7 @@ static int hisi_cpa_pmu_probe(struct platform_device *pdev)
> if (ret) {
> dev_err(cpa_pmu->dev, "PMU register failed\n");
> cpuhp_state_remove_instance_nocalls(
> - CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE, &cpa_pmu->node);
> + hisi_uncore_pmu_cpuhp_state, &cpa_pmu->node);
> hisi_cpa_pmu_enable_pm(cpa_pmu);
> return ret;
> }
> @@ -321,7 +321,7 @@ static void hisi_cpa_pmu_remove(struct platform_device *pdev)
> struct hisi_pmu *cpa_pmu = platform_get_drvdata(pdev);
>
> perf_pmu_unregister(&cpa_pmu->pmu);
> - cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE,
> + cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state,
> &cpa_pmu->node);
> hisi_cpa_pmu_enable_pm(cpa_pmu);
> }
> @@ -336,33 +336,7 @@ static struct platform_driver hisi_cpa_pmu_driver = {
> .remove = hisi_cpa_pmu_remove,
> };
>
> -static int __init hisi_cpa_pmu_module_init(void)
> -{
> - int ret;
> -
> - ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE,
> - "AP_PERF_ARM_HISI_CPA_ONLINE",
> - hisi_uncore_pmu_online_cpu,
> - hisi_uncore_pmu_offline_cpu);
> - if (ret) {
> - pr_err("setup hotplug failed: %d\n", ret);
> - return ret;
> - }
> -
> - ret = platform_driver_register(&hisi_cpa_pmu_driver);
> - if (ret)
> - cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE);
> -
> - return ret;
> -}
> -module_init(hisi_cpa_pmu_module_init);
> -
> -static void __exit hisi_cpa_pmu_module_exit(void)
> -{
> - platform_driver_unregister(&hisi_cpa_pmu_driver);
> - cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE);
> -}
> -module_exit(hisi_cpa_pmu_module_exit);
> +module_platform_driver(hisi_cpa_pmu_driver);
>
> MODULE_IMPORT_NS("HISI_PMU");
> MODULE_DESCRIPTION("HiSilicon SoC CPA PMU driver");
> diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
> index 21c494881ca0..e905160523ee 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
> @@ -401,7 +401,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
> if (!name)
> return -ENOMEM;
>
> - ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE,
> + ret = cpuhp_state_add_instance(hisi_uncore_pmu_cpuhp_state,
> &ddrc_pmu->node);
> if (ret) {
> dev_err(&pdev->dev, "Error %d registering hotplug;\n", ret);
> @@ -414,7 +414,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
> if (ret) {
> dev_err(ddrc_pmu->dev, "DDRC PMU register failed!\n");
> cpuhp_state_remove_instance_nocalls(
> - CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE, &ddrc_pmu->node);
> + hisi_uncore_pmu_cpuhp_state, &ddrc_pmu->node);
> }
>
> return ret;
> @@ -425,7 +425,7 @@ static void hisi_ddrc_pmu_remove(struct platform_device *pdev)
> struct hisi_pmu *ddrc_pmu = platform_get_drvdata(pdev);
>
> perf_pmu_unregister(&ddrc_pmu->pmu);
> - cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE,
> + cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state,
> &ddrc_pmu->node);
> }
>
> @@ -501,33 +501,7 @@ static struct platform_driver hisi_ddrc_pmu_driver = {
> .remove = hisi_ddrc_pmu_remove,
> };
>
> -static int __init hisi_ddrc_pmu_module_init(void)
> -{
> - int ret;
> -
> - ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE,
> - "AP_PERF_ARM_HISI_DDRC_ONLINE",
> - hisi_uncore_pmu_online_cpu,
> - hisi_uncore_pmu_offline_cpu);
> - if (ret) {
> - pr_err("DDRC PMU: setup hotplug, ret = %d\n", ret);
> - return ret;
> - }
> -
> - ret = platform_driver_register(&hisi_ddrc_pmu_driver);
> - if (ret)
> - cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE);
> -
> - return ret;
> -}
> -module_init(hisi_ddrc_pmu_module_init);
> -
> -static void __exit hisi_ddrc_pmu_module_exit(void)
> -{
> - platform_driver_unregister(&hisi_ddrc_pmu_driver);
> - cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE);
> -}
> -module_exit(hisi_ddrc_pmu_module_exit);
> +module_platform_driver(hisi_ddrc_pmu_driver);
>
> MODULE_IMPORT_NS("HISI_PMU");
> MODULE_DESCRIPTION("HiSilicon SoC DDRC uncore PMU driver");
> diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
> index 97cfaa586a87..93a250b7abb8 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
> @@ -490,7 +490,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev)
> if (!name)
> return -ENOMEM;
>
> - ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE,
> + ret = cpuhp_state_add_instance(hisi_uncore_pmu_cpuhp_state,
> &hha_pmu->node);
> if (ret) {
> dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
> @@ -503,7 +503,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev)
> if (ret) {
> dev_err(hha_pmu->dev, "HHA PMU register failed!\n");
> cpuhp_state_remove_instance_nocalls(
> - CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE, &hha_pmu->node);
> + hisi_uncore_pmu_cpuhp_state, &hha_pmu->node);
> }
>
> return ret;
> @@ -514,7 +514,7 @@ static void hisi_hha_pmu_remove(struct platform_device *pdev)
> struct hisi_pmu *hha_pmu = platform_get_drvdata(pdev);
>
> perf_pmu_unregister(&hha_pmu->pmu);
> - cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE,
> + cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state,
> &hha_pmu->node);
> }
>
> @@ -528,33 +528,7 @@ static struct platform_driver hisi_hha_pmu_driver = {
> .remove = hisi_hha_pmu_remove,
> };
>
> -static int __init hisi_hha_pmu_module_init(void)
> -{
> - int ret;
> -
> - ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE,
> - "AP_PERF_ARM_HISI_HHA_ONLINE",
> - hisi_uncore_pmu_online_cpu,
> - hisi_uncore_pmu_offline_cpu);
> - if (ret) {
> - pr_err("HHA PMU: Error setup hotplug, ret = %d;\n", ret);
> - return ret;
> - }
> -
> - ret = platform_driver_register(&hisi_hha_pmu_driver);
> - if (ret)
> - cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE);
> -
> - return ret;
> -}
> -module_init(hisi_hha_pmu_module_init);
> -
> -static void __exit hisi_hha_pmu_module_exit(void)
> -{
> - platform_driver_unregister(&hisi_hha_pmu_driver);
> - cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE);
> -}
> -module_exit(hisi_hha_pmu_module_exit);
> +module_platform_driver(hisi_hha_pmu_driver);
>
> MODULE_IMPORT_NS("HISI_PMU");
> MODULE_DESCRIPTION("HiSilicon SoC HHA uncore PMU driver");
> diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
> index f963e4f9e552..0b78a0e094dd 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
> @@ -93,6 +93,8 @@ struct hisi_l3c_pmu_ext {
> bool support_ext;
> };
>
> +static enum cpuhp_state hisi_l3c_pmu_cpuhp_state;
> +
> static bool support_ext(struct hisi_l3c_pmu *pmu)
> {
> struct hisi_l3c_pmu_ext *l3c_pmu_ext = pmu->l3c_pmu.dev_info->private;
> @@ -845,8 +847,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
> if (!name)
> return -ENOMEM;
>
> - ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
> - &l3c_pmu->node);
> + ret = cpuhp_state_add_instance(hisi_l3c_pmu_cpuhp_state, &l3c_pmu->node);
> if (ret) {
> dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
> return ret;
> @@ -858,7 +859,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
> if (ret) {
> dev_err(l3c_pmu->dev, "L3C PMU register failed!\n");
> cpuhp_state_remove_instance_nocalls(
> - CPUHP_AP_PERF_ARM_HISI_L3_ONLINE, &l3c_pmu->node);
> + hisi_l3c_pmu_cpuhp_state, &l3c_pmu->node);
> }
>
> return ret;
> @@ -869,7 +870,7 @@ static void hisi_l3c_pmu_remove(struct platform_device *pdev)
> struct hisi_pmu *l3c_pmu = platform_get_drvdata(pdev);
>
> perf_pmu_unregister(&l3c_pmu->pmu);
> - cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
> + cpuhp_state_remove_instance_nocalls(hisi_l3c_pmu_cpuhp_state,
> &l3c_pmu->node);
> }
>
> @@ -939,20 +940,20 @@ static int hisi_l3c_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
>
> static int __init hisi_l3c_pmu_module_init(void)
> {
> - int ret;
> -
> - ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
> + int ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
> "AP_PERF_ARM_HISI_L3_ONLINE",
> hisi_l3c_pmu_online_cpu,
> hisi_l3c_pmu_offline_cpu);
> - if (ret) {
> + if (ret < 0) {
> pr_err("L3C PMU: Error setup hotplug, ret = %d\n", ret);
> return ret;
> }
>
> + hisi_l3c_pmu_cpuhp_state = ret;
> +
> ret = platform_driver_register(&hisi_l3c_pmu_driver);
> if (ret)
> - cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE);
> + cpuhp_remove_multi_state(hisi_l3c_pmu_cpuhp_state);
>
> return ret;
> }
> @@ -961,7 +962,7 @@ module_init(hisi_l3c_pmu_module_init);
> static void __exit hisi_l3c_pmu_module_exit(void)
> {
> platform_driver_unregister(&hisi_l3c_pmu_driver);
> - cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE);
> + cpuhp_remove_multi_state(hisi_l3c_pmu_cpuhp_state);
> }
> module_exit(hisi_l3c_pmu_module_exit);
>
> diff --git a/drivers/perf/hisilicon/hisi_uncore_mn_pmu.c b/drivers/perf/hisilicon/hisi_uncore_mn_pmu.c
> index 246cc0333099..ad898153ff49 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_mn_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_mn_pmu.c
> @@ -13,9 +13,6 @@
>
> #include "hisi_uncore_pmu.h"
>
> -/* Dynamic CPU hotplug state used by MN PMU */
> -static enum cpuhp_state hisi_mn_pmu_online;
> -
> /* MN register definition */
> #define HISI_MN_DYNAMIC_CTRL_REG 0x400
> #define HISI_MN_DYNAMIC_CTRL_EN BIT(0)
> @@ -291,7 +288,7 @@ static int hisi_mn_pmu_dev_init(struct platform_device *pdev,
>
> static void hisi_mn_pmu_remove_cpuhp(void *hotplug_node)
> {
> - cpuhp_state_remove_instance_nocalls(hisi_mn_pmu_online, hotplug_node);
> + cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state, hotplug_node);
> }
>
> static void hisi_mn_pmu_unregister(void *pmu)
> @@ -320,7 +317,7 @@ static int hisi_mn_pmu_probe(struct platform_device *pdev)
> if (!name)
> return -ENOMEM;
>
> - ret = cpuhp_state_add_instance(hisi_mn_pmu_online, &mn_pmu->node);
> + ret = cpuhp_state_add_instance(hisi_uncore_pmu_cpuhp_state, &mn_pmu->node);
> if (ret)
> return dev_err_probe(&pdev->dev, ret, "Failed to register cpu hotplug\n");
>
> @@ -376,33 +373,7 @@ static struct platform_driver hisi_mn_pmu_driver = {
> .probe = hisi_mn_pmu_probe,
> };
>
> -static int __init hisi_mn_pmu_module_init(void)
> -{
> - int ret;
> -
> - ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "perf/hisi/mn:online",
> - hisi_uncore_pmu_online_cpu,
> - hisi_uncore_pmu_offline_cpu);
> - if (ret < 0) {
> - pr_err("hisi_mn_pmu: Failed to setup MN PMU hotplug: %d\n", ret);
> - return ret;
> - }
> - hisi_mn_pmu_online = ret;
> -
> - ret = platform_driver_register(&hisi_mn_pmu_driver);
> - if (ret)
> - cpuhp_remove_multi_state(hisi_mn_pmu_online);
> -
> - return ret;
> -}
> -module_init(hisi_mn_pmu_module_init);
> -
> -static void __exit hisi_mn_pmu_module_exit(void)
> -{
> - platform_driver_unregister(&hisi_mn_pmu_driver);
> - cpuhp_remove_multi_state(hisi_mn_pmu_online);
> -}
> -module_exit(hisi_mn_pmu_module_exit);
> +module_platform_driver(hisi_mn_pmu_driver);
>
> MODULE_IMPORT_NS("HISI_PMU");
> MODULE_DESCRIPTION("HiSilicon SoC MN uncore PMU driver");
> diff --git a/drivers/perf/hisilicon/hisi_uncore_noc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_noc_pmu.c
> index 616f4af57db7..abf44fa46d17 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_noc_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_noc_pmu.c
> @@ -41,9 +41,6 @@
> HISI_PMU_EVENT_ATTR_EXTRACTOR(ch, config1, 2, 0);
> HISI_PMU_EVENT_ATTR_EXTRACTOR(tt_en, config1, 3, 3);
>
> -/* Dynamic CPU hotplug state used by this PMU driver */
> -static enum cpuhp_state hisi_noc_pmu_cpuhp_state;
> -
> struct hisi_noc_pmu_regs {
> u32 version;
> u32 pmu_ctrl;
> @@ -324,7 +321,7 @@ static int hisi_noc_pmu_dev_init(struct platform_device *pdev, struct hisi_pmu *
>
> static void hisi_noc_pmu_remove_cpuhp_instance(void *hotplug_node)
> {
> - cpuhp_state_remove_instance_nocalls(hisi_noc_pmu_cpuhp_state, hotplug_node);
> + cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state, hotplug_node);
> }
>
> static void hisi_noc_pmu_unregister_pmu(void *pmu)
> @@ -353,7 +350,7 @@ static int hisi_noc_pmu_probe(struct platform_device *pdev)
> if (ret)
> return ret;
>
> - ret = cpuhp_state_add_instance(hisi_noc_pmu_cpuhp_state, &noc_pmu->node);
> + ret = cpuhp_state_add_instance(hisi_uncore_pmu_cpuhp_state, &noc_pmu->node);
> if (ret)
> return dev_err_probe(dev, ret, "Fail to register cpuhp instance\n");
>
> @@ -408,33 +405,7 @@ static struct platform_driver hisi_noc_pmu_driver = {
> .probe = hisi_noc_pmu_probe,
> };
>
> -static int __init hisi_noc_pmu_module_init(void)
> -{
> - int ret;
> -
> - ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "perf/hisi/noc:online",
> - hisi_uncore_pmu_online_cpu,
> - hisi_uncore_pmu_offline_cpu);
> - if (ret < 0) {
> - pr_err("hisi_noc_pmu: Fail to setup cpuhp callbacks, ret = %d\n", ret);
> - return ret;
> - }
> - hisi_noc_pmu_cpuhp_state = ret;
> -
> - ret = platform_driver_register(&hisi_noc_pmu_driver);
> - if (ret)
> - cpuhp_remove_multi_state(hisi_noc_pmu_cpuhp_state);
> -
> - return ret;
> -}
> -module_init(hisi_noc_pmu_module_init);
> -
> -static void __exit hisi_noc_pmu_module_exit(void)
> -{
> - platform_driver_unregister(&hisi_noc_pmu_driver);
> - cpuhp_remove_multi_state(hisi_noc_pmu_cpuhp_state);
> -}
> -module_exit(hisi_noc_pmu_module_exit);
> +module_platform_driver(hisi_noc_pmu_driver);
>
> MODULE_IMPORT_NS("HISI_PMU");
> MODULE_DESCRIPTION("HiSilicon SoC Uncore NoC PMU driver");
> diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
> index 80108c63cb60..3d1e0af64260 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c
> @@ -468,7 +468,7 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev)
> if (!name)
> return -ENOMEM;
>
> - ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
> + ret = cpuhp_state_add_instance(hisi_uncore_pmu_cpuhp_state,
> &pa_pmu->node);
> if (ret) {
> dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
> @@ -479,7 +479,7 @@ static int hisi_pa_pmu_probe(struct platform_device *pdev)
> ret = perf_pmu_register(&pa_pmu->pmu, name, -1);
> if (ret) {
> dev_err(pa_pmu->dev, "PMU register failed, ret = %d\n", ret);
> - cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
> + cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state,
> &pa_pmu->node);
> return ret;
> }
> @@ -493,7 +493,7 @@ static void hisi_pa_pmu_remove(struct platform_device *pdev)
> struct hisi_pmu *pa_pmu = platform_get_drvdata(pdev);
>
> perf_pmu_unregister(&pa_pmu->pmu);
> - cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
> + cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state,
> &pa_pmu->node);
> }
>
> @@ -515,33 +515,7 @@ static struct platform_driver hisi_pa_pmu_driver = {
> .remove = hisi_pa_pmu_remove,
> };
>
> -static int __init hisi_pa_pmu_module_init(void)
> -{
> - int ret;
> -
> - ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
> - "AP_PERF_ARM_HISI_PA_ONLINE",
> - hisi_uncore_pmu_online_cpu,
> - hisi_uncore_pmu_offline_cpu);
> - if (ret) {
> - pr_err("PA PMU: cpuhp state setup failed, ret = %d\n", ret);
> - return ret;
> - }
> -
> - ret = platform_driver_register(&hisi_pa_pmu_driver);
> - if (ret)
> - cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE);
> -
> - return ret;
> -}
> -module_init(hisi_pa_pmu_module_init);
> -
> -static void __exit hisi_pa_pmu_module_exit(void)
> -{
> - platform_driver_unregister(&hisi_pa_pmu_driver);
> - cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_PA_ONLINE);
> -}
> -module_exit(hisi_pa_pmu_module_exit);
> +module_platform_driver(hisi_pa_pmu_driver);
>
> MODULE_IMPORT_NS("HISI_PMU");
> MODULE_DESCRIPTION("HiSilicon Protocol Adapter uncore PMU driver");
> diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c
> index de71dcf11653..276785a79ae9 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c
> @@ -23,6 +23,9 @@
>
> #define HISI_MAX_PERIOD(nr) (GENMASK_ULL((nr) - 1, 0))
>
> +enum cpuhp_state hisi_uncore_pmu_cpuhp_state;
> +EXPORT_SYMBOL_NS_GPL(hisi_uncore_pmu_cpuhp_state, "HISI_PMU");
> +
> /*
> * PMU event attributes
> */
> @@ -621,5 +624,27 @@ void hisi_pmu_init(struct hisi_pmu *hisi_pmu, struct module *module)
> }
> EXPORT_SYMBOL_NS_GPL(hisi_pmu_init, "HISI_PMU");
>
> +static int __init hisi_uncore_pmu_init(void)
> +{
> + int ret;
> +
> + ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "perf/hisi/uncore:online",
> + hisi_uncore_pmu_online_cpu,
> + hisi_uncore_pmu_offline_cpu);
> + if (ret < 0)
> + return ret;
> +
> + hisi_uncore_pmu_cpuhp_state = ret;
> +
> + return 0;
> +}
> +module_init(hisi_uncore_pmu_init);
> +
> +static void __exit hisi_uncore_pmu_exit(void)
> +{
> + cpuhp_remove_multi_state(hisi_uncore_pmu_cpuhp_state);
> +}
> +module_exit(hisi_uncore_pmu_exit);
> +
> MODULE_DESCRIPTION("HiSilicon SoC uncore Performance Monitor driver framework");
> MODULE_LICENSE("GPL v2");
> diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
> index 3ffe6acda653..e5a4b3898865 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
> +++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
> @@ -171,4 +171,6 @@ int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu,
> void hisi_uncore_pmu_init_topology(struct hisi_pmu *hisi_pmu, struct device *dev);
>
> void hisi_pmu_init(struct hisi_pmu *hisi_pmu, struct module *module);
> +
> +extern enum cpuhp_state hisi_uncore_pmu_cpuhp_state;
> #endif /* __HISI_UNCORE_PMU_H__ */
> diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
> index cd32d606df05..d01340ff2e5c 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c
> @@ -503,7 +503,7 @@ static int hisi_sllc_pmu_probe(struct platform_device *pdev)
> if (!name)
> return -ENOMEM;
>
> - ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
> + ret = cpuhp_state_add_instance(hisi_uncore_pmu_cpuhp_state,
> &sllc_pmu->node);
> if (ret) {
> dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
> @@ -515,7 +515,7 @@ static int hisi_sllc_pmu_probe(struct platform_device *pdev)
> ret = perf_pmu_register(&sllc_pmu->pmu, name, -1);
> if (ret) {
> dev_err(sllc_pmu->dev, "PMU register failed, ret = %d\n", ret);
> - cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
> + cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state,
> &sllc_pmu->node);
> return ret;
> }
> @@ -530,7 +530,7 @@ static void hisi_sllc_pmu_remove(struct platform_device *pdev)
> struct hisi_pmu *sllc_pmu = platform_get_drvdata(pdev);
>
> perf_pmu_unregister(&sllc_pmu->pmu);
> - cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
> + cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state,
> &sllc_pmu->node);
> }
>
> @@ -551,33 +551,7 @@ static struct platform_driver hisi_sllc_pmu_driver = {
> .remove = hisi_sllc_pmu_remove,
> };
>
> -static int __init hisi_sllc_pmu_module_init(void)
> -{
> - int ret;
> -
> - ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
> - "AP_PERF_ARM_HISI_SLLC_ONLINE",
> - hisi_uncore_pmu_online_cpu,
> - hisi_uncore_pmu_offline_cpu);
> - if (ret) {
> - pr_err("SLLC PMU: cpuhp state setup failed, ret = %d\n", ret);
> - return ret;
> - }
> -
> - ret = platform_driver_register(&hisi_sllc_pmu_driver);
> - if (ret)
> - cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE);
> -
> - return ret;
> -}
> -module_init(hisi_sllc_pmu_module_init);
> -
> -static void __exit hisi_sllc_pmu_module_exit(void)
> -{
> - platform_driver_unregister(&hisi_sllc_pmu_driver);
> - cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE);
> -}
> -module_exit(hisi_sllc_pmu_module_exit);
> +module_platform_driver(hisi_sllc_pmu_driver);
>
> MODULE_IMPORT_NS("HISI_PMU");
> MODULE_DESCRIPTION("HiSilicon SLLC uncore PMU driver");
> diff --git a/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c
> index e8186b6e1687..b4d017a5d688 100644
> --- a/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c
> +++ b/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c
> @@ -13,9 +13,6 @@
>
> #include "hisi_uncore_pmu.h"
>
> -/* Dynamic CPU hotplug state used by UC PMU */
> -static enum cpuhp_state hisi_uc_pmu_online;
> -
> /* UC register definition */
> #define HISI_UC_INT_MASK_REG 0x0800
> #define HISI_UC_INT_STS_REG 0x0808
> @@ -488,7 +485,7 @@ static int hisi_uc_pmu_dev_probe(struct platform_device *pdev,
>
> static void hisi_uc_pmu_remove_cpuhp_instance(void *hotplug_node)
> {
> - cpuhp_state_remove_instance_nocalls(hisi_uc_pmu_online, hotplug_node);
> + cpuhp_state_remove_instance_nocalls(hisi_uncore_pmu_cpuhp_state, hotplug_node);
> }
>
> static void hisi_uc_pmu_unregister_pmu(void *pmu)
> @@ -518,7 +515,7 @@ static int hisi_uc_pmu_probe(struct platform_device *pdev)
> if (!name)
> return -ENOMEM;
>
> - ret = cpuhp_state_add_instance(hisi_uc_pmu_online, &uc_pmu->node);
> + ret = cpuhp_state_add_instance(hisi_uncore_pmu_cpuhp_state, &uc_pmu->node);
> if (ret)
> return dev_err_probe(&pdev->dev, ret, "Error registering hotplug\n");
>
> @@ -559,34 +556,7 @@ static struct platform_driver hisi_uc_pmu_driver = {
> .probe = hisi_uc_pmu_probe,
> };
>
> -static int __init hisi_uc_pmu_module_init(void)
> -{
> - int ret;
> -
> - ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
> - "perf/hisi/uc:online",
> - hisi_uncore_pmu_online_cpu,
> - hisi_uncore_pmu_offline_cpu);
> - if (ret < 0) {
> - pr_err("UC PMU: Error setup hotplug, ret = %d\n", ret);
> - return ret;
> - }
> - hisi_uc_pmu_online = ret;
> -
> - ret = platform_driver_register(&hisi_uc_pmu_driver);
> - if (ret)
> - cpuhp_remove_multi_state(hisi_uc_pmu_online);
> -
> - return ret;
> -}
> -module_init(hisi_uc_pmu_module_init);
> -
> -static void __exit hisi_uc_pmu_module_exit(void)
> -{
> - platform_driver_unregister(&hisi_uc_pmu_driver);
> - cpuhp_remove_multi_state(hisi_uc_pmu_online);
> -}
> -module_exit(hisi_uc_pmu_module_exit);
> +module_platform_driver(hisi_uc_pmu_driver);
>
> MODULE_IMPORT_NS("HISI_PMU");
> MODULE_DESCRIPTION("HiSilicon SoC UC uncore PMU driver");
> diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
> index 0fb3a2a62eb0..965d6ce02a29 100644
> --- a/include/linux/cpuhotplug.h
> +++ b/include/linux/cpuhotplug.h
> @@ -210,12 +210,6 @@ enum cpuhp_state {
> CPUHP_AP_PERF_S390_SF_ONLINE,
> CPUHP_AP_PERF_ARM_CCI_ONLINE,
> CPUHP_AP_PERF_ARM_CCN_ONLINE,
> - CPUHP_AP_PERF_ARM_HISI_CPA_ONLINE,
> - CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE,
> - CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE,
> - CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
> - CPUHP_AP_PERF_ARM_HISI_PA_ONLINE,
> - CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
> CPUHP_AP_PERF_ARM_HISI_PCIE_PMU_ONLINE,
> CPUHP_AP_PERF_ARM_HNS3_PMU_ONLINE,
> CPUHP_AP_PERF_ARM_L2X0_ONLINE,
^ permalink raw reply
page: next (older)
- 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