Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v6 16/22] drm: bridge: dw_hdmi: Use display_info is_hdmi and has_audio
From: Jani Nikula @ 2026-05-18  9:02 UTC (permalink / raw)
  To: Jonas Karlman, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Heiko Stuebner, Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
	Luca Ceresoli, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter
  Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
	Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
	linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
	linux-kernel
In-Reply-To: <20260516183838.2024991-17-jonas@kwiboo.se>

On Sat, 16 May 2026, Jonas Karlman <jonas@kwiboo.se> wrote:
> -	/*
> -	 * FIXME: This should use connector->display_info.is_hdmi and
> -	 * connector->display_info.has_audio from a path that has read the EDID
> -	 * and called drm_edid_connector_update().
> -	 */
> -	edid = drm_edid_raw(drm_edid);
> -
> -	dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n",
> -		edid->width_cm, edid->height_cm);
> -
> -	hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
> -	hdmi->sink_has_audio = drm_detect_monitor_audio(edid);

Yay! \o/


>  
>  	return drm_edid;
>  }

-- 
Jani Nikula, Intel


^ permalink raw reply

* Re: [PATCH] iommu: Allow device driver to use its own PASID space for SVA
From: Joonwon Kang @ 2026-05-18  9:06 UTC (permalink / raw)
  To: jgg, kirill.shutemov
  Cc: Alexander.Grest, alexander.shishkin, amhetre, baolu.lu, bp,
	dave.hansen, easwar.hariharan, hpa, iommu, jacob.jun.pan,
	joonwonkang, joro, jpb, kas, kees, kevin.tian, linux-arm-kernel,
	linux-kernel, mingo, nicolinc, peterz, praan, robin.murphy,
	ryasuoka, smostafa, sohil.mehta, tglx, will, x86, xin
In-Reply-To: <20260515231808.GQ7702@ziepe.ca>

> On Fri, May 15, 2026 at 09:46:05AM +0000, Joonwon Kang wrote:
> > diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
> > index 0ca3912ecb7f..61e2e52105e5 100644
> > --- a/arch/x86/kernel/traps.c
> > +++ b/arch/x86/kernel/traps.c
> > @@ -864,6 +864,8 @@ static bool try_fixup_enqcmd_gp(void)
> >  		return false;
> >  
> >  	pasid = mm_get_enqcmd_pasid(current->mm);
> > +	if (pasid == IOMMU_PASID_INVALID)
> > +		return false;
> 
> If you do this then probably you should get rid of mm_valid_pasid(),
> mm_get_enqcmd_pasid() already has the NULL check so the two functions
> are kind of pointless.
> 
> You also missed the other place calling mm_valid_pasid() that should
> really be sensitive to this as well:
> 
> static int prctl_enable_tagged_addr(struct mm_struct *mm, unsigned long nr_bits)
> {
> [..]
>         if (mm_valid_pasid(mm) &&
>             !test_bit(MM_CONTEXT_FORCE_TAGGED_SVA, &mm->context.flags))
>                 return -EINVAL;
> 
> Make that removal a prep patch
> 

Thanks for pointing this out. I think mm_valid_pasid() is to check if SVA
is currently in action while mm_get_enqcmd_pasid() is to get the PASID for
"ENQCMD instruction execution". What prctl_enable_tagged_addr()
semantically requires here seems to be only checking if SVA is activated
or not regardless of whether EL0 can execute ENQCMD instruction; the
function wants to return error if SVA has been activated when LAM is to be
activated as they are mutually exclusive [1]. So, I think we should leave
it as-is. I am adding the author Kiryl as a reviewer for confirmation.

Since it is now possible with this patch to activate SVA without involving
EL0(for ENQCMD-like instructions), callers should be able to distinguish
between if SVA is activated and if EL0 can execute ENQCMD-like
instructions in addition to the SVA activation. mm_valid_pasid() is for
the former and mm_get_enqcmd_pasid() is for the latter. So, I think there
will be loss if we make the latter API serve for the former.

Or, I guess we could rename mm_valid_pasid() to be more specific like
mm_sva_activated() or mm_sva_in_use(). What do you think?

> I didn't try to check the rest closely but the approach looked sane to
> me

Thanks. Sashiko reported valid points [2] and I will handle them in the
meantime.

[1] https://lore.kernel.org/all/20230312112612.31869-12-kirill.shutemov@linux.intel.com/
[2] https://sashiko.dev/#/patchset/20260515094605.3195841-1-joonwonkang%40google.com

Thanks,
Joonwon Kang


^ permalink raw reply

* Re: [PATCH v1] virt: arm-cca-guest: use raw variant of smp_processor_id() in arm_cca_report_new()
From: Suzuki K Poulose @ 2026-05-18  9:10 UTC (permalink / raw)
  To: Kohei Enju, Catalin Marinas, Will Deacon
  Cc: Sami Mujawar, Gavin Shan, Steven Price, linux-arm-kernel,
	linux-kernel
In-Reply-To: <20260518033157.1865498-1-enju.kohei@fujitsu.com>

On 18/05/2026 04:31, Kohei Enju wrote:
> With CONFIG_DEBUG_PREEMPT=y, smp_processor_id() becomes an alias of
> debug_smp_processor_id(). This debug function complains when certain
> conditions that ensure CPU ID stability are not met, specifically when
> it's called from a preemptible context.
> 
> In arm_cca_report_new(), which runs in a preemptible context,
> smp_processor_id() triggers a splat [0] due to this.
> 
> However, the CPU ID obtained here is used as the target CPU for
> smp_call_function_single() to designate a specific CPU for subsequent
> operations, not to assert that the current thread will continue to
> execute on the same CPU. Therefore, snapshotting the CPU ID itself is
> correct, and thus there's no actual harm except for the splat.
> 
> Use raw_smp_processor_id() instead, to directly retrieve the current CPU
> ID without the debug checks, avoiding the unnecessary warning message
> while preserving the correct functional behavior.
> 
> [0]
>   BUG: using smp_processor_id() in preemptible [00000000] code: cca-workload-at/134
>   caller is debug_smp_processor_id+0x20/0x2c
>   CPU: 0 UID: 0 PID: 134 Comm: cca-workload-at Not tainted 7.0.0-rc1-gc74a64d12073 #1 PREEMPT
>   Hardware name: linux,dummy-virt (DT)
>   Call trace:
>    [...]
>    check_preemption_disabled+0xf8/0x100
>    debug_smp_processor_id+0x20/0x2c
>    arm_cca_report_new+0x54/0x230
>    tsm_report_read+0x184/0x260
>    tsm_report_outblob_read+0x18/0x38
>    configfs_bin_read_iter+0xf4/0x1dc
>    vfs_read+0x230/0x31c
>    [...]
> 
> Fixes: 7999edc484ca ("virt: arm-cca-guest: TSM_REPORT support for realms")
> Signed-off-by: Kohei Enju <enju.kohei@fujitsu.com>

Thank for the fix,

Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>


> ---
>   drivers/virt/coco/arm-cca-guest/arm-cca-guest.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> index 0c9ea24a200c..2d450caee3e4 100644
> --- a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> +++ b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> @@ -108,7 +108,7 @@ static int arm_cca_report_new(struct tsm_report *report, void *data)
>   	 * allocate outblob based on the returned value from the 'init'
>   	 * call and that cannot be done in an atomic context.
>   	 */
> -	cpu = smp_processor_id();
> +	cpu = raw_smp_processor_id();
>   
>   	info.challenge = desc->inblob;
>   	info.challenge_size = desc->inblob_len;



^ permalink raw reply

* Re: [PATCH 3/4 v2] phy: s32g: Add serdes xpcs subsystem
From: Enric Balletbo i Serra @ 2026-05-18  9:11 UTC (permalink / raw)
  To: Vincent Guittot
  Cc: Russell King (Oracle), vkoul, neil.armstrong, krzk+dt, conor+dt,
	ciprianmarian.costea, s32, p.zabel, ghennadi.procopciuc,
	Ionut.Vicovan, linux-phy, devicetree, linux-kernel,
	linux-arm-kernel, netdev, horms, Frank.li
In-Reply-To: <CAKfTPtAAmwjwSJ_5kfARaOns-g5tnXdeGM4s2JOy5vnhNTTXYQ@mail.gmail.com>

Hi all,

Just in case I missed something.

On Thu, Feb 5, 2026 at 6:03 PM Vincent Guittot
<vincent.guittot@linaro.org> wrote:
>

Is there a new version of this patchset? I tried applying this one on
top of the current mainline, building it as a module, and I received
different build errors:

ERROR: modpost: missing MODULE_LICENSE() in drivers/net/pcs/pcs-nxp-s32g-xpcs.o
WARNING: modpost: missing MODULE_DESCRIPTION() in
drivers/net/pcs/pcs-nxp-s32g-xpcs.o
ERROR: modpost: "s32g_xpcs_init"
[drivers/phy/freescale/phy-nxp-s32g-serdes.ko] undefined!
ERROR: modpost: "s32g_xpcs_init_plls"
[drivers/phy/freescale/phy-nxp-s32g-serdes.ko] undefined!
ERROR: modpost: "s32g_xpcs_pre_pcie_2g5"
[drivers/phy/freescale/phy-nxp-s32g-serdes.ko] undefined!
ERROR: modpost: "s32g_xpcs_vreset"
[drivers/phy/freescale/phy-nxp-s32g-serdes.ko] undefined!
ERROR: modpost: "s32g_xpcs_wait_vreset"
[drivers/phy/freescale/phy-nxp-s32g-serdes.ko] undefined!
ERROR: modpost: "s32g_xpcs_reset_rx"
[drivers/phy/freescale/phy-nxp-s32g-serdes.ko] undefined!
ERROR: modpost: "s32g_xpcs_disable_an"
[drivers/phy/freescale/phy-nxp-s32g-serdes.ko] undefined!

Thanks,
 Enric

> On Wed, 4 Feb 2026 at 16:29, Russell King (Oracle)
> <linux@armlinux.org.uk> wrote:
> >
> > Sorry, I don't have time to finish this review, nor cut down the context
> > as I normally would do... I'm being bothered on company Slack, which now
> > has the really bloody annoying feature of popping up a window rather than
> > using KDE's notification subsystem, and that steals keyboard focus away
> > from whatever one is trying to do at the time.
> >
> > On Tue, Feb 03, 2026 at 05:19:16PM +0100, Vincent Guittot wrote:
> > > +static bool s32g_xpcs_poll_timeout(struct s32g_xpcs *xpcs, xpcs_poll_func_t func,
> > > +                                ktime_t timeout)
> > > +{
> > > +     ktime_t cur = ktime_get();
> > > +
> > > +     return func(xpcs) || ktime_after(cur, timeout);
> > > +}
> > > +
> > > +static int s32g_xpcs_wait(struct s32g_xpcs *xpcs, xpcs_poll_func_t func)
> > > +{
> > > +     ktime_t timeout = ktime_add_ms(ktime_get(), XPCS_TIMEOUT_MS);
> > > +
> > > +     spin_until_cond(s32g_xpcs_poll_timeout(xpcs, func, timeout));
> > > +     if (!func(xpcs))
> > > +             return -ETIMEDOUT;
> >
> > XPCS_TIMEOUT_MS is 300ms. spin_until_cond() spins until the condition is
> > true. Do you need to tie up this CPU for up to 300ms? That seems
> > excessive. What is the reason that read_poll_timeout() or similar
> > couldn't be used?
>
> This needs additional tests because some instabilities have been
> reported when using read_poll_timeout in some places
>
> >
> > The advantage of read_poll_timeout() is that it will correctly handle
> > the timeout vs condition being satisfied witout need for special code.
> >
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static int s32g_xpcs_wait_bits(struct s32g_xpcs *xpcs, unsigned int reg,
> > > +                            unsigned int mask, unsigned int bits)
> > > +{
> > > +     ktime_t cur;
> > > +     ktime_t timeout = ktime_add_ms(ktime_get(), XPCS_TIMEOUT_MS);
> > > +
> > > +     spin_until_cond((cur = ktime_get(),
> > > +                      (s32g_xpcs_read(xpcs, reg) & mask) == bits ||
> > > +                      ktime_after(cur, timeout)));
> > > +     if ((s32g_xpcs_read(xpcs, reg) & mask) != bits)
> > > +             return -ETIMEDOUT;
> >
> > Same here:
> >
> >         return read_poll_timeout(s32g_xpcs_read, val, (val & mask) == bits,
> >                                  0, XPCS_TIMEOUT_MS, false,
> >                                  xpcs, reg);
> >
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static unsigned int s32g_xpcs_digital_status(struct s32g_xpcs *xpcs)
> > > +{
> > > +     return s32g_xpcs_read(xpcs, VR_MII_DIG_STS);
> > > +}
> > > +
> > > +static int s32g_xpcs_wait_power_good_state(struct s32g_xpcs *xpcs)
> > > +{
> > > +     unsigned int val;
> > > +
> > > +     return read_poll_timeout(s32g_xpcs_digital_status, val,
> > > +                              FIELD_GET(PSEQ_STATE_MASK, val) == POWER_GOOD_STATE,
> > > +                              0,
> > > +                              XPCS_TIMEOUT_MS, false, xpcs);
> >
> > This could be:
> >         return read_poll_timeout(s32g_xpcs_read, val,
> >                                  FIELD_GET(PSEQ_STATE_MASK, val) == POWER_GOOD_STATE,
> >                                  0, XPCS_TIMEOUT_MS, false,
> >                                  xpcs, VR_MII_DIG_STS);
> >
> > eliminating the need for s32g_xpcs_digital_status().
>
> fair enough
>
> >
> > > +}
> > > +
> > > +void s32g_xpcs_vreset(struct s32g_xpcs *xpcs)
> > > +{
> > > +     /* Step 19 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_DIG_CTRL1, VR_RST, VR_RST);
> > > +}
> > > +
> > > +static bool s32g_xpcs_is_not_in_reset(struct s32g_xpcs *xpcs)
> > > +{
> > > +     unsigned int val;
> > > +
> > > +     val = s32g_xpcs_read(xpcs, VR_MII_DIG_CTRL1);
> > > +
> > > +     return !(val & VR_RST);
> > > +}
> > > +
> > > +int s32g_xpcs_wait_vreset(struct s32g_xpcs *xpcs)
> > > +{
> > > +     int ret;
> > > +
> > > +     /* Step 20 */
> > > +     ret = s32g_xpcs_wait(xpcs, s32g_xpcs_is_not_in_reset);
> > > +     if (ret)
> > > +             dev_err(xpcs->dev, "XPCS%d is in reset\n", xpcs->id);
> > > +
> > > +     return ret;
> > > +}
> > > +
> > > +int s32g_xpcs_reset_rx(struct s32g_xpcs *xpcs)
> > > +{
> > > +     int ret = 0;
> > > +
> > > +     ret = s32g_xpcs_wait_power_good_state(xpcs);
> > > +     if (ret) {
> > > +             dev_err(xpcs->dev, "Failed to enter in PGOOD state after vendor reset\n");
> > > +             return ret;
> > > +     }
> > > +
> > > +     /* Step 21 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_RX_GENCTRL1,
> > > +                          RX_RST_0, RX_RST_0);
> > > +
> > > +     /* Step 22 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_RX_GENCTRL1,
> > > +                          RX_RST_0, 0);
> > > +
> > > +     /* Step 23 */
> > > +     /* Wait until SR_MII_STS[LINK_STS] = 1 */
> > > +
> > > +     return ret;
> > > +}
> > > +
> > > +static int s32g_xpcs_ref_clk_sel(struct s32g_xpcs *xpcs,
> > > +                              enum s32g_xpcs_pll ref_pll)
> > > +{
> > > +     switch (ref_pll) {
> > > +     case XPCS_PLLA:
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_MPLL_CMN_CTRL,
> > > +                                  MPLLB_SEL_0, 0);
> > > +             xpcs->ref = XPCS_PLLA;
> > > +             break;
> > > +     case XPCS_PLLB:
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_MPLL_CMN_CTRL,
> > > +                                  MPLLB_SEL_0, MPLLB_SEL_0);
> > > +             xpcs->ref = XPCS_PLLB;
> > > +             break;
> > > +     default:
> > > +             return -EINVAL;
> > > +     }
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static void s32g_xpcs_electrical_configure(struct s32g_xpcs *xpcs)
> > > +{
> > > +     /* Step 2 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_TX_EQ_CTRL0,
> > > +                          TX_EQ_MAIN_MASK, FIELD_PREP(TX_EQ_MAIN_MASK, 0xC));
> >
> > Prefer hex numbers to be lower case.
>
> ok
>
> >
> > > +
> > > +     /* Step 3 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_CONSUMER_10G_TX_TERM_CTRL,
> > > +                          TX0_TERM_MASK, FIELD_PREP(TX0_TERM_MASK, 0x4));
> > > +}
> > > +
> > > +static int s32g_xpcs_vco_cfg(struct s32g_xpcs *xpcs, enum s32g_xpcs_pll vco_pll)
> > > +{
> > > +     unsigned int vco_ld = 0;
> > > +     unsigned int vco_ref = 0;
> > > +     unsigned int rx_baud = 0;
> > > +     unsigned int tx_baud = 0;
> > > +
> > > +     switch (vco_pll) {
> > > +     case XPCS_PLLA:
> > > +             if (xpcs->mhz125) {
> > > +                     vco_ld = FIELD_PREP(VCO_LD_VAL_0_MASK, 1360);
> > > +                     vco_ref = FIELD_PREP(VCO_REF_LD_0_MASK, 17);
> > > +             } else {
> > > +                     vco_ld = FIELD_PREP(VCO_LD_VAL_0_MASK, 1350);
> > > +                     vco_ref = FIELD_PREP(VCO_REF_LD_0_MASK, 27);
> > > +             }
> > > +
> > > +             rx_baud = FIELD_PREP(RX0_RATE_MASK, RX0_BAUD_DIV_8);
> > > +             tx_baud = FIELD_PREP(TX0_RATE_MASK, TX0_BAUD_DIV_4);
> > > +             break;
> > > +     case XPCS_PLLB:
> > > +             if (xpcs->mhz125) {
> > > +                     vco_ld = FIELD_PREP(VCO_LD_VAL_0_MASK, 1350);
> > > +                     vco_ref = FIELD_PREP(VCO_REF_LD_0_MASK, 27);
> > > +             } else {
> > > +                     vco_ld = FIELD_PREP(VCO_LD_VAL_0_MASK, 1344);
> > > +                     vco_ref = FIELD_PREP(VCO_REF_LD_0_MASK, 43);
> > > +             }
> > > +
> > > +             rx_baud = FIELD_PREP(RX0_RATE_MASK, RX0_BAUD_DIV_2);
> > > +             tx_baud = FIELD_PREP(TX0_RATE_MASK, TX0_BAUD_DIV_1);
> > > +             break;
> > > +     default:
> > > +             return -EINVAL;
> > > +     }
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_VCO_CAL_LD0,
> > > +                          VCO_LD_VAL_0_MASK, vco_ld);
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_VCO_CAL_REF0,
> > > +                          VCO_REF_LD_0_MASK, vco_ref);
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_TX_RATE_CTRL,
> > > +                          TX0_RATE_MASK, tx_baud);
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_RX_RATE_CTRL,
> > > +                          RX0_RATE_MASK, rx_baud);
> > > +
> > > +     if (vco_pll == XPCS_PLLB) {
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_CDR_CTRL,
> > > +                                  VCO_LOW_FREQ_0, VCO_LOW_FREQ_0);
> > > +     } else {
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_CDR_CTRL,
> > > +                                  VCO_LOW_FREQ_0, 0);
> > > +     }
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static int s32g_xpcs_init_mplla(struct s32g_xpcs *xpcs)
> > > +{
> > > +     unsigned int val;
> > > +
> > > +     if (!xpcs)
> > > +             return -EINVAL;
> > > +
> > > +     /* Step 7 */
> > > +     val = 0;
> > > +     if (xpcs->ext_clk)
> > > +             val |= REF_USE_PAD;
> > > +
> > > +     if (xpcs->mhz125) {
> > > +             val |= REF_MPLLA_DIV2;
> > > +             val |= REF_CLK_DIV2;
> > > +             val |= FIELD_PREP(REF_RANGE_MASK, RANGE_52_78_MHZ);
> > > +     } else {
> > > +             val |= FIELD_PREP(REF_RANGE_MASK, RANGE_26_53_MHZ);
> > > +     }
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_REF_CLK_CTRL,
> > > +                          REF_MPLLA_DIV2 | REF_USE_PAD | REF_RANGE_MASK |
> > > +                          REF_CLK_DIV2, val);
> > > +
> > > +     /* Step 8 */
> > > +     if (xpcs->mhz125)
> > > +             val = FIELD_PREP(MLLA_MULTIPLIER_MASK, 80);
> > > +     else
> > > +             val = FIELD_PREP(MLLA_MULTIPLIER_MASK, 25);
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_MPLLA_CTRL0,
> > > +                          MPLLA_CAL_DISABLE | MLLA_MULTIPLIER_MASK,
> > > +                          val);
> > > +
> > > +     /* Step 9 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_MPLLA_CTRL1,
> > > +                          MPLLA_FRACN_CTRL_MASK, 0);
> > > +
> > > +     /* Step 10 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_MPLLA_CTRL2,
> > > +                          MPLLA_TX_CLK_DIV_MASK | MPLLA_DIV10_CLK_EN,
> > > +                          FIELD_PREP(MPLLA_TX_CLK_DIV_MASK, 1) | MPLLA_DIV10_CLK_EN);
> > > +
> > > +     /* Step 11 */
> > > +     if (xpcs->mhz125)
> > > +             val = FIELD_PREP(MPLLA_BANDWIDTH_MASK, 43);
> > > +     else
> > > +             val = FIELD_PREP(MPLLA_BANDWIDTH_MASK, 357);
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_MPLLA_CTRL3,
> > > +                          MPLLA_BANDWIDTH_MASK, val);
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static int s32g_xpcs_init_mpllb(struct s32g_xpcs *xpcs)
> > > +{
> > > +     unsigned int val;
> > > +
> > > +     if (!xpcs)
> > > +             return -EINVAL;
> > > +
> > > +     /* Step 7 */
> > > +     val = 0;
> > > +     if (xpcs->ext_clk)
> > > +             val |= REF_USE_PAD;
> > > +
> > > +     if (xpcs->mhz125) {
> > > +             val |= REF_MPLLB_DIV2;
> > > +             val |= REF_CLK_DIV2;
> > > +             val |= FIELD_PREP(REF_RANGE_MASK, RANGE_52_78_MHZ);
> > > +     } else {
> > > +             val |= FIELD_PREP(REF_RANGE_MASK, RANGE_26_53_MHZ);
> > > +     }
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_REF_CLK_CTRL,
> > > +                          REF_MPLLB_DIV2 | REF_USE_PAD | REF_RANGE_MASK |
> > > +                          REF_CLK_DIV2, val);
> > > +
> > > +     /* Step 8 */
> > > +     if (xpcs->mhz125)
> > > +             val = 125 << MLLB_MULTIPLIER_OFF;
> > > +     else
> > > +             val = 39 << MLLB_MULTIPLIER_OFF;
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_MPLLB_CTRL0,
> > > +                          MPLLB_CAL_DISABLE | MLLB_MULTIPLIER_MASK,
> > > +                          val);
> > > +
> > > +     /* Step 9 */
> > > +     if (xpcs->mhz125)
> > > +             val = FIELD_PREP(MPLLB_FRACN_CTRL_MASK, 0);
> > > +     else
> > > +             val = FIELD_PREP(MPLLB_FRACN_CTRL_MASK, 1044);
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_MPLLB_CTRL1,
> > > +                          MPLLB_FRACN_CTRL_MASK, val);
> > > +
> > > +     /* Step 10 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_MPLLB_CTRL2,
> > > +                          MPLLB_TX_CLK_DIV_MASK | MPLLB_DIV10_CLK_EN,
> > > +                          FIELD_PREP(MPLLB_TX_CLK_DIV_MASK, 5) | MPLLB_DIV10_CLK_EN);
> > > +
> > > +     /* Step 11 */
> > > +     if (xpcs->mhz125)
> > > +             val = FIELD_PREP(MPLLB_BANDWIDTH_MASK, 68);
> > > +     else
> > > +             val = FIELD_PREP(MPLLB_BANDWIDTH_MASK, 102);
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_MPLLB_CTRL3,
> > > +                          MPLLB_BANDWIDTH_MASK, val);
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static void s32g_serdes_pma_high_freq_recovery(struct s32g_xpcs *xpcs)
> > > +{
> > > +     /* PCS signal protection, PLL railout recovery */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_DBG_CTRL, SUPPRESS_LOS_DET | RX_DT_EN_CTL,
> > > +                          SUPPRESS_LOS_DET | RX_DT_EN_CTL);
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_MISC_CTRL0,
> > > +                          PLL_CTRL, PLL_CTRL);
> > > +}
> > > +
> > > +static void s32g_serdes_pma_configure_tx_eq_post(struct s32g_xpcs *xpcs)
> > > +{
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_TX_EQ_CTRL1,
> > > +                          TX_EQ_OVR_RIDE, TX_EQ_OVR_RIDE);
> > > +}
> > > +
> > > +static int s32g_serdes_bifurcation_pll_transit(struct s32g_xpcs *xpcs,
> > > +                                            enum s32g_xpcs_pll target_pll)
> > > +{
> > > +     int ret = 0;
> > > +     struct device *dev = xpcs->dev;
> > > +
> > > +     /* Configure XPCS speed and VCO */
> > > +     if (target_pll == XPCS_PLLA) {
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_DIG_CTRL1, EN_2_5G_MODE, 0);
> > > +             s32g_xpcs_vco_cfg(xpcs, XPCS_PLLA);
> > > +     } else {
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_DIG_CTRL1,
> > > +                                  EN_2_5G_MODE, EN_2_5G_MODE);
> > > +             s32g_xpcs_vco_cfg(xpcs, XPCS_PLLB);
> > > +     }
> >
> > I am really not happy with this driver being
> > PHY_INTERFACE_MODE_SGMII-only but supporting running that at 2.5Gbps.
> > In the kernel, PHY_INTERFACE_MODE_SGMII is strictly _Cisco_ SGMII only,
> > which means the version of it clocked at 1.25GHz, not 3.125GHz.
> >
> > OCSGMII or whatever random name you call it tends to be only supported
> > without inband AN, and we have pushed everyone to adopt
> > PHY_INTERFACE_MODE_2500BASEX for that. Please do the same.
> >
> > Should this SerDes be connected to a SFP cage, it will need to support
> > dynamically switching between Cisco SGMII and 2500BASE-X.
>
> okay, this needs to be checked with SoC Team
>
> >
> > > +
> > > +     /* Signal that clock are not available */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_TX_GENCTRL1,
> > > +                          TX_CLK_RDY_0, 0);
> > > +
> > > +     /* Select PLL reference */
> > > +     if (target_pll == XPCS_PLLA)
> > > +             s32g_xpcs_ref_clk_sel(xpcs, XPCS_PLLA);
> > > +     else
> > > +             s32g_xpcs_ref_clk_sel(xpcs, XPCS_PLLB);
> > > +
> > > +     /* Initiate transmitter TX reconfiguration request */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_TX_GENCTRL2,
> > > +                          TX_REQ_0, TX_REQ_0);
> > > +
> > > +     /* Wait for transmitter to reconfigure */
> > > +     ret = s32g_xpcs_wait_bits(xpcs, VR_MII_GEN5_12G_16G_TX_GENCTRL2,
> > > +                               TX_REQ_0, 0);
> > > +     if (ret) {
> > > +             dev_err(dev, "Switch to TX_REQ_0 failed\n");
> > > +             return ret;
> > > +     }
> > > +
> > > +     /* Initiate transmitter RX reconfiguration request */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_RX_GENCTRL2,
> > > +                          RX_REQ_0, RX_REQ_0);
> > > +
> > > +     /* Wait for receiver to reconfigure */
> > > +     ret = s32g_xpcs_wait_bits(xpcs, VR_MII_GEN5_12G_16G_RX_GENCTRL2,
> > > +                               RX_REQ_0, 0);
> > > +     if (ret) {
> > > +             dev_err(dev, "Switch to RX_REQ_0 failed\n");
> > > +             return ret;
> > > +     }
> > > +
> > > +     /* Signal that clock are available */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_TX_GENCTRL1,
> > > +                          TX_CLK_RDY_0, TX_CLK_RDY_0);
> > > +
> > > +     /* Flush internal logic */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_DIG_CTRL1, INIT, INIT);
> > > +
> > > +     /* Wait for init */
> > > +     ret = s32g_xpcs_wait_bits(xpcs, VR_MII_DIG_CTRL1, INIT, 0);
> > > +     if (ret) {
> > > +             dev_err(dev, "XPCS INIT failed\n");
> > > +             return ret;
> > > +     }
> > > +
> > > +     return ret;
> > > +}
> > > +
> > > +/*
> > > + * phylink_pcs_ops
> > > + */
> > > +
> > > +static unsigned int s32cc_phylink_pcs_inband_caps(struct phylink_pcs *pcs,
> > > +                                               phy_interface_t interface)
> > > +{
> > > +     switch (interface) {
> > > +     case PHY_INTERFACE_MODE_SGMII:
> > > +             return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
> > > +
> > > +     default:
> > > +             return 0;
> > > +     }
> > > +}
> > > +
> > > +static int s32cc_phylink_pcs_config(struct phylink_pcs *pcs,
> > > +                                 unsigned int neg_mode,
> > > +                                 phy_interface_t interface,
> > > +                                 const unsigned long *advertising,
> > > +                                 bool permit_pause_to_mac)
> > > +{
> > > +     struct s32g_xpcs *xpcs = phylink_pcs_to_s32g_xpcs(pcs);
> > > +
> > > +     /* Step 1: Disable SGMII AN */
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL, AN_ENABLE, 0);
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_AN_CTRL,
> > > +                          MII_AN_INTR_EN,
> > > +                          0);
> > > +
> > > +     if (!(neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED))
> > > +             return 0;
> > > +
> > > +     /* Step 2  */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_AN_CTRL,
> > > +                          PCS_MODE_MASK,
> > > +                          FIELD_PREP(PCS_MODE_MASK, PCS_MODE_SGMII));
> > > +
> > > +     /* Step 3 */
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL,
> > > +                          SS13 | SS6,
> > > +                          SS6);
> > > +
> > > +     /* Step 4  */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_AN_CTRL,
> > > +                          MII_CTRL,
> > > +                          0);
> > > +     /* Step 5 and 8 */
> > > +     if (xpcs->pcie_shared == PCIE_XPCS_2G5) {
> > > +             s32g_xpcs_write(xpcs, VR_MII_LINK_TIMER_CTRL, 0x2faf);
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_DIG_CTRL1,
> > > +                                  MAC_AUTO_SW, MAC_AUTO_SW);
> > > +     } else {
> > > +             s32g_xpcs_write(xpcs, VR_MII_LINK_TIMER_CTRL, 0x7a1);
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_DIG_CTRL1, MAC_AUTO_SW, 0);
> > > +     }
> > > +
> > > +     /* Step 6 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_DIG_CTRL1,
> > > +                          CL37_TMR_OVRRIDE, CL37_TMR_OVRRIDE);
> > > +
> > > +     /* Step 7 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_AN_CTRL,
> > > +                          MII_AN_INTR_EN,
> > > +                          MII_AN_INTR_EN);
> > > +
> > > +     /* Step 9: Enable SGMII AN */
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL, AN_ENABLE, AN_ENABLE);
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static void s32cc_phylink_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode,
> > > +                                     struct phylink_link_state *state)
> > > +{
> > > +     struct s32g_xpcs *xpcs = phylink_pcs_to_s32g_xpcs(pcs);
> > > +     bool ss6, ss13, an_enabled;
> > > +     struct device *dev = xpcs->dev;
> > > +     unsigned int val, ss;
> > > +
> > > +     an_enabled = (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED);
> > > +
> > > +     if (an_enabled) {
> > > +             state->link = 0;
> > > +             val = s32g_xpcs_read(xpcs, VR_MII_AN_INTR_STS);
> > > +
> > > +             /* Interrupt is raised with each SGMII AN that is in cases
> > > +              * Link down - Every SGMII link timer expire
> > > +              * Link up - Once before link goes up
> > > +              * So either linkup or raised interrupt mean AN was completed
> > > +              */
> > > +             if ((val & CL37_ANCMPLT_INTR) || (val & CL37_ANSGM_STS_LINK)) {
> > > +                     state->an_complete = 1;
> > > +                     if (val & CL37_ANSGM_STS_LINK)
> > > +                             state->link = 1;
> > > +                     else
> > > +                             return;
> > > +                     if (val & CL37_ANSGM_STS_DUPLEX)
> > > +                             state->duplex = DUPLEX_FULL;
> > > +                     else
> > > +                             state->duplex = DUPLEX_HALF;
> > > +                     ss = FIELD_GET(CL37_ANSGM_STS_SPEED_MASK, val);
> > > +             } else {
> > > +                     return;
> > > +             }
> > > +
> > > +     } else {
> > > +             val = s32g_xpcs_read(xpcs, SR_MII_STS);
> > > +             state->link = !!(val & LINK_STS);
> > > +             state->an_complete = 0;
> > > +             state->pause = MLO_PAUSE_NONE;
> > > +
> > > +             val = s32g_xpcs_read(xpcs, SR_MII_CTRL);
> > > +             if (val & DUPLEX_MODE)
> > > +                     state->duplex = DUPLEX_FULL;
> > > +             else
> > > +                     state->duplex = DUPLEX_HALF;
> > > +
> > > +             /*
> > > +              * Build similar value as CL37_ANSGM_STS_SPEED with
> > > +              * SS6 and SS13 of SR_MII_CTRL:
> > > +              *   - 0 for 10 Mbps
> > > +              *   - 1 for 100 Mbps
> > > +              *   - 2 for 1000 Mbps
> > > +              */
> > > +             ss6 = !!(val & SS6);
> > > +             ss13 = !!(val & SS13);
> > > +             ss = ss6 << 1 | ss13;
> > > +     }
> > > +
> > > +     switch (ss) {
> > > +     case CL37_ANSGM_10MBPS:
> > > +             state->speed = SPEED_10;
> > > +             break;
> > > +     case CL37_ANSGM_100MBPS:
> > > +             state->speed = SPEED_100;
> > > +             break;
> > > +     case CL37_ANSGM_1000MBPS:
> > > +             state->speed = SPEED_1000;
> > > +             break;
> > > +     default:
> > > +             dev_err(dev, "Failed to interpret the value of SR_MII_CTRL\n");
> > > +             break;
> > > +     }
> > > +
> > > +     val = s32g_xpcs_read(xpcs, VR_MII_DIG_CTRL1);
> > > +     if ((val & EN_2_5G_MODE) && state->speed == SPEED_1000)
> > > +             state->speed = SPEED_2500;
> > > +
> > > +     /* Cover SGMII AN inability to distigunish between 1G and 2.5G */
> > > +     if ((val & EN_2_5G_MODE) &&
> > > +         state->speed != SPEED_2500 && an_enabled) {
> > > +             dev_err(dev, "Speed not supported in SGMII AN mode\n");
> > > +     }
> > > +}
> > > +
> > > +static void s32cc_phylink_pcs_link_up(struct phylink_pcs *pcs,
> > > +                                   unsigned int neg_mode,
> > > +                                   phy_interface_t interface, int speed,
> > > +                                   int duplex)
> > > +{
> > > +     struct s32g_xpcs *xpcs = phylink_pcs_to_s32g_xpcs(pcs);
> > > +     struct device *dev = xpcs->dev;
> > > +     bool an_enabled = (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED);
> > > +     unsigned int val;
> > > +     int ret;
> > > +
> > > +     dev_dbg(dev, "xpcs_%d: speed=%u duplex=%d an=%d\n", xpcs->id,
> > > +             speed, duplex, an_enabled);
> > > +
> > > +     if (an_enabled)
> > > +             return;
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL, AN_ENABLE, 0);
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_AN_CTRL, MII_AN_INTR_EN, 0);
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_AN_CTRL, MII_CTRL, 0);
> >
> > Haven't you already disabled AN in .pcs_config() ? This method doesn't
> > change the AN enable state, the only time that happens is when
> > .pcs_config() will be called. All other cases of passing neg_mode are
> > merely informational.
>
> Fair enough, this is probably not needed anymore with the changes in .pcs_config
>
> >
> > > +
> > > +     if (duplex == DUPLEX_FULL)
> > > +             val = DUPLEX_MODE;
> > > +     else
> > > +             val = 0;
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL, DUPLEX_MODE, val);
> > > +
> > > +     switch (speed) {
> > > +     case SPEED_10:
> > > +             val = 0;
> > > +             break;
> > > +     case SPEED_100:
> > > +             val = SS13;
> > > +             break;
> > > +     case SPEED_1000:
> > > +             val = SS6;
> > > +             break;
> > > +     case SPEED_2500:
> > > +             val = SS6;
> > > +             break;
> > > +     default:
> > > +             dev_err(dev, "Speed not supported\n");
> > > +             break;
> > > +     }
> > > +
> > > +     if (speed == SPEED_2500) {
> > > +             ret = s32g_serdes_bifurcation_pll_transit(xpcs, XPCS_PLLB);
> > > +             if (ret)
> > > +                     dev_err(dev, "Switch to PLLB failed\n");
> > > +     } else {
> > > +             ret = s32g_serdes_bifurcation_pll_transit(xpcs, XPCS_PLLA);
> > > +             if (ret)
> > > +                     dev_err(dev, "Switch to PLLA failed\n");
> > > +     }
> >
> > This is a protocol transition, and isn't something that can be handled
> > here. Cisco SGMII (PHY_INTERFACE_MODE_SGMII) does not support 2500Mbps
> > and phylink will not allow it.
> >
> > See my comments for s32g_serdes_bifurcation_pll_transit().
> >
> > > +
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL, SS6 | SS13, val);
> > > +}
> > > +
> > > +static const struct phylink_pcs_ops s32cc_phylink_pcs_ops = {
> > > +     .pcs_inband_caps = s32cc_phylink_pcs_inband_caps,
> > > +     .pcs_get_state = s32cc_phylink_pcs_get_state,
> > > +     .pcs_config = s32cc_phylink_pcs_config,
> > > +     .pcs_link_up = s32cc_phylink_pcs_link_up,
> > > +};
> > > +
> > > +/*
> > > + * Serdes functions for initializing/configuring/releasing the xpcs
> > > + */
> > > +
> > > +int s32g_xpcs_pre_pcie_2g5(struct s32g_xpcs *xpcs)
> > > +{
> > > +     int ret;
> > > +
> > > +     /* Enable voltage boost */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_TX_GENCTRL1, VBOOST_EN_0,
> > > +                          VBOOST_EN_0);
> > > +
> > > +     /* TX rate baud  */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_TX_RATE_CTRL, 0x7, 0x0U);
> > > +
> > > +     /* Rx rate baud/2 */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_RX_RATE_CTRL, 0x3U, 0x1U);
> > > +
> > > +     /* Set low-frequency operating band */
> > > +     s32g_xpcs_write_bits(xpcs, VR_MII_GEN5_12G_16G_CDR_CTRL, CDR_SSC_EN_0,
> > > +                          VCO_LOW_FREQ_0);
> > > +
> > > +     ret = s32g_serdes_bifurcation_pll_transit(xpcs, XPCS_PLLB);
> > > +     if (ret)
> > > +             dev_err(xpcs->dev, "Switch to PLLB failed\n");
> > > +
> > > +     return ret;
> > > +}
> > > +
> > > +int s32g_xpcs_init_plls(struct s32g_xpcs *xpcs)
> > > +{
> > > +     int ret;
> > > +     struct device *dev = xpcs->dev;
> > > +
> > > +     if (!xpcs->ext_clk) {
> > > +             /* Step 1 */
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_DIG_CTRL1, BYP_PWRUP, BYP_PWRUP);
> > > +     } else if (xpcs->pcie_shared == NOT_SHARED) {
> > > +             ret = s32g_xpcs_wait_power_good_state(xpcs);
> > > +             if (ret)
> > > +                     return ret;
> > > +     } else if (xpcs->pcie_shared == PCIE_XPCS_2G5) {
> > > +             ret = s32g_xpcs_wait_power_good_state(xpcs);
> > > +             if (ret)
> > > +                     return ret;
> > > +             /* Configure equalization */
> > > +             s32g_serdes_pma_configure_tx_eq_post(xpcs);
> > > +             s32g_xpcs_electrical_configure(xpcs);
> > > +
> > > +             /* Enable receiver recover */
> > > +             s32g_serdes_pma_high_freq_recovery(xpcs);
> > > +             return 0;
> > > +     }
> > > +
> > > +     s32g_xpcs_electrical_configure(xpcs);
> > > +
> > > +     s32g_xpcs_ref_clk_sel(xpcs, XPCS_PLLA);
> > > +     ret = s32g_xpcs_init_mplla(xpcs);
> > > +     if (ret) {
> > > +             dev_err(dev, "Failed to initialize PLLA\n");
> > > +             return ret;
> > > +     }
> > > +     ret = s32g_xpcs_init_mpllb(xpcs);
> > > +     if (ret) {
> > > +             dev_err(dev, "Failed to initialize PLLB\n");
> > > +             return ret;
> > > +     }
> > > +     s32g_xpcs_vco_cfg(xpcs, XPCS_PLLA);
> > > +
> > > +     /* Step 18 */
> > > +     if (!xpcs->ext_clk)
> > > +             s32g_xpcs_write_bits(xpcs, VR_MII_DIG_CTRL1, BYP_PWRUP, 0);
> > > +
> > > +     /* Will be cleared by Step 19 Vreset */
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL, AN_ENABLE, 0);
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL, DUPLEX_MODE, DUPLEX_MODE);
> > > +
> > > +     return ret;
> > > +}
> > > +
> > > +void s32g_xpcs_disable_an(struct s32g_xpcs *xpcs)
> > > +{
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL, DUPLEX_MODE, DUPLEX_MODE);
> > > +     s32g_xpcs_write_bits(xpcs, SR_MII_CTRL, AN_ENABLE, 0);
> > > +}
> >
> > Sorry, but why? You should never override phylink's requests.
>
> Serdes sometimes needs to be reset and the AN is enabled by default
> after the reset and even before pcs_config has been called. This is
> called during the inti of serdes after an ip reset.
> That being said this might not be needed anymore after the change in
> pcs_config that disables AN
>
>
> >
> > > +
> > > +int s32g_xpcs_init(struct s32g_xpcs *xpcs, struct device *dev,
> > > +                unsigned char id, void __iomem *base, bool ext_clk,
> > > +                unsigned long rate, enum s32g_xpcs_shared pcie_shared)
> > > +{
> > > +     struct regmap_config conf;
> > > +
> > > +     if (rate != (125 * HZ_PER_MHZ) && rate != (100 * HZ_PER_MHZ)) {
> > > +             dev_err(dev, "XPCS cannot operate @%lu HZ\n", rate);
> > > +             return -EINVAL;
> > > +     }
> > > +
> > > +     xpcs->base = base;
> > > +     xpcs->ext_clk = ext_clk;
> > > +     xpcs->id = id;
> > > +     xpcs->dev = dev;
> > > +     xpcs->pcie_shared = pcie_shared;
> > > +
> > > +     if (rate == (125 * HZ_PER_MHZ))
> > > +             xpcs->mhz125 = true;
> > > +     else
> > > +             xpcs->mhz125 = false;
> > > +
> > > +     conf = s32g_xpcs_regmap_config;
> > > +
> > > +     if (!id)
> > > +             conf.name = "xpcs0";
> > > +     else
> > > +             conf.name = "xpcs1";
> > > +
> > > +     xpcs->regmap = devm_regmap_init(dev, NULL, xpcs, &conf);
> > > +     if (IS_ERR(xpcs->regmap))
> > > +             return dev_err_probe(dev, PTR_ERR(xpcs->regmap),
> > > +                                  "Failed to init register amp\n");
> > > +
> > > +     /* Phylink PCS */
> > > +     xpcs->pcs.ops = &s32cc_phylink_pcs_ops;
> > > +     xpcs->pcs.poll = true;
> > > +     __set_bit(PHY_INTERFACE_MODE_SGMII, xpcs->pcs.supported_interfaces);
> > > +
> > > +     return 0;
> > > +}
> > > diff --git a/drivers/phy/freescale/Kconfig b/drivers/phy/freescale/Kconfig
> > > index 45184a3cdd69..bb7f59897faf 100644
> > > --- a/drivers/phy/freescale/Kconfig
> > > +++ b/drivers/phy/freescale/Kconfig
> > > @@ -66,6 +66,7 @@ config PHY_S32G_SERDES
> > >       tristate "NXP S32G SERDES support"
> > >       depends on ARCH_S32 || COMPILE_TEST
> > >       select GENERIC_PHY
> > > +     select REGMAP
> > >       help
> > >         This option enables support for S23G SerDes PHY used for
> > >         PCIe & Ethernet
> > > diff --git a/drivers/phy/freescale/phy-nxp-s32g-serdes.c b/drivers/phy/freescale/phy-nxp-s32g-serdes.c
> > > index 321a80c02be5..f2f7eb5aa327 100644
> > > --- a/drivers/phy/freescale/phy-nxp-s32g-serdes.c
> > > +++ b/drivers/phy/freescale/phy-nxp-s32g-serdes.c
> > > @@ -12,12 +12,14 @@
> > >  #include <linux/module.h>
> > >  #include <linux/of_platform.h>
> > >  #include <linux/of_address.h>
> > > +#include <linux/pcs/pcs-nxp-s32g-xpcs.h>
> > >  #include <linux/phy/phy.h>
> > >  #include <linux/platform_device.h>
> > >  #include <linux/processor.h>
> > >  #include <linux/reset.h>
> > >  #include <linux/units.h>
> > >
> > > +#define S32G_SERDES_XPCS_MAX                 2
> > >  #define S32G_SERDES_MODE_MAX                 5
> > >
> > >  #define EXTERNAL_CLK_NAME                    "ext"
> > > @@ -32,6 +34,52 @@
> > >  #define S32G_PCIE_PHY_MPLLA_CTRL             0x10
> > >  #define  MPLL_STATE                          BIT(30)
> > >
> > > +#define S32G_PCIE_PHY_MPLLB_CTRL             0x14
> > > +#define  MPLLB_SSC_EN                                BIT(1)
> > > +
> > > +#define S32G_PCIE_PHY_EXT_CTRL_SEL           0x18
> > > +#define  EXT_PHY_CTRL_SEL                    BIT(0)
> > > +
> > > +#define S32G_PCIE_PHY_EXT_BS_CTRL            0x1C
> > > +#define  EXT_BS_TX_LOWSWING                  BIT(6)
> > > +#define  EXT_BS_RX_BIGSWING                  BIT(5)
> > > +#define  EXT_BS_RX_LEVEL_MASK                        GENMASK(4, 0)
> > > +
> > > +#define S32G_PCIE_PHY_REF_CLK_CTRL           0x20
> > > +#define  EXT_REF_RANGE_MASK                  GENMASK(5, 3)
> > > +#define  REF_CLK_DIV2_EN                     BIT(2)
> > > +#define  REF_CLK_MPLLB_DIV2_EN                       BIT(1)
> > > +
> > > +#define S32G_PCIE_PHY_EXT_MPLLA_CTRL_1               0x30
> > > +#define  EXT_MPLLA_BANDWIDTH_MASK            GENMASK(15, 0)
> > > +
> > > +#define S32G_PCIE_PHY_EXT_MPLLB_CTRL_1               0x40
> > > +#define  EXT_MPLLB_DIV_MULTIPLIER_MASK               GENMASK(31, 24)
> > > +#define  EXT_MPLLB_DIV_CLK_EN                        BIT(19)
> > > +#define  EXT_MPLLB_DIV8_CLK_EN                       BIT(18)
> > > +#define  EXT_MPLLB_DIV10_CLK_EN                      BIT(16)
> > > +#define  EXT_MPLLB_BANDWIDTH_MASK            GENMASK(15, 0)
> > > +
> > > +#define S32G_PCIE_PHY_EXT_MPLLB_CTRL_2               0x44
> > > +#define  EXT_MPLLB_FRACN_CTRL_MASK           GENMASK(22, 12)
> > > +#define  MPLLB_MULTIPLIER_MASK                       GENMASK(8, 0)
> > > +
> > > +#define S32G_PCIE_PHY_EXT_MPLLB_CTRL_3               0x48
> > > +#define  EXT_MPLLB_WORD_DIV2_EN                      BIT(31)
> > > +#define  EXT_MPLLB_TX_CLK_DIV_MASK           GENMASK(30, 28)
> > > +
> > > +#define S32G_PCIE_PHY_EXT_MISC_CTRL_1                0xA0
> > > +#define  EXT_RX_LOS_THRESHOLD_MASK           GENMASK(7, 1)
> > > +#define  EXT_RX_VREF_CTRL_MASK                       GENMASK(28, 24)
> > > +
> > > +#define S32G_PCIE_PHY_EXT_MISC_CTRL_2                0xA4
> > > +#define  EXT_TX_VBOOST_LVL_MASK                      GENMASK(18, 16)
> > > +#define  EXT_TX_TERM_CTRL_MASK                       GENMASK(26, 24)
> > > +
> > > +#define S32G_PCIE_PHY_XPCS1_RX_OVRD_CTRL     0xD0
> > > +#define  XPCS1_RX_VCO_LD_VAL_MASK            GENMASK(28, 16)
> > > +#define  XPCS1_RX_REF_LD_VAL_MASK            GENMASK(14, 8)
> > > +
> > >  #define S32G_SS_RW_REG_0                     0xF0
> > >  #define  SUBMODE_MASK                                GENMASK(3, 0)
> > >  #define  CLKEN_MASK                          BIT(23)
> > > @@ -44,6 +92,9 @@
> > >
> > >  #define S32G_PHY_REG_DATA                    0x4
> > >
> > > +#define S32G_PHY_RST_CTRL                    0x8
> > > +#define  WARM_RST                            BIT(1)
> > > +
> > >  #define RAWLANE0_DIG_PCS_XF_RX_EQ_DELTA_IQ_OVRD_IN   0x3019
> > >  #define RAWLANE1_DIG_PCS_XF_RX_EQ_DELTA_IQ_OVRD_IN   0x3119
> > >
> > > @@ -76,16 +127,33 @@ struct s32g_pcie_ctrl {
> > >       bool powered_on;
> > >  };
> > >
> > > +struct s32g_xpcs_ctrl {
> > > +     struct s32g_xpcs *phys[2];
> > > +     void __iomem *base0, *base1;
> > > +};
> > > +
> > >  struct s32g_serdes {
> > >       struct s32g_serdes_ctrl ctrl;
> > >       struct s32g_pcie_ctrl pcie;
> > > +     struct s32g_xpcs_ctrl xpcs;
> > >       struct device *dev;
> > > +     u8 lanes_status;
> > >  };
> > >
> > >  /* PCIe phy subsystem */
> > >
> > >  #define S32G_SERDES_PCIE_FREQ                        (100 * HZ_PER_MHZ)
> > >
> > > +static void s32g_pcie_phy_reset(struct s32g_serdes *serdes)
> > > +{
> > > +     u32 val;
> > > +
> > > +     val = readl(serdes->pcie.phy_base + S32G_PHY_RST_CTRL);
> > > +     writel(val | WARM_RST, serdes->pcie.phy_base + S32G_PHY_RST_CTRL);
> > > +     usleep_range(1000, 1100);
> > > +     writel(val, serdes->pcie.phy_base + S32G_PHY_RST_CTRL);
> > > +}
> > > +
> > >  static int s32g_pcie_check_clk(struct s32g_serdes *serdes)
> > >  {
> > >       struct s32g_serdes_ctrl *sctrl = &serdes->ctrl;
> > > @@ -277,6 +345,192 @@ static struct phy *s32g_serdes_phy_xlate(struct device *dev,
> > >       return phy;
> > >  }
> > >
> > > +/* XPCS subsystem */
> > > +
> > > +static int s32g_serdes_xpcs_init(struct s32g_serdes *serdes, int id)
> > > +{
> > > +     struct s32g_serdes_ctrl *ctrl = &serdes->ctrl;
> > > +     struct s32g_xpcs_ctrl *xpcs = &serdes->xpcs;
> > > +     enum s32g_xpcs_shared shared = NOT_SHARED;
> > > +     unsigned long rate = ctrl->ref_clk_rate;
> > > +     struct device *dev = serdes->dev;
> > > +     void __iomem *base;
> > > +
> > > +     if (!id)
> > > +             base = xpcs->base0;
> > > +     else
> > > +             base = xpcs->base1;
> > > +
> > > +     if (ctrl->ss_mode == 1 || ctrl->ss_mode == 2)
> > > +             shared = PCIE_XPCS_1G;
> > > +     else if (ctrl->ss_mode == 5)
> > > +             shared = PCIE_XPCS_2G5;
> > > +
> > > +     return s32g_xpcs_init(xpcs->phys[id], dev, id, base,
> > > +                            ctrl->ext_clk, rate, shared);
> > > +}
> > > +
> > > +static void s32g_serdes_prepare_pma_mode5(struct s32g_serdes *serdes)
> > > +{
> > > +     u32 val;
> > > +     /* Configure TX_VBOOST_LVL and TX_TERM_CTRL */
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MISC_CTRL_2);
> > > +     val &= ~(EXT_TX_VBOOST_LVL_MASK | EXT_TX_TERM_CTRL_MASK);
> > > +     val |= FIELD_PREP(EXT_TX_VBOOST_LVL_MASK, 0x3) |
> > > +             FIELD_PREP(EXT_TX_TERM_CTRL_MASK, 0x4);
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MISC_CTRL_2);
> > > +
> > > +     /* Enable phy external control */
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_CTRL_SEL);
> > > +     val |= EXT_PHY_CTRL_SEL;
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_CTRL_SEL);
> > > +
> > > +     /* Configure ref range, disable PLLB/ref div2 */
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_REF_CLK_CTRL);
> > > +     val &= ~(REF_CLK_DIV2_EN | REF_CLK_MPLLB_DIV2_EN | EXT_REF_RANGE_MASK);
> > > +     val |= FIELD_PREP(EXT_REF_RANGE_MASK, 0x3);
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_REF_CLK_CTRL);
> > > +
> > > +     /* Configure multiplier */
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MPLLB_CTRL_2);
> > > +     val &= ~(MPLLB_MULTIPLIER_MASK | EXT_MPLLB_FRACN_CTRL_MASK | BIT(24) | BIT(28));
> > > +     val |= FIELD_PREP(MPLLB_MULTIPLIER_MASK, 0x27U) |
> > > +             FIELD_PREP(EXT_MPLLB_FRACN_CTRL_MASK, 0x414);
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MPLLB_CTRL_2);
> > > +
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_MPLLB_CTRL);
> > > +     val &= ~MPLLB_SSC_EN;
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_MPLLB_CTRL);
> > > +
> > > +     /* Configure tx lane division, disable word clock div2*/
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MPLLB_CTRL_3);
> > > +     val &= ~(EXT_MPLLB_WORD_DIV2_EN | EXT_MPLLB_TX_CLK_DIV_MASK);
> > > +     val |= FIELD_PREP(EXT_MPLLB_TX_CLK_DIV_MASK, 0x5);
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MPLLB_CTRL_3);
> > > +
> > > +     /* Configure bandwidth for filtering and div10*/
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MPLLB_CTRL_1);
> > > +     val &= ~(EXT_MPLLB_BANDWIDTH_MASK | EXT_MPLLB_DIV_CLK_EN |
> > > +              EXT_MPLLB_DIV8_CLK_EN | EXT_MPLLB_DIV_MULTIPLIER_MASK);
> > > +     val |= FIELD_PREP(EXT_MPLLB_BANDWIDTH_MASK, 0x5f) | EXT_MPLLB_DIV10_CLK_EN;
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MPLLB_CTRL_1);
> > > +
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MPLLA_CTRL_1);
> > > +     val &= ~(EXT_MPLLA_BANDWIDTH_MASK);
> > > +     val |= FIELD_PREP(EXT_MPLLA_BANDWIDTH_MASK, 0xc5);
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MPLLA_CTRL_1);
> > > +
> > > +     /* Configure VCO */
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_XPCS1_RX_OVRD_CTRL);
> > > +     val &= ~(XPCS1_RX_VCO_LD_VAL_MASK | XPCS1_RX_REF_LD_VAL_MASK);
> > > +     val |= FIELD_PREP(XPCS1_RX_VCO_LD_VAL_MASK, 0x540) |
> > > +             FIELD_PREP(XPCS1_RX_REF_LD_VAL_MASK, 0x2b);
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_XPCS1_RX_OVRD_CTRL);
> > > +
> > > +     /* Boundary scan control */
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_BS_CTRL);
> > > +     val &= ~(EXT_BS_RX_LEVEL_MASK | EXT_BS_TX_LOWSWING);
> > > +     val |= FIELD_PREP(EXT_BS_RX_LEVEL_MASK, 0xB) | EXT_BS_RX_BIGSWING;
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_BS_CTRL);
> > > +
> > > +     /* Rx loss threshold */
> > > +     val = readl(serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MISC_CTRL_1);
> > > +     val &= ~(EXT_RX_LOS_THRESHOLD_MASK | EXT_RX_VREF_CTRL_MASK);
> > > +     val |= FIELD_PREP(EXT_RX_LOS_THRESHOLD_MASK, 0x3U) |
> > > +             FIELD_PREP(EXT_RX_VREF_CTRL_MASK, 0x11U);
> > > +     writel(val, serdes->ctrl.ss_base + S32G_PCIE_PHY_EXT_MISC_CTRL_1);
> > > +}
> > > +
> > > +static int s32g_serdes_enable_mode5(struct s32g_serdes *serdes, struct s32g_xpcs *xpcs)
> > > +{
> > > +     int ret;
> > > +
> > > +     s32g_serdes_prepare_pma_mode5(serdes);
> > > +
> > > +     ret = s32g_xpcs_pre_pcie_2g5(xpcs);
> > > +     if (ret) {
> > > +             dev_err(serdes->dev,
> > > +                     "Failed to prepare SerDes for PCIE & XPCS @ 2G5 mode\n");
> > > +             return ret;
> > > +     }
> > > +
> > > +     s32g_pcie_phy_reset(serdes);
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static int s32g_serdes_init_clks(struct s32g_serdes *serdes)
> > > +{
> > > +     struct s32g_serdes_ctrl *ctrl = &serdes->ctrl;
> > > +     struct s32g_xpcs_ctrl *xpcs = &serdes->xpcs;
> > > +     struct s32g_xpcs *order[2];
> > > +     size_t i;
> > > +     int ret;
> > > +
> > > +     switch (ctrl->ss_mode) {
> > > +     case 0:
> > > +             return 0;
> > > +     case 1:
> > > +             order[0] = xpcs->phys[0];
> > > +             order[1] = NULL;
> > > +             break;
> > > +     case 2:
> > > +     case 5:
> > > +             order[0] = xpcs->phys[1];
> > > +             order[1] = NULL;
> > > +             break;
> > > +     case 3:
> > > +             order[0] = xpcs->phys[1];
> > > +             order[1] = xpcs->phys[0];
> > > +             break;
> > > +     case 4:
> > > +             order[0] = xpcs->phys[0];
> > > +             order[1] = xpcs->phys[1];
> > > +             break;
> > > +     default:
> > > +             return -EINVAL;
> > > +     }
> > > +
> > > +     for (i = 0; i < ARRAY_SIZE(order); i++) {
> > > +             if (!order[i])
> > > +                     continue;
> > > +
> > > +             ret = s32g_xpcs_init_plls(order[i]);
> > > +             if (ret)
> > > +                     return ret;
> > > +     }
> > > +
> > > +     for (i = 0; i < ARRAY_SIZE(order); i++) {
> > > +             if (!order[i])
> > > +                     continue;
> > > +
> > > +             if (ctrl->ss_mode == 5) {
> > > +                     ret = s32g_serdes_enable_mode5(serdes, order[i]);
> > > +                     if (ret)
> > > +                             return ret;
> > > +             } else {
> > > +                     s32g_xpcs_vreset(order[i]);
> > > +             }
> > > +     }
> > > +
> > > +     for (i = 0; i < ARRAY_SIZE(order); i++) {
> > > +             if (!order[i])
> > > +                     continue;
> > > +
> > > +             ret = s32g_xpcs_wait_vreset(order[i]);
> > > +             if (ret)
> > > +                     return ret;
> > > +
> > > +             ret = s32g_xpcs_reset_rx(order[i]);
> > > +             if (ret)
> > > +                     return ret;
> > > +
> > > +             s32g_xpcs_disable_an(order[i]);
> > > +     }
> > > +
> > > +     return 0;
> > > +}
> > > +
> > >  /* Serdes subsystem */
> > >
> > >  static int s32g_serdes_assert_reset(struct s32g_serdes *serdes)
> > > @@ -331,6 +585,10 @@ static int s32g_serdes_init(struct s32g_serdes *serdes)
> > >               return ret;
> > >       }
> > >
> > > +     /*
> > > +      * We have a tight timing for the init sequence and any delay linked to
> > > +      * printk as an example can fail the init after reset
> > > +      */
> > >       ret = s32g_serdes_assert_reset(serdes);
> > >       if (ret)
> > >               goto disable_clks;
> > > @@ -363,7 +621,13 @@ static int s32g_serdes_init(struct s32g_serdes *serdes)
> > >       dev_info(serdes->dev, "Using mode %d for SerDes subsystem\n",
> > >                ctrl->ss_mode);
> > >
> > > -     return 0;
> > > +     ret = s32g_serdes_init_clks(serdes);
> > > +     if (ret) {
> > > +             dev_err(serdes->dev, "XPCS init failed\n");
> > > +             goto disable_clks;
> > > +     }
> > > +
> > > +     return ret;
> > >
> > >  disable_clks:
> > >       clk_bulk_disable_unprepare(serdes->ctrl.nclks,
> > > @@ -449,12 +713,32 @@ static int s32g_serdes_get_pcie_resources(struct platform_device *pdev, struct s
> > >       return 0;
> > >  }
> > >
> > > +static int s32g_serdes_get_xpcs_resources(struct platform_device *pdev, struct s32g_serdes *serdes)
> > > +{
> > > +     struct s32g_xpcs_ctrl *xpcs = &serdes->xpcs;
> > > +     struct device *dev = &pdev->dev;
> > > +
> > > +     xpcs->base0 = devm_platform_ioremap_resource_byname(pdev, "xpcs0");
> > > +     if (IS_ERR(xpcs->base0)) {
> > > +             dev_err(dev, "Failed to map 'xpcs0'\n");
> > > +             return PTR_ERR(xpcs->base0);
> > > +     }
> > > +
> > > +     xpcs->base1 = devm_platform_ioremap_resource_byname(pdev, "xpcs1");
> > > +     if (IS_ERR(xpcs->base1)) {
> > > +             dev_err(dev, "Failed to map 'xpcs1'\n");
> > > +             return PTR_ERR(xpcs->base1);
> > > +     }
> > > +
> > > +     return 0;
> > > +}
> > > +
> > >  static int s32g2_serdes_create_phy(struct s32g_serdes *serdes, struct device_node *child_node)
> > >  {
> > >       struct s32g_serdes_ctrl *ctrl = &serdes->ctrl;
> > >       struct phy_provider *phy_provider;
> > >       struct device *dev = serdes->dev;
> > > -     int ss_mode = ctrl->ss_mode;
> > > +     int ret, ss_mode = ctrl->ss_mode;
> > >       struct phy *phy;
> > >
> > >       if (of_device_is_compatible(child_node, "nxp,s32g2-serdes-pcie-phy")) {
> > > @@ -476,6 +760,37 @@ static int s32g2_serdes_create_phy(struct s32g_serdes *serdes, struct device_nod
> > >               if (IS_ERR(phy_provider))
> > >                       return PTR_ERR(phy_provider);
> > >
> > > +     } else if (of_device_is_compatible(child_node, "nxp,s32g2-serdes-xpcs")) {
> > > +             struct s32g_xpcs_ctrl *xpcs_ctrl = &serdes->xpcs;
> > > +             struct s32g_xpcs *xpcs;
> > > +             int port;
> > > +
> > > +             /* no Ethernet phy lane */
> > > +             if (ss_mode == 0)
> > > +                     return 0;
> > > +
> > > +             /* Get XPCS port number connected to the lane */
> > > +             if (of_property_read_u32(child_node, "reg", &port))
> > > +                     return -EINVAL;
> > > +
> > > +             /* XPCS1 is not used */
> > > +             if (ss_mode == 1 && port == 1)
> > > +                     return -EINVAL;
> > > +
> > > +             /* XPCS0 is not used */
> > > +             if (ss_mode == 2 && port == 0)
> > > +                     return -EINVAL;
> > > +
> > > +             xpcs = devm_kmalloc(dev, sizeof(*xpcs), GFP_KERNEL);
> > > +             if (!xpcs)
> > > +                     return -ENOMEM;
> > > +
> > > +             xpcs_ctrl->phys[port] = xpcs;
> > > +
> > > +             ret = s32g_serdes_xpcs_init(serdes, port);
> > > +             if (ret)
> > > +                     return ret;
> > > +
> > >       } else {
> > >               dev_warn(dev, "Skipping unknown child node %pOFn\n", child_node);
> > >       }
> > > @@ -517,6 +832,10 @@ static int s32g_serdes_probe(struct platform_device *pdev)
> > >       if (ret)
> > >               return ret;
> > >
> > > +     ret = s32g_serdes_get_xpcs_resources(pdev, serdes);
> > > +     if (ret)
> > > +             return ret;
> > > +
> > >       ret = s32g_serdes_parse_lanes(dev, serdes);
> > >       if (ret)
> > >               return ret;
> > > @@ -555,6 +874,57 @@ static int __maybe_unused s32g_serdes_resume(struct device *device)
> > >       return ret;
> > >  }
> > >
> > > +struct phylink_pcs *s32g_serdes_pcs_create(struct device *dev, struct device_node *np)
> > > +{
> > > +     struct platform_device *pdev;
> > > +     struct device_node *pcs_np;
> > > +     struct s32g_serdes *serdes;
> > > +     u32 port;
> > > +
> > > +     if (of_property_read_u32(np, "reg", &port))
> > > +             return ERR_PTR(-EINVAL);
> > > +
> > > +     if (port >= S32G_SERDES_XPCS_MAX)
> > > +             return ERR_PTR(-EINVAL);
> > > +
> > > +     /* The PCS pdev is attached to the parent node */
> > > +     pcs_np = of_get_parent(np);
> > > +     if (!pcs_np)
> > > +             return ERR_PTR(-ENODEV);
> > > +
> > > +     if (!of_device_is_available(pcs_np)) {
> > > +             of_node_put(pcs_np);
> > > +             return ERR_PTR(-ENODEV);
> > > +     }
> > > +
> > > +     pdev = of_find_device_by_node(pcs_np);
> > > +     of_node_put(pcs_np);
> > > +     if (!pdev)
> > > +             return ERR_PTR(-EPROBE_DEFER);
> > > +
> > > +     serdes = platform_get_drvdata(pdev);
> > > +     if (!serdes) {
> > > +             put_device(&pdev->dev);
> > > +             return ERR_PTR(-EPROBE_DEFER);
> > > +     }
> > > +
> > > +     if (!serdes->xpcs.phys[port]) {
> > > +             put_device(&pdev->dev);
> > > +             return ERR_PTR(-EPROBE_DEFER);
> > > +     }
> > > +
> > > +     return &serdes->xpcs.phys[port]->pcs;
> > > +}
> > > +EXPORT_SYMBOL(s32g_serdes_pcs_create);
> > > +
> > > +void s32g_serdes_pcs_destroy(struct phylink_pcs *pcs)
> > > +{
> > > +     struct s32g_xpcs *xpcs = phylink_pcs_to_s32g_xpcs(pcs);
> > > +
> > > +     put_device(xpcs->dev);
> > > +}
> > > +EXPORT_SYMBOL(s32g_serdes_pcs_destroy);
> > > +
> > >  static const struct of_device_id s32g_serdes_match[] = {
> > >       {
> > >               .compatible = "nxp,s32g2-serdes",
> > > diff --git a/include/linux/pcs/pcs-nxp-s32g-xpcs.h b/include/linux/pcs/pcs-nxp-s32g-xpcs.h
> > > new file mode 100644
> > > index 000000000000..96a0049b93a6
> > > --- /dev/null
> > > +++ b/include/linux/pcs/pcs-nxp-s32g-xpcs.h
> > > @@ -0,0 +1,50 @@
> > > +/* SPDX-License-Identifier: GPL-2.0 */
> > > +/**
> > > + * Copyright 2021-2026 NXP
> > > + */
> > > +#ifndef PCS_NXP_S32G_XPCS_H
> > > +#define PCS_NXP_S32G_XPCS_H
> > > +
> > > +#include <linux/phylink.h>
> > > +
> > > +enum s32g_xpcs_shared {
> > > +     NOT_SHARED,
> > > +     PCIE_XPCS_1G,
> > > +     PCIE_XPCS_2G5,
> > > +};
> > > +
> > > +enum s32g_xpcs_pll {
> > > +     XPCS_PLLA,      /* Slow PLL */
> > > +     XPCS_PLLB,      /* Fast PLL */
> > > +};
> > > +
> > > +struct s32g_xpcs {
> > > +     void __iomem *base;
> > > +     struct device *dev;
> > > +     unsigned char id;
> > > +     struct regmap *regmap;
> > > +     enum s32g_xpcs_pll ref;
> > > +     bool ext_clk;
> > > +     bool mhz125;
> > > +     enum s32g_xpcs_shared pcie_shared;
> > > +     struct phylink_pcs pcs;
> > > +};
> > > +
> > > +#define phylink_pcs_to_s32g_xpcs(pl_pcs) \
> > > +     container_of((pl_pcs), struct s32g_xpcs, pcs)
> > > +
> > > +int s32g_xpcs_init(struct s32g_xpcs *xpcs, struct device *dev,
> > > +                unsigned char id, void __iomem *base, bool ext_clk,
> > > +                unsigned long rate, enum s32g_xpcs_shared pcie_shared);
> > > +int s32g_xpcs_init_plls(struct s32g_xpcs *xpcs);
> > > +int s32g_xpcs_pre_pcie_2g5(struct s32g_xpcs *xpcs);
> > > +void s32g_xpcs_vreset(struct s32g_xpcs *xpcs);
> > > +int s32g_xpcs_wait_vreset(struct s32g_xpcs *xpcs);
> > > +int s32g_xpcs_reset_rx(struct s32g_xpcs *xpcs);
> > > +void s32g_xpcs_disable_an(struct s32g_xpcs *xpcs);
> > > +
> > > +struct phylink_pcs *s32g_serdes_pcs_create(struct device *dev, struct device_node *np);
> > > +void s32g_serdes_pcs_destroy(struct phylink_pcs *pcs);
> > > +
> > > +#endif /* PCS_NXP_S32G_XPCS_H */
> > > +
> > > --
> > > 2.43.0
> > >
> > >
> >
> >
> > --
> > RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> > FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
>



^ permalink raw reply

* Re: [PATCH RFC 05/12] usb: hub: Power on connected M.2 E-key connectors
From: Chen-Yu Tsai @ 2026-05-18  9:13 UTC (permalink / raw)
  To: Alan Stern
  Cc: Bartosz Golaszewski, Greg Kroah-Hartman, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
	AngeloGioacchino Del Regno, linux-pm, linux-usb, devicetree,
	linux-mediatek, linux-arm-kernel, linux-kernel,
	Manivannan Sadhasivam
In-Reply-To: <41260a6d-46fa-4a45-9906-e1bc5e5dd83a@rowland.harvard.edu>

On Fri, May 15, 2026 at 10:39 PM Alan Stern <stern@rowland.harvard.edu> wrote:
>
> On Fri, May 15, 2026 at 05:01:41PM +0800, Chen-Yu Tsai wrote:
> > diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> > index 90ea597d42ae..4165f71e212b 100644
> > --- a/drivers/usb/core/hub.c
> > +++ b/drivers/usb/core/hub.c
> > @@ -31,7 +31,9 @@
> >  #include <linux/minmax.h>
> >  #include <linux/mutex.h>
> >  #include <linux/random.h>
> > +#include <linux/of_graph.h>
> >  #include <linux/pm_qos.h>
> > +#include <linux/pwrseq/consumer.h>
> >  #include <linux/kobject.h>
> >
> >  #include <linux/bitfield.h>
> > @@ -888,13 +890,25 @@ int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
> >  {
> >       int ret;
> >
> > +     if (set)
> > +             ret = pwrseq_power_on(hub->ports[port1 - 1]->pwrseq);
> > +     else
> > +             ret = pwrseq_power_off(hub->ports[port1 - 1]->pwrseq);
> > +     if (ret)
> > +             return ret;
> > +
> >       if (set)
> >               ret = set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
> >       else
> >               ret = usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
> >
> > -     if (ret)
> > +     if (ret) {
> > +             if (set)
> > +                     pwrseq_power_off(hub->ports[port1 - 1]->pwrseq);
> > +             else
> > +                     pwrseq_power_on(hub->ports[port1 - 1]->pwrseq);
> >               return ret;
> > +     }
> >
> >       if (set)
> >               set_bit(port1, hub->power_bits);
> > @@ -1867,6 +1881,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
> >       struct usb_host_interface *desc;
> >       struct usb_device *hdev;
> >       struct usb_hub *hub;
> > +     int ret;
> >
> >       desc = intf->cur_altsetting;
> >       hdev = interface_to_usbdev(intf);
>
> This change is totally useless.  Didn't you get a warning from the
> compiler when you built it?

Apologies. This should have been part of the previous patch.

> > diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
> > index 9ebc5ef54a32..6039e5f5dcd7 100644
> > --- a/drivers/usb/core/hub.h
> > +++ b/drivers/usb/core/hub.h
> > @@ -85,6 +85,7 @@ struct usb_hub {
> >   * @port_owner: port's owner
> >   * @peer: related usb2 and usb3 ports (share the same connector)
> >   * @connector: USB Type-C connector
> > + * @pwrseq: power sequencing descriptor for the port
> >   * @req: default pm qos request for hubs without port power control
> >   * @connect_type: port's connect type
> >   * @state: device state of the usb device attached to the port
> > @@ -104,6 +105,7 @@ struct usb_port {
> >       struct usb_dev_state *port_owner;
> >       struct usb_port *peer;
> >       struct typec_connector *connector;
> > +     struct pwrseq_desc *pwrseq;
> >       struct dev_pm_qos_request *req;
> >       enum usb_port_connect_type connect_type;
> >       enum usb_device_state state;
>
> The fact that hub.h uses struct pwrseq_desc indicates that it ought to
> #include <linux/pwrseq/consumer.h>, instead of making the .c files do
> so themselves.  Then you wouldn't have to add the #include lines to
> hub.c and port.c.

I couldn't tell if the existing pattern in this file was to include
the headers or not, as it's missing a whole bunch.

Regardless of whether this header file includes linux/pwrseq/consumer.h
or has a forward declaration or nothing, I think that if the .c files
use the API, then they should include the corresponding header file
directly.

> > diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
> > index b1364f0c384c..2d09037fee93 100644
> > --- a/drivers/usb/core/port.c
> > +++ b/drivers/usb/core/port.c
> > @@ -7,11 +7,14 @@
> >   * Author: Lan Tianyu <tianyu.lan@intel.com>
> >   */
> >
> > +#include <linux/cleanup.h>
>
> Why is this needed?

For the __free() in usb_hub_port_pwrseq_get() below:

    struct device_node *np __free(device_node) = NULL;


Thanks
ChenYu


> >  #include <linux/kstrtox.h>
> >  #include <linux/slab.h>
> >  #include <linux/string_choices.h>
> >  #include <linux/sysfs.h>
> > +#include <linux/of_graph.h>
> >  #include <linux/pm_qos.h>
> > +#include <linux/pwrseq/consumer.h>
> >  #include <linux/component.h>
> >  #include <linux/usb/of.h>
> >
>
> Alan Stern


^ permalink raw reply

* [PATCH v2] firmware: imx: scu-irq: drop wakeup_src sysfs file, log via dev_dbg()
From: Stepan Ionichev @ 2026-05-18  9:39 UTC (permalink / raw)
  To: Frank.Li
  Cc: peng.fan, s.hauer, kernel, festevam, shawnguo, gregkh, hcazarim,
	imx, linux-arm-kernel, linux-kernel, sozdayvek
In-Reply-To: <20260515175002.34853-1-sozdayvek@gmail.com>

wakeup_source_show() walks all IMX_SC_IRQ_NUM_GROUP groups and
rewrites buf from offset 0 each iteration, so userspace reading
/sys/firmware/scu_wakeup_source/wakeup_src only ever sees the last
group reported, and the trailing strlen(buf) reports only that
line length. sprintf() is also unbounded against the sysfs
PAGE_SIZE buffer.

The attribute is not documented under Documentation/ABI/ and a code
search across GitHub and Debian found no out-of-tree consumers.
Peng Fan (NXP) confirmed it is safe to drop.

Remove the attribute, the supporting kobject and the per-group
valid/wakeup_src state used only to feed it. Log the same wakeup
information via dev_dbg() from imx_scu_irq_work_handler() so it
can be enabled dynamically when needed.

Fixes: c081197a33a2 ("firmware: imx: scu-irq: support identifying SCU wakeup source from sysfs")
Suggested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Link: https://lore.kernel.org/all/2026051656-corral-edgy-290c@gregkh/
Signed-off-by: Stepan Ionichev <sozdayvek@gmail.com>
---
v2:
- Drop the sysfs file entirely instead of patching it (Greg)
- Log wakeup info via dev_dbg() in the IRQ work handler (Greg)
- Peng Fan (NXP) confirmed no out-of-tree consumers

v1: https://lore.kernel.org/all/20260515175002.34853-1-sozdayvek@gmail.com/

 drivers/firmware/imx/imx-scu-irq.c | 84 ++++++------------------------
 1 file changed, 16 insertions(+), 68 deletions(-)

diff --git a/drivers/firmware/imx/imx-scu-irq.c b/drivers/firmware/imx/imx-scu-irq.c
index a68d38f89..5969460ba 100644
--- a/drivers/firmware/imx/imx-scu-irq.c
+++ b/drivers/firmware/imx/imx-scu-irq.c
@@ -9,11 +9,9 @@
 #include <dt-bindings/firmware/imx/rsrc.h>
 #include <linux/firmware/imx/ipc.h>
 #include <linux/firmware/imx/sci.h>
-#include <linux/kobject.h>
 #include <linux/mailbox_client.h>
 #include <linux/of.h>
 #include <linux/suspend.h>
-#include <linux/sysfs.h>
 
 #define IMX_SC_IRQ_FUNC_ENABLE	1
 #define IMX_SC_IRQ_FUNC_STATUS	2
@@ -43,19 +41,8 @@ struct imx_sc_msg_irq_enable {
 	u8 enable;
 } __packed;
 
-struct scu_wakeup {
-	u32 mask;
-	u32 wakeup_src;
-	bool valid;
-};
-
-/* Sysfs functions */
-static struct kobject *wakeup_obj;
-static ssize_t wakeup_source_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
-static struct kobj_attribute wakeup_source_attr =
-		__ATTR(wakeup_src, 0660, wakeup_source_show, NULL);
-
-static struct scu_wakeup scu_irq_wakeup[IMX_SC_IRQ_NUM_GROUP];
+static u32 scu_irq_wakeup_mask[IMX_SC_IRQ_NUM_GROUP];
+static struct device *imx_sc_irq_dev;
 
 static struct imx_sc_ipc *imx_sc_irq_ipc_handle;
 static struct work_struct imx_sc_irq_work;
@@ -88,11 +75,6 @@ static void imx_scu_irq_work_handler(struct work_struct *work)
 	u8 i;
 
 	for (i = 0; i < IMX_SC_IRQ_NUM_GROUP; i++) {
-		if (scu_irq_wakeup[i].mask) {
-			scu_irq_wakeup[i].valid = false;
-			scu_irq_wakeup[i].wakeup_src = 0;
-		}
-
 		ret = imx_scu_irq_get_status(i, &irq_status);
 		if (ret) {
 			pr_err("get irq group %d status failed, ret %d\n",
@@ -102,12 +84,15 @@ static void imx_scu_irq_work_handler(struct work_struct *work)
 
 		if (!irq_status)
 			continue;
-		if (scu_irq_wakeup[i].mask & irq_status) {
-			scu_irq_wakeup[i].valid = true;
-			scu_irq_wakeup[i].wakeup_src = irq_status & scu_irq_wakeup[i].mask;
-		} else {
-			scu_irq_wakeup[i].wakeup_src = irq_status;
-		}
+
+		if (scu_irq_wakeup_mask[i] & irq_status)
+			dev_dbg(imx_sc_irq_dev,
+				"Wakeup source group = %d, irq = 0x%x\n",
+				i, irq_status & scu_irq_wakeup_mask[i]);
+		else
+			dev_dbg(imx_sc_irq_dev,
+				"Spurious SCU wakeup, group = %d, irq = 0x%x\n",
+				i, irq_status);
 
 		pm_system_wakeup();
 		imx_scu_irq_notifier_call_chain(irq_status, &i);
@@ -164,9 +149,9 @@ int imx_scu_irq_group_enable(u8 group, u32 mask, u8 enable)
 			group, mask, ret);
 
 	if (enable)
-		scu_irq_wakeup[group].mask |= mask;
+		scu_irq_wakeup_mask[group] |= mask;
 	else
-		scu_irq_wakeup[group].mask &= ~mask;
+		scu_irq_wakeup_mask[group] &= ~mask;
 
 	return ret;
 }
@@ -177,25 +162,6 @@ static void imx_scu_irq_callback(struct mbox_client *c, void *msg)
 	schedule_work(&imx_sc_irq_work);
 }
 
-static ssize_t wakeup_source_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
-{
-	int i;
-
-	for (i = 0; i < IMX_SC_IRQ_NUM_GROUP; i++) {
-		if (!scu_irq_wakeup[i].wakeup_src)
-			continue;
-
-		if (scu_irq_wakeup[i].valid)
-			sprintf(buf, "Wakeup source group = %d, irq = 0x%x\n",
-				i, scu_irq_wakeup[i].wakeup_src);
-		else
-			sprintf(buf, "Spurious SCU wakeup, group = %d, irq = 0x%x\n",
-				i, scu_irq_wakeup[i].wakeup_src);
-	}
-
-	return strlen(buf);
-}
-
 int imx_scu_enable_general_irq_channel(struct device *dev)
 {
 	struct of_phandle_args spec;
@@ -233,29 +199,11 @@ int imx_scu_enable_general_irq_channel(struct device *dev)
 	if (IS_ERR(ch)) {
 		ret = PTR_ERR(ch);
 		dev_err(dev, "failed to request mbox chan gip3, ret %d\n", ret);
-		goto free_cl;
-	}
-
-	/* Create directory under /sysfs/firmware */
-	wakeup_obj = kobject_create_and_add("scu_wakeup_source", firmware_kobj);
-	if (!wakeup_obj) {
-		ret = -ENOMEM;
-		goto free_ch;
+		devm_kfree(dev, cl);
+		return ret;
 	}
 
-	ret = sysfs_create_file(wakeup_obj, &wakeup_source_attr.attr);
-	if (ret) {
-		dev_err(dev, "Cannot create wakeup source src file......\n");
-		kobject_put(wakeup_obj);
-		goto free_ch;
-	}
+	imx_sc_irq_dev = dev;
 
 	return 0;
-
-free_ch:
-	mbox_free_channel(ch);
-free_cl:
-	devm_kfree(dev, cl);
-
-	return ret;
 }
-- 
2.43.0



^ permalink raw reply related

* Re: [PATCH 0/4] arm64: dts: mediatek: random Chromebook cleanups
From: AngeloGioacchino Del Regno @ 2026-05-18  9:40 UTC (permalink / raw)
  To: Matthias Brugger, Chen-Yu Tsai
  Cc: linux-mediatek, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20260514101254.2749300-1-wenst@chromium.org>

On Thu, 14 May 2026 18:12:48 +0800, Chen-Yu Tsai wrote:
> Here are some random DT cleanups that are not directly related to other
> topics I'm working on, but came up when checking for warnings.
> 
> The regulator related changes overlap with my other "Regulator cleanup
> for Chromebooks" series [1].
> 
> Please have a look.
> 
> [...]

Applied to v7.1-next/dts64, thanks!

[1/4] arm64: dts: mediatek: mt8192-asurada: Fix SPI-NOR flash compatible
      commit: 95937cbb6d51e0c6f8ac937bd043fb3b442391ec
[2/4] arm64: dts: mediatek: mt8192-asurada: Add (BT|WIFI)_KILL_1V8_L GPIO line names
      commit: c42235145c52955ab20fcb648bb8c7818f58282b
[3/4] arm64: dts: mediatek: mt8195-cherry: Fix names for EC controlled regulators
      commit: 2066ac078402301d9aa50026dee017182d316eac
[4/4] arm64: dts: mediatek: mt8195-cherry: Sort top level nodes correctly
      commit: 559b8b1524760ad8dc18d52c4415d40ee24d02fc

Cheers,
Angelo




^ permalink raw reply

* RE: [PATCH 2/2] ARM: dts: aspeed: rainiera6: Add Meta Rainiera6 BMC
From: Biju Das @ 2026-05-18  9:45 UTC (permalink / raw)
  To: Neil Cheng, robh@kernel.org, krzk+dt@kernel.org,
	conor+dt@kernel.org, joel@jms.id.au, andrew@codeconstruct.com.au,
	geert+renesas@glider.be, magnus.damm
  Cc: devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	linux-renesas-soc@vger.kernel.org
In-Reply-To: <afee3ea3d6d697d039ce97cc7add47e97bbdab4e.1779088499.git.neilcheng0417@gmail.com>

Hi Neil Cheng, 

> -----Original Message-----
> From: Neil Cheng <neilcheng0417@gmail.com>
> Sent: 18 May 2026 09:13
> Subject: [PATCH 2/2] ARM: dts: aspeed: rainiera6: Add Meta Rainiera6 BMC
> 
> [You don't often get email from neilcheng0417@gmail.com. Learn why this is important at
> https://aka.ms/LearnAboutSenderIdentification ]
> 
> Add device tree for the Meta (Facebook) Rainiera6 compute node, based on
> AST2600 BMC.
> 
> Signed-off-by: Neil Cheng <neilcheng0417@gmail.com>
> ---
>  arch/arm/boot/dts/aspeed/Makefile             |    1 +
>  .../aspeed/aspeed-bmc-facebook-rainiera6.dts  | 1012 +++++++++++++++++
>  2 files changed, 1013 insertions(+)
>  create mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-rainiera6.dts
> 
> diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile
> index 767f7c7652d5..215429af1135 100644
> --- a/arch/arm/boot/dts/aspeed/Makefile
> +++ b/arch/arm/boot/dts/aspeed/Makefile
> @@ -34,6 +34,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
>         aspeed-bmc-facebook-harma.dtb \
>         aspeed-bmc-facebook-minerva.dtb \
>         aspeed-bmc-facebook-minipack.dtb \
> +       aspeed-bmc-facebook-rainiera6.dtb \
>         aspeed-bmc-facebook-santabarbara.dtb \
>         aspeed-bmc-facebook-tiogapass.dtb \
>         aspeed-bmc-facebook-wedge40.dtb \ diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-
> rainiera6.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-rainiera6.dts
> new file mode 100644
> index 000000000000..2c8c983db677
> --- /dev/null
> +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-rainiera6.dts
> @@ -0,0 +1,1012 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +// Copyright (c) 2026 Facebook Inc.
> +
> +/dts-v1/;
> +#include "aspeed-g6.dtsi"
> +#include <dt-bindings/gpio/aspeed-gpio.h> #include
> +<dt-bindings/i2c/i2c.h>
> +
> +/ {
> +       model = "Facebook Rainier BMC";
> +       compatible = "facebook,rainiera6-bmc", "aspeed,ast2600";
> +
> +       aliases {
> +               i2c16 = &i2c5mux0ch0;
> +               i2c17 = &i2c5mux0ch1;
> +               i2c18 = &i2c5mux1ch0;
> +               i2c19 = &i2c5mux1ch1;
> +               i2c20 = &i2c6mux0ch0;
> +               i2c21 = &i2c6mux0ch1;
> +               i2c22 = &i2c6mux0ch2;
> +               i2c23 = &i2c6mux0ch3;
> +               i2c24 = &i2c8mux0ch0;
> +               i2c25 = &i2c8mux0ch1;
> +               i2c26 = &i2c8mux0ch2;
> +               i2c27 = &i2c8mux0ch3;
> +               i2c28 = &i2c26mux0ch0;
> +               i2c29 = &i2c26mux0ch1;
> +               i2c30 = &i2c26mux0ch2;
> +               i2c31 = &i2c26mux0ch3;
> +               serial0 = &uart1;
> +               serial2 = &uart3;
> +               serial3 = &uart4;
> +               serial4 = &uart5;
> +       };
> +
> +       chosen {
> +               stdout-path = "serial4:57600n8";
> +       };
> +
> +       iio-hwmon {
> +               compatible = "iio-hwmon";
> +               io-channels = <&adc0 0>, <&adc0 1>, <&adc0 2>, <&adc0 3>,
> +                                         <&adc0 4>, <&adc0 5>, <&adc0 6>, <&adc0 7>,
> +                                         <&adc1 2>;
> +       };
> +
> +       leds {
> +               compatible = "gpio-leds";
> +
> +               led-0 {
> +                       label = "bmc_heartbeat_amber";
> +                       gpios = <&gpio0 ASPEED_GPIO(P, 7) GPIO_ACTIVE_LOW>;
> +                       linux,default-trigger = "heartbeat";
> +               };
> +
> +               led-1 {
> +                       label = "fp_id_amber";
> +                       default-state = "off";
> +                       gpios = <&gpio0 ASPEED_GPIO(B, 5) GPIO_ACTIVE_HIGH>;
> +               };
> +
> +               led-2 {
> +                       label = "power_fault_amber";
> +                       default-state = "off";
> +                       gpios = <&gpio0 ASPEED_GPIO(P, 4) GPIO_ACTIVE_HIGH>;
> +               };
> +       };
> +
> +       memory@80000000 {
> +               device_type = "memory";
> +               reg = <0x80000000 0x80000000>;
> +       };
> +
> +       p1v8_adc_vref: regulator-p1v8-aux {
> +               compatible = "regulator-fixed";
> +               regulator-name = "p1v8_adc_vref";
> +               regulator-min-microvolt = <1800000>;
> +               regulator-max-microvolt = <1800000>;
> +               regulator-always-on;
> +       };
> +
> +       spi_gpio: spi {
> +               compatible = "spi-gpio";
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +
> +               sck-gpios = <&gpio0 ASPEED_GPIO(Z, 3) GPIO_ACTIVE_HIGH>;
> +               mosi-gpios = <&gpio0 ASPEED_GPIO(Z, 4) GPIO_ACTIVE_HIGH>;
> +               miso-gpios = <&gpio0 ASPEED_GPIO(Z, 5) GPIO_ACTIVE_HIGH>;
> +               cs-gpios = <&gpio0 ASPEED_GPIO(Z, 0) GPIO_ACTIVE_LOW>;
> +               num-chipselects = <1>;
> +               status = "okay";
> +
> +               tpm@0 {
> +                       compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
> +                       spi-max-frequency = <33000000>;
> +                       reg = <0>;
> +               };
> +       };
> +};
> +
> +&adc0 {
> +       vref-supply = <&p1v8_adc_vref>;
> +       status = "okay";

Maybe status after pinctrl entries to consistent with wdt1 and spi2 below??

Cheers,
Biju

> +       pinctrl-names = "default";
> +       pinctrl-0 = <&pinctrl_adc0_default &pinctrl_adc1_default
> +                                &pinctrl_adc2_default &pinctrl_adc3_default
> +                                &pinctrl_adc4_default &pinctrl_adc5_default
> +                                &pinctrl_adc6_default
> +&pinctrl_adc7_default>; };
> +
> +&adc1 {
> +       aspeed,int-vref-microvolt = <2500000>;
> +       status = "okay";
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&pinctrl_adc10_default>; };
> +
> +&ehci0 {
> +       status = "okay";
> +};
> +
> +&ehci1 {
> +       status = "okay";
> +};
> +
> +&fmc {
> +       status = "okay";
> +
> +       flash@0 {
> +               status = "okay";
> +               m25p,fast-read;
> +               label = "bmc";
> +               spi-max-frequency = <50000000>; #include
> +"openbmc-flash-layout-128.dtsi"
> +       };
> +
> +       flash@1 {
> +               status = "okay";
> +               m25p,fast-read;
> +               label = "alt-bmc";
> +               spi-max-frequency = <50000000>;
> +       };
> +};
> +
> +&gpio0 {
> +       gpio-line-names =
> +       /*A0-A7*/       "","","","","","","","",
> +       /*B0-B7*/       "BATTERY_DETECT","","BMC_I2C1_FPGA_ALERT_L","BMC_READY_R",
> +                               "IOEXP_INT_3V3_L_R1","FM_ID_LED","","",
> +       /*C0-C7*/       "BMC_GPIOC0","","","","PMBUS_REQ_N","PSU_FW_UPDATE_REQ_N","",
> +                               "BMC_I2C_SSIF_ALERT_L",
> +       /*D0-D7*/       "","","","","BMC_GPIOD4","","","",
> +       /*E0-E7*/       "BMC_GPIOE0","BMC_GPIOE1","","","","","","",
> +       /*F0-F7*/       "","","","","","","","",
> +       /*G0-G7*/       "FM_BMC_MUX1_SEL_R","","","","","","FM_DEBUG_PORT_PRSNT_R1_N",
> +                       "FM_BMC_DBP_PRESENT_R_N",
> +       /*H0-H7*/       "","","","","","","","",
> +       /*I0-I7*/       "","","","","","FLASH_WP_STATUS_R1","BMC_JTAG_MUX_SEL","",
> +       /*J0-J7*/       "","","","","","","","",
> +       /*K0-K7*/       "","","","","","","","",
> +       /*L0-L7*/       "","","","","","","","",
> +       /*M0-M7*/       "PCIE_EP_RST_EN","BMC_FRU_WP","SCM_HPM_STBY_RST_N",
> +                               "SCM_HPM_STBY_R_EN","STBY_POWER_PG_3V3_R","TH500_SHDN_OK_L","","",
> +       /*N0-N7*/       "LED_POSTCODE_0","LED_POSTCODE_1","LED_POSTCODE_2",
> +                               "LED_POSTCODE_3","LED_POSTCODE_4","LED_POSTCODE_5",
> +                               "LED_POSTCODE_6","LED_POSTCODE_7",
> +       /*O0-O7*/       "RUN_POWER_PG","PWR_BRAKE_L","CHASSIS_AC_LOSS_L",
> +                               "BSM_PRSNT_R_N","PSU_SMB_ALERT_L","FM_TPM_PRSNT_0_N",
> +                               "PSU_FW_UPDATING_N","DEBUG_CARD_BYPASS",
> +       /*P0-P7*/       "PWR_BTN_BMC_R1_N","IPEX_CABLE_PRSNT_L","ID_RST_BTN_BMC_R_N",
> +                               "RST_BMC_RSTBTN_OUT_R_N","BMC_PWR_LED","RUN_POWER_EN",
> +                               "SHDN_FORCE_L","BMC_HEARTBEAT_N",
> +       /*Q0-Q7*/       "IRQ_PCH_TPM_SPI_LV3_N","USB_OC0_REAR_R_N","UART_MUX_SEL",
> +                               "I2C_MUX_RESET_L","RSVD_NV_PLT_DETECT","SPI_TPM_INT_L",
> +                               "CPU_JTAG_MUX_SELECT","THERM_BB_OVERT_L",
> +       /*R0-R7*/       "THERM_BB_WARN_L","SPI_BMC_FPGA_INT_L","CPU_BOOT_DONE",
> +                               "PMBUS_GNT_L","CHASSIS_PWR_BRK_L","PCIE_WAKE_L","PDB_THERM_OVERT_L",
> +                               "SHDN_REQ_L",
> +       /*S0-S7*/       "","","SYS_BMC_PWRBTN_R_N","FM_TPM_PRSNT_1_N",
> +                               "FM_BMC_DEBUG_SW_N","UID_LED_N","SYS_FAULT_LED_N",
> +                               "RUN_POWER_FAULT_L",
> +       /*T0-T7*/       "","","","","","","","",
> +       /*U0-U7*/       "","","","","","","","",
> +       /*V0-V7*/       "L2_RST_REQ_OUT_L","L0L1_RST_REQ_OUT_L","BMC_ID_BEEP_SEL_R1",
> +                               "BMC_I2C0_FPGA_ALERT_L","SMB_BMC_TMP_ALERT","PWR_LED_N",
> +                               "SYS_RST_OUT_L","IRQ_TPM_SPI_N",
> +       /*W0-W7*/       "","","","","","","","",
> +       /*X0-X7*/       "","FM_DBP_CPU_PREQ_GF_N_R1","","","","","","",
> +       /*Y0-Y7*/       "","RST_BMC_SELF_HW_R1","FM_FLASH_LATCH_N_R1","",
> +                               "BMC_GPIOY4_R","BMC_GPIOY5_R","","",
> +       /*Z0-Z7*/       "","","","","","","BMC_GPIOZ6_R","BMC_GPIOZ7_R";
> +};
> +
> +&gpio1 {
> +       gpio-line-names =
> +       /*18A0-18A7*/   "","","","","","","","",
> +       /*18B0-18B7*/   "","","","","FM_BOARD_BMC_REV_ID0","FM_BOARD_BMC_REV_ID1",
> +                       "FM_BOARD_BMC_REV_ID2","",
> +       /*18C0-18C7*/   "","","SPI_BMC_BIOS_ROM_IRQ0_R_N","","","","","",
> +       /*18D0-18D7*/   "","","","","","","","",
> +       /*18E0-18E3*/   "FM_BMC_PROT_LS_EN","AC_PWR_BMC_BTN_R_N","","";
> +};
> +
> +/* Rainiera6 SoC SSIF */
> +&i2c1 {
> +       status = "okay";
> +
> +       ssif_bmc: ssif-bmc@10 {
> +               compatible = "ssif-bmc";
> +               reg = <0x10>;
> +               status = "okay";
> +       };
> +};
> +
> +/* MCIO 2A I2C */
> +&i2c2 {
> +       status = "okay";
> +};
> +
> +&i2c4 {
> +       multi-master;
> +       mctp-controller;
> +       clock-frequency = <400000>;
> +       status = "okay";
> +
> +       mctp@10 {
> +               compatible = "mctp-i2c-controller";
> +               reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
> +       };
> +
> +       /* OCP NIC TEMP */
> +       temperature-sensor@1f {
> +               compatible = "ti,tmp421";
> +               reg = <0x1f>;
> +       };
> +
> +       /* OCP NIC FRU EEPROM */
> +       eeprom@50 {
> +               compatible = "atmel,24c64";
> +               reg = <0x50>;
> +       };
> +};
> +
> +&i2c5 {
> +       status = "okay";
> +
> +       gpio-expander@22 {
> +               compatible = "nxp,pca9535";
> +               reg = <0x22>;
> +               gpio-controller;
> +               #gpio-cells = <2>;
> +               gpio-line-names =
> +                       "JTAG_BMC_IOEXP_MUX_OE", "JTAG_BMC_MCIO_MUX_S1",
> +                       "JTAG_BMC_MCIO_MUX_S0", "JTAG_IOEXP_BMC_MUX_SEL",
> +                       "FM_USB_MUX_1_OE_N", "FM_USB_MUX_2_OE_N",
> +                       "PROGRAMN_CPLD", "",
> +                       "", "",
> +                       "", "",
> +                       "", "",
> +                       "", "";
> +       };
> +
> +       /* I2C MUX for MCIO 1A */
> +       i2c-mux@70 {
> +               compatible = "nxp,pca9546";
> +               reg = <0x70>;
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               i2c-mux-idle-disconnect;
> +
> +               i2c5mux0ch0: i2c@0 {
> +                       reg = <0>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +
> +               i2c5mux0ch1: i2c@1 {
> +                       reg = <1>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +       };
> +
> +       /* I2C MUX for MCIO 0A */
> +       i2c-mux@77 {
> +               compatible = "nxp,pca9546";
> +               reg = <0x77>;
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               i2c-mux-idle-disconnect;
> +
> +               i2c5mux1ch0: i2c@0 {
> +                       reg = <0>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +
> +               i2c5mux1ch1: i2c@1 {
> +                       reg = <1>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +       };
> +};
> +
> +&i2c6 {
> +       status = "okay";
> +
> +       /* I2C MUX for PWRPIC #13 ~ #16 */
> +       i2c-mux@77 {
> +               compatible = "nxp,pca9546";
> +               reg = <0x77>;
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               i2c-mux-idle-disconnect;
> +
> +               /* PWRPIC #13 */
> +               i2c6mux0ch0: i2c@0 {
> +                       reg = <0>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +
> +               /* PWRPIC #14 */
> +               i2c6mux0ch1: i2c@1 {
> +                       reg = <1>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +
> +               /* PWRPIC #16 */
> +               i2c6mux0ch2: i2c@2 {
> +                       reg = <2>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +
> +               /* PWRPIC #15 */
> +               i2c6mux0ch3: i2c@3 {
> +                       reg = <3>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +       };
> +};
> +
> +&i2c7 {
> +       multi-master;
> +       status = "okay";
> +
> +       ipmb@10 {
> +               compatible = "ipmb-dev";
> +               reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
> +               i2c-protocol;
> +       };
> +};
> +
> +&i2c8 {
> +       status = "okay";
> +
> +       power-monitor@14 {
> +               compatible = "infineon,xdp710";
> +               reg = <0x14>;
> +       };
> +
> +       adc@1d {
> +               compatible = "ti,adc128d818";
> +               reg = <0x1d>;
> +               ti,mode = /bits/ 8 <1>;
> +       };
> +
> +       /* PDB IOEXP0 */
> +       pdb_io_expander0: gpio-expander@24 {
> +               compatible = "nxp,pca9555";
> +               reg = <0x24>;
> +               interrupt-parent = <&sgpiom0>;
> +               interrupts = <92 IRQ_TYPE_LEVEL_LOW>;
> +               interrupt-controller;
> +               #interrupt-cells = <2>;
> +               gpio-controller;
> +               #gpio-cells = <2>;
> +               gpio-line-names =
> +                       "FM_P52V_AUX_FLT_N","FM_P12V_AUX_ALERT_N",
> +                       "FM_SLOT1_HSC_FAULT","FM_SLOT2_HSC_FAULT",
> +                       "FM_SLOT3_HSC_FAULT","FM_SLOT4_HSC_FAULT",
> +                       "FM_SLOT5_HSC_FAULT","FM_SLOT6_HSC_FAULT",
> +                       "PRSNT_FAN0","PRSNT_FAN1",
> +                       "PRSNT_FAN2","PRSNT_FAN3",
> +                       "","",
> +                       "","INT_SLOT";
> +       };
> +
> +       /* PDB IOEXP1 */
> +       gpio-expander@25 {
> +               compatible = "nxp,pca9555";
> +               reg = <0x25>;
> +               interrupt-parent = <&pdb_io_expander0>;
> +               interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
> +               gpio-controller;
> +               #gpio-cells = <2>;
> +               gpio-line-names =
> +                       "SLOT1_CM_UPDATE","SLOT2_CM_UPDATE",
> +                       "SLOT3_CM_UPDATE","SLOT4_CM_UPDATE",
> +                       "SLOT5_CM_UPDATE","SLOT6_CM_UPDATE",
> +                       "","",
> +                       "","",
> +                       "","",
> +                       "","",
> +                       "","";
> +       };
> +
> +       power-sensor@40 {
> +               compatible = "ti,ina238";
> +               reg = <0x40>;
> +               shunt-resistor = <1000>;
> +       };
> +
> +       /* PADDLE BD IOEXP */
> +       gpio-expander@41 {
> +               compatible = "nxp,pca9536";
> +               reg = <0x41>;
> +               gpio-controller;
> +               #gpio-cells = <2>;
> +               gpio-line-names =
> +                       "HSC_OC_GPIO0", "HSC_OC_GPIO1",
> +                       "HSC_OC_GPIO2", "HSC_OC_GPIO3";
> +       };
> +
> +       power-sensor@42 {
> +               compatible = "ti,ina238";
> +               reg = <0x42>;
> +               shunt-resistor = <1000>;
> +       };
> +
> +       power-monitor@43 {
> +               compatible = "lltc,ltc4287";
> +               reg = <0x43>;
> +               shunt-resistor-micro-ohms = <100>;
> +       };
> +
> +       power-sensor@44 {
> +               compatible = "ti,ina238";
> +               reg = <0x44>;
> +               shunt-resistor = <1000>;
> +       };
> +
> +       power-sensor@45 {
> +               compatible = "ti,ina238";
> +               reg = <0x45>;
> +               shunt-resistor = <1000>;
> +       };
> +
> +       power-monitor@46 {
> +               compatible = "mps,mp5998";
> +               reg = <0x46>;
> +       };
> +
> +       power-monitor@47 {
> +               compatible = "ti,tps25990";
> +               reg = <0x47>;
> +               ti,rimon-micro-ohms = <430000000>;
> +       };
> +
> +       temperature-sensor@48 {
> +               compatible = "ti,tmp75";
> +               reg = <0x48>;
> +       };
> +
> +       temperature-sensor@49 {
> +               compatible = "ti,tmp75";
> +               reg = <0x49>;
> +       };
> +
> +       /* PDB FRU */
> +       eeprom@56 {
> +               compatible = "atmel,24c128";
> +               reg = <0x56>;
> +       };
> +
> +       /* Paddle BD FRU */
> +       eeprom@57 {
> +               compatible = "atmel,24c128";
> +               reg = <0x57>;
> +       };
> +
> +       power-monitor@58 {
> +               compatible = "renesas,isl28022";
> +               reg = <0x58>;
> +               shunt-resistor-micro-ohms = <10000>;
> +       };
> +
> +       power-monitor@59 {
> +               compatible = "renesas,isl28022";
> +               reg = <0x59>;
> +               shunt-resistor-micro-ohms = <10000>;
> +       };
> +
> +       power-monitor@5a {
> +               compatible = "renesas,isl28022";
> +               reg = <0x5a>;
> +               shunt-resistor-micro-ohms = <10000>;
> +       };
> +
> +       power-monitor@5b {
> +               compatible = "renesas,isl28022";
> +               reg = <0x5b>;
> +               shunt-resistor-micro-ohms = <10000>;
> +       };
> +
> +       psu@5c {
> +               compatible = "renesas,raa228006";
> +               reg = <0x5c>;
> +       };
> +
> +       fan-controller@5e{
> +               compatible = "maxim,max31790";
> +               reg = <0x5e>;
> +       };
> +
> +       /* I2C MUX for PWRPIC #1, #2, #11, #12 */
> +       i2c-mux@77 {
> +               compatible = "nxp,pca9546";
> +               reg = <0x77>;
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               i2c-mux-idle-disconnect;
> +
> +               /* PWRPIC #1 */
> +               i2c8mux0ch0: i2c@0 {
> +                       reg = <0>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +
> +               /* PWRPIC #2 */
> +               i2c8mux0ch1: i2c@1 {
> +                       reg = <1>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +
> +               /* PWRPIC #12 (Connector to CXL BD) */
> +               i2c8mux0ch2: i2c@2 {
> +                       reg = <2>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +                       i2c-mux@70 {
> +                               compatible = "nxp,pca9546";
> +                               reg = <0x70>;
> +                               #address-cells = <1>;
> +                               #size-cells = <0>;
> +                               i2c-mux-idle-disconnect;
> +                               i2c26mux0ch0: i2c@0 {
> +                                       reg = <0>;
> +                                       #address-cells = <1>;
> +                                       #size-cells = <0>;
> +                               };
> +                               i2c26mux0ch1: i2c@1 {
> +                                       reg = <1>;
> +                                       #address-cells = <1>;
> +                                       #size-cells = <0>;
> +                               };
> +                               i2c26mux0ch2: i2c@2 {
> +                                       reg = <2>;
> +                                       #address-cells = <1>;
> +                                       #size-cells = <0>;
> +                                       /* CXL FRU */
> +                                       eeprom@50 {
> +                                               compatible = "atmel,24c64";
> +                                               reg = <0x50>;
> +                                       };
> +                               };
> +                               i2c26mux0ch3: i2c@3 {
> +                                       reg = <3>;
> +                                       #address-cells = <1>;
> +                                       #size-cells = <0>;
> +                               };
> +                       };
> +               };
> +
> +               /* PWRPIC #11 */
> +               i2c8mux0ch3: i2c@3 {
> +                       reg = <3>;
> +                       #address-cells = <1>;
> +                       #size-cells = <0>;
> +               };
> +       };
> +};
> +
> +&i2c9 {
> +       status = "okay";
> +
> +       temperature-sensor@4b {
> +               compatible = "ti,tmp75";
> +               reg = <0x4b>;
> +       };
> +
> +       /* SCM FRU */
> +       eeprom@51 {
> +               compatible = "atmel,24c128";
> +               reg = <0x51>;
> +       };
> +
> +       /* BSM FRU */
> +       eeprom@56 {
> +               compatible = "atmel,24c64";
> +               reg = <0x56>;
> +       };
> +};
> +
> +/* MCIO 0A I2C */
> +&i2c10 {
> +       status = "okay";
> +};
> +
> +&i2c11 {
> +       status = "okay";
> +
> +       /* I2C11_IOEXP_3 */
> +       gpio-expander@20 {
> +               compatible = "nxp,pca9535";
> +               reg = <0x20>;
> +               gpio-controller;
> +               #gpio-cells = <2>;
> +               gpio-line-names =
> +                       "IRQ_INA230_FAN0_ALERT_N_CPLD", "IRQ_INA230_FAN1_ALERT_N_CPLD",
> +                       "IRQ_INA230_FAN2_ALERT_N_CPLD", "IRQ_INA230_FAN3_ALERT_N_CPLD",
> +                       "IRQ_INA230_P12V_DIMM_0_ALERT_N", "IRQ_INA230_P12V_DIMM_1_ALERT_N",
> +                       "IRQ_P3V3_E1S_0_FLT_N", "P12V_E1S_0_FAULT_R_N",
> +                       "IRQ_P3V3_E1S_1_FLT_N", "P12V_E1S_1_FAULT_R_N",
> +                       "IRQ_P3V3_NIC_FLT_N", "P12V_NIC_FAULT_R_N",
> +                       "SMB_SENSOR_ALERT_N", "FW_CPLD_RST_RTC_RST_R1",
> +                       "RTC_CLR", "RTC_U11_ALRT_N";
> +       };
> +
> +       /* I2C11_IOEXP_2 */
> +       gpio-expander@21 {
> +               compatible = "nxp,pca9535";
> +               reg = <0x21>;
> +               gpio-controller;
> +               #gpio-cells = <2>;
> +               gpio-line-names =
> +                       "FAN_0_PRESENT_CPLD", "FAN_1_PRESENT_CPLD",
> +                       "FAN_2_PRESENT_CPLD", "FAN_3_PRESENT_CPLD",
> +                       "FAN_FAIL_L_CPLD", "FULL_SPEED_N_R_CPLD",
> +                       "P12V_FAN0_PWRGD_CPLD", "P12V_FAN1_PWRGD_CPLD",
> +                       "P12V_FAN2_PWRGD_CPLD", "P12V_FAN3_PWRGD_CPLD",
> +                       "FM_P12V_FAN0_FLTB_N_CPLD", "FM_P12V_FAN1_FLTB_N_CPLD",
> +                       "FM_P12V_FAN2_FLTB_N_CPLD", "FM_P12V_FAN3_FLTB_N_CPLD",
> +                       "P12V_FAN_EN_R_CPLD", "";
> +       };
> +
> +       /* I2C11_IOEXP_1 */
> +       gpio-expander@27 {
> +               compatible = "nxp,pca9535";
> +               reg = <0x27>;
> +               gpio-controller;
> +               #gpio-cells = <2>;
> +               gpio-line-names =
> +                       "PWRGD_P12V_SCM", "PWRGD_P5V_STBY",
> +                       "PWRGD_P3V3_STBY", "PWRGD_P1V8_STBY",
> +                       "PWRGD_P1V2_STBY", "PWRGD_P1V1_STBY",
> +                       "PWRGD_P1V0_STBY", "",
> +                       "", "",
> +                       "", "",
> +                       "", "",
> +                       "", "";
> +       };
> +
> +       power-sensor@40 {
> +               compatible = "ti,ina230";
> +               reg = <0x40>;
> +               shunt-resistor = <1000>;
> +       };
> +
> +       power-sensor@41 {
> +               compatible = "ti,ina230";
> +               reg = <0x41>;
> +               shunt-resistor = <1000>;
> +       };
> +
> +       power-sensor@42 {
> +               compatible = "ti,ina230";
> +               reg = <0x42>;
> +               shunt-resistor = <2000>;
> +       };
> +
> +       power-sensor@43 {
> +               compatible = "ti,ina230";
> +               reg = <0x43>;
> +               shunt-resistor = <2000>;
> +       };
> +
> +       power-sensor@44 {
> +               compatible = "ti,ina230";
> +               reg = <0x44>;
> +               shunt-resistor = <2000>;
> +       };
> +
> +       power-sensor@45 {
> +               compatible = "ti,ina230";
> +               reg = <0x45>;
> +               shunt-resistor = <2000>;
> +       };
> +
> +       adc@49 {
> +               compatible = "ti,ads7830";
> +               reg = <0x49>;
> +       };
> +
> +       adc@4a {
> +               compatible = "ti,ads7830";
> +               reg = <0x4a>;
> +       };
> +
> +       adc@4b {
> +               compatible = "ti,ads7830";
> +               reg = <0x4b>;
> +       };
> +       rtc@6f {
> +               compatible = "nuvoton,nct3018y";
> +               reg = <0x6f>;
> +               status = "okay";
> +       };
> +};
> +
> +/* MCIO 4A I2C */
> +&i2c12 {
> +       multi-master;
> +       mctp-controller;
> +       clock-frequency = <400000>;
> +       status = "okay";
> +
> +       mctp@10 {
> +               compatible = "mctp-i2c-controller";
> +               reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
> +       };
> +};
> +
> +&i2c13 {
> +       status = "okay";
> +
> +       fan-controller@20 {
> +               compatible = "maxim,max31790";
> +               reg = <0x20>;
> +       };
> +
> +       power-sensor@40 {
> +               compatible = "ti,ina230";
> +               reg = <0x40>;
> +               shunt-resistor = <2000>;
> +       };
> +
> +       power-sensor@41 {
> +               compatible = "ti,ina230";
> +               reg = <0x41>;
> +               shunt-resistor = <2000>;
> +       };
> +
> +       power-sensor@44 {
> +               compatible = "ti,ina230";
> +               reg = <0x44>;
> +               shunt-resistor = <2000>;
> +       };
> +
> +       power-sensor@45 {
> +               compatible = "ti,ina230";
> +               reg = <0x45>;
> +               shunt-resistor = <2000>;
> +       };
> +
> +       temperature-sensor@48 {
> +               compatible = "national,lm75b";
> +               reg = <0x48>;
> +       };
> +
> +       temperature-sensor@49 {
> +               compatible = "national,lm75b";
> +               reg = <0x49>;
> +       };
> +
> +       /* MB FRU */
> +       eeprom@51 {
> +               compatible = "atmel,24c128";
> +               reg = <0x51>;
> +       };
> +};
> +
> +/* PROT reserve */
> +&i2c14 {
> +       status = "okay";
> +};
> +
> +/* MCIO 3A I2C */
> +&i2c15 {
> +       status = "okay";
> +};
> +
> +&mac2 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&pinctrl_ncsi3_default>;
> +       use-ncsi;
> +       status = "okay";
> +};
> +
> +&pinctrl {
> +       pinctrl_ncsi3_default: ncsi3_default {
> +               function = "RMII3";
> +               groups = "NCSI3";
> +       };
> +};
> +
> +&sgpiom0 {
> +       status = "okay";
> +       ngpios = <128>;
> +       bus-frequency = <2000000>;
> +       gpio-line-names =
> +       /*"input pin","output pin"*/
> +       "SOC_ERROR_N_CPLD","RST_SOC_SRST_N_CPLD",
> +       "SOC_ELASTOPCLK_N","SOC_BMC_READY_CPLD",
> +       "SOC_LINKSTOP_N","wIBB_BMC_SRST_OUT",
> +       "SOC_POST_COMPLETE_CPLD","I3C_MUX_SEL_DIMM_C0_024",
> +       "SOC_RESETREQ","I3C_MUX_SEL_DIMM_C0_135",
> +       "SOC_SYS_PWRDN_CPLD","I3C_MUX_SEL_DIMM_C1_024",
> +       "SOC_PORQ","I3C_MUX_SEL_DIMM_C1_135",
> +       "SOC_HOT_N_CPLD","BOOT_PWRDIS_CPLD",
> +       // IOB0-IOB7 bit8-15
> +       "PWRGD_V1P8_CPU","HDD0_PERST_N_CPLD",
> +       "PWRGD_V1P26_CPLD","HDD1_PERST_N_CPLD",
> +       "PWRGD_V1P2","MCIO_1A_PWRDIS_R",
> +       "","",
> +       "FM_CONFIG_ID","P3V_BAT_SCALED_EN",
> +       "wALL_POWER_OK","PERST_CEM0_N_CPLD",
> +       "wANDGATE_ALL_POWER_GD","PERST_CEM1_N_CPLD",
> +       "wAC_CYCLE_12V","PERST_PLD_TUSB7340_N",
> +       // IOC0-IOC7 bit16-23
> +       "wAC_CYCLE_54V","FM_USB_MUX_SEL_CPLD",
> +       "FM_PLD_CLKS_DEV_EN","SMB_BOOT_RST_N_CPLD",
> +       "PWRGD_P1V2_STBY","SMB_MCIO_0A_RST_R_N",
> +       "wIBB_BMC_SRST","RST_SMB_NIC_R_N",
> +       "PWRGD_P12V_E1S_0","FM_PPS_NIC_IN_BUF_OE_N_R",
> +       "PWRGD_P12V_E1S_1","FM_BUF_PPS_NIC_IN_EN_CPLD",
> +       "","FM_NIC_PPS_IN_OE_CPLD",
> +       "PWRGD_P12V_NIC","FM_PPS_NIC_IN_S0_CPLD",
> +       // IOD0-IOD7 bit24-31
> +       "wALL_POWER_OK_1","FM_NIC_PPS_IN_S1",
> +       "wALL_POWER_OK_2","FM_PPS_NIC_OUT_CPU_OE_N",
> +       "PWRGD_EAST_DIMM_CPLD","",
> +       "PWRGD_WEST_DIMM_CPLD","FM_BUF_PPS_NIC_OUT_EN_CPLD",
> +       "PWRGD_NIC_CPLD","",
> +       "","PMBUS_MUX_SEL_C0",
> +       "PHOENIX_PWRBTN_N_CPLD","PMBUS_MUX_SEL_C1",
> +       "IRQ_INA230_E1S_0_ALERT_N","",
> +       // IOE0-IOE7 bit32-39
> +       "IRQ_INA230_E1S_1_ALERT_N","PWR_ON_RST_TUSB7340_CPLD",
> +       "","RST_PCIE_BOOT_PERST_N_CPLD",
> +       "FM_NIC_WAKE_N_CPLD","RST_PCIE_CPLD_NIC_N_CPLD",
> +       "FM_TPM_CONN_PRSNT_N","RST_PCIE_MCIO_0A_PERST_N_CPLD",
> +       "HDD0_PRSNT_N_CPLD","RST_PCIE_MCIO_0B_PERST_N_CPLD",
> +       "IRQ_INA230_P12V_NIC_ALERT_N","RST_PCIE_MCIO_1A_PERST_N_CPLD",
> +       "IRQ_INA230_P12V_SCM_ALERT_N","RST_PCIE_MCIO_1A_SA_PERST_N_CPL",
> +       "IRQ_PMBUS_ALERT_PWR11_R_N","RST_PCIE_MCIO_1B_PERST_N_CPLD",
> +       // IOF0-IOF7 bit40-47
> +       "CHASSIS_LEAK_2A_R_N","RST_PCIE_MCIO_2A_PERST_N_CPLD",
> +       "CHASSIS_LEAK_3A_R_N","RST_PCIE_MCIO_2B_PERST_N_CPLD",
> +       "CHASSIS_LEAK_4A_R_N","RST_PCIE_MCIO_3A_PERST_N_CPLD",
> +       "OC_ALERT_PADDLE_R_N","RST_PCIE_MCIO_3B_PERST_N_CPLD",
> +       "OC_ALERT_PWR2_R_N","RST_PCIE_MCIO_4A_PERST_N_CPLD",
> +       "OC_ALERT_PWR11_R_N","RST_PCIE_MCIO_4B_PERST_N_CPLD",
> +       "FM_IOE_ALT_N","RST_PERST1_N_CPLD",
> +       "LEAK_DETECT_1_PWR14_R_N","RST_PERST2_N_CPLD",
> +       // IOG0-IOG7 bit48-55
> +       "LEAK_DETECT_2_PWR14_R_N","RST_PERST3_N_CPLD",
> +       "LEAK_DETECT_1_PWR15_R_N","RST_SMB_MUX_MCIO_0A_R_N",
> +       "LEAK_DETECT_2_PWR15_R_N","RST_SMB_MUX_MCIO_1A_R_N",
> +       "MCIO_0A_SMB_ALERT_N","RST_SOC_EXTWARMRESET_CPLD",
> +       "MCIO_1A_SMB_ALERT_N","RST_SOC_PORESET_N_BMC",
> +       "MCIO_2A_SMB_ALERT_N","RST_USB_HUB_R_N",
> +       "MCIO_2B_SMB_ALERT_N","SMB_MM7_MUX_RESET_N",
> +       "MCIO_3A_SMB_ALERT_N","SMB_MUX_RESET_N_CPLD",
> +       // IOH0-IOH7 bit56-63
> +       "MCIO_3B_SMB_ALERT_N","SOC_I2C_0_ALERT_CPLD",
> +       "MCIO_4A_SMB_ALERT_N","SOC_LINKSTOP_OUT_N",
> +       "MCIO_4B_SMB_ALERT_N","SPI_TPM_RST_R_N",
> +       "MCIO_1A_THERMTRIP_N","",
> +       "MCIO_2A_THERMTRIP_N","",
> +       "MCIO_3A_THERMTRIP_N","",
> +       "MCIO_4A_THERMTRIP_N_CPLD","",
> +       "UV_ALERT_PADDLE_R_N","wFM_USB_MUX_OE_N",
> +       // IOI0-IOI7 bit64-71
> +       "UV_ALERT_PWR2_R_N","wFM_USB_MUX_SEL",
> +       "UV_ALERT_PWR11_R_N","",
> +       "SOC_PMBUS_0_ALERT_R_CPLD","FM_BIOS_DEBUG_MODE_N",
> +       "HDD1_PRSNT_N_CPLD","",
> +       "","",
> +       "SOC_DRAM_0_HOT_N_CPLD","",
> +       "SOC_DRAM_1_HOT_N_CPLD","RST_PLTRST_PLD_B_N",
> +       "SOC_DRAM_2_HOT_N_CPLD","FM_TPM_MUX6_SEL",
> +       // IOJ0-IOJ7 bit72-79
> +       "SOC_DRAM_3_HOT_N_CPLD","CPLD_MUX6_EN_N",
> +       "IRQ_P3V3_NIC_FLT_MOS_N_CPLD","",
> +       "VRHOT_V0P75_PCIE_VDDQ_N","",
> +       "P12V_SCM_FAULT_R_N","",
> +       "SOC_I2C_1_ALERT_CPLD","",
> +       "","",
> +       "SOC_PLATHOT_N_CPLD","",
> +       "SOC_THRMTRIP_N_CPLD","",
> +       // IOK0-IOK7 bit80-87
> +       "VRHOT_VCPUC1_VCPUMC1_N","",
> +       "VRHOT_VSYSC0_VSOCC0_N","",
> +       "VRHOT_VSYSC1_VSOCC1_N","",
> +       "VRHOT_VCPUC0_VCPUMC0_N","",
> +       "","",
> +       "INT_IOEXP_N","",
> +       "RSVD_IOEXP_0A_SB1_R","",
> +       "RSVD_IOEXP_0A_SB2_R","",
> +       // IOL0-IOL7 bit88-95
> +       "IRQ_PMBUS_PWR2_ALERT_R_N","",
> +       "FM_BORD_REV_ID0","",
> +       "FM_BORD_REV_ID1","",
> +       "FM_BORD_REV_ID2","",
> +       "FM_VR_TYPE_0","",
> +       "FM_VR_TYPE_1","",
> +       "","",
> +       "MCIO_0B_SMB_ALERT_N","",
> +       // IOM0-IOM7 bit96-103
> +       "MCIO_1B_SMB_ALERT_N","",
> +       "PRSNT_BOOT_N","",
> +       "PRSNT_MCIO_1A_N","",
> +       "wPRSNT_NIC_N","",
> +       "","",
> +       "SOC_TEST_MODE0","",
> +       "PWRGD_V0P75_PCIE","",
> +       "PWRGD_VDDQ","",
> +       // ION0-ION7 bit104-111
> +       "PWRGD_VCPUC0","",
> +       "PWRGD_VCPUMC0","",
> +       "PWRGD_VCPUMC1","",
> +       "PWRGD_VCPUC1","",
> +       "PWRGD_VSYSC0","",
> +       "PWRGD_VSOCC0","",
> +       "PWRGD_VSYSC1","",
> +       "PWRGD_VSOCC1","",
> +       // IOO0-IOO7 bit112-119
> +       "SOC_PMBUS_1_ALERT_R_CPLD","",
> +       "SOC_GPIO_15","",
> +       "C0_POSTCODE_0_CPLD","",
> +       "C0_POSTCODE_1_CPLD","",
> +       "C0_POSTCODE_2_CPLD","",
> +       "C0_POSTCODE_3_CPLD","",
> +       "C0_POSTCODE_4_CPLD","",
> +       "C1_POSTCODE_0_CPLD","",
> +       // IOP0-IOP7 bit 120-127
> +       "C1_POSTCODE_1_CPLD","",
> +       "C1_POSTCODE_2_CPLD","",
> +       "C1_POSTCODE_3_CPLD","",
> +       "C1_POSTCODE_4_CPLD","",
> +       "","",
> +       "SOC_GPIO_17","",
> +       "SOC_GPIO_18","",
> +       "SOC_GPIO_37","";
> +};
> +
> +/* BIOS Flash */
> +&spi2 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&pinctrl_spi2_default>;
> +       status = "okay";
> +
> +       flash@0 {
> +               m25p,fast-read;
> +               label = "pnor";
> +               spi-max-frequency = <12000000>;
> +               spi-tx-bus-width = <2>;
> +               spi-rx-bus-width = <2>;
> +               status = "okay";
> +       };
> +};
> +
> +&uart1 {
> +       status = "okay";
> +};
> +
> +&uart2 {
> +       status = "okay";
> +};
> +
> +/* SOL */
> +&uart3 {
> +       status = "okay";
> +};
> +
> +&uart4 {
> +       status = "okay";
> +};
> +
> +/* BMC Console */
> +&uart5 {
> +       status = "okay";
> +};
> +
> +&wdt1 {
> +       pinctrl-names = "default";
> +       pinctrl-0 = <&pinctrl_wdtrst1_default>;
> +       aspeed,reset-type = "soc";
> +       aspeed,external-signal;
> +       aspeed,ext-push-pull;
> +       aspeed,ext-active-high;
> +       aspeed,ext-pulse-duration = <256>;
> +       status = "okay";
> +};
> --
> 2.25.1
> 



^ permalink raw reply

* Re: [PATCH v2 0/5] mm: reduce mmap_lock contention and improve page fault performance
From: Lorenzo Stoakes @ 2026-05-18  9:46 UTC (permalink / raw)
  To: Barry Song
  Cc: Matthew Wilcox, surenb, akpm, linux-mm, david, liam, vbabka, rppt,
	mhocko, jack, pfalcato, wanglian, chentao, lianux.mm, kunwu.chan,
	liyangouwen1, chrisl, kasong, shikemeng, nphamcs, bhe,
	youngjun.park, linux-arm-kernel, linux-kernel, loongarch,
	linuxppc-dev, linux-riscv, linux-s390, Nanzhe Zhao
In-Reply-To: <CAGsJ_4ysMcrmDLSOwBkf7qwCQrcDWeEMXkHDajTJFMLKUk0bSQ@mail.gmail.com>

On Sun, May 17, 2026 at 04:45:15PM +0800, Barry Song wrote:
> On Sat, May 2, 2026 at 1:58 AM Matthew Wilcox <willy@infradead.org> wrote:
> >
> > On Sat, May 02, 2026 at 01:44:34AM +0800, Barry Song wrote:
> > > On Fri, May 1, 2026 at 10:57 PM Matthew Wilcox <willy@infradead.org> wrote:
> > > >
> > > > On Fri, May 01, 2026 at 06:49:58AM +0800, Barry Song wrote:
> > > > > 1. There is no deterministic latency for I/O completion. It depends on
> > > > > both the hardware and the software stack (bio/request queues and the
> > > > > block scheduler). Sometimes the latency is short; at other times it can
> > > > > be quite long. In such cases, a high-priority thread performing operations
> > > > > such as mprotect, unmap, prctl_set_vma, or madvise may be forced to wait
> > > > > for an unpredictable amount of time.
> > > >
> > > > But does that actually happen?  I find it hard to believe that thread A
> > > > unmaps a VMA while thread B is in the middle of taking a page fault in
> > > > that same VMA.  mprotect() and madvise() are more likely to happen, but
> > > > it still seems really unlikely to me.
> > >
> > > It doesn’t have to involve unmapping or applying mprotect to
> > > the entire VMA—just a portion of it is sufficient.
> >
> > Yes, but that still fails to answer "does this actually happen".  How much
> > performance is all this complexity in the page fault handler buying us?
> > If you don't answer this question, I'm just going to go in and rip it
> > all out.
> >
>
> Hi Matthew (and Lorenzo, Jan, and anyone else who may be
> waiting for answers),
>
> As promised during LSF/MM/BPF, we conducted thorough
> testing on Android phones to determine whether performing
> I/O in `filemap_fault()` can block `vma_start_write()`.
> I wanted to give a quick update on this question.
>
> Nanzhe at Xiaomi created tracing scripts and ran various
> applications on Android devices with I/O performed under
> the VMA lock in `filemap_fault()`. We found that:
>
> 1. There are very few cases where unmap() is blocked by
>    page faults. I assume this is due to buggy user code
>    or poor synchronization between reads and unmap().
> So I assume it is not a problem.
>
> 2. We observed many cases where `vma_start_write()`
>    is blocked by page-fault I/O in some applications.
>    The blocking occurs in the `dup_mmap()` path during
>    fork().
>
> With Suren's commit fb49c455323ff ("fork: lock VMAs of
> the parent process when forking"), we now always hold
> `vma_write_lock()` for each VMA. Note that the
> `mmap_lock` write lock is also held, which could lead to
> chained waiting if page-fault I/O is performed without
> releasing the VMA lock.

Hm but did you observe this 'chained waiting'? And what were the latencies?

>
> My gut feeling is that Suren's commit may be overshooting,
> so my rough idea is that we might want to do something like
> the following (we haven't tested it yet and it might be
> wrong):

Yeah I'm really not sure about that.

Prior to the VMA locks, the mmap write lock would have guaranteed no concurrent
page faults, which is really what fb49c455323ff is about.

So Suren's patch was essentially restoring the _existing_ forking behaviour, and
now you're saying 'let's change the forking behaviour that's been like that for
forever'.

I think you would _really_ have to be sure that's safe. And forking is a very
dangerous time in terms of complexity and sensitivity and 'weird stuff'
happening so I'd tread _very_ carefully here.

>
> diff --git a/mm/mmap.c b/mm/mmap.c
> index 2311ae7c2ff4..5ddaf297f31a 100644
> --- a/mm/mmap.c
> +++ b/mm/mmap.c
> @@ -1762,7 +1762,13 @@ __latent_entropy int dup_mmap(struct mm_struct
> *mm, struct mm_struct *oldmm)
>         for_each_vma(vmi, mpnt) {
>                 struct file *file;
>
> -               retval = vma_start_write_killable(mpnt);
> +               /*
> +                * For anonymous or writable private VMAs, prevent
> +                * concurrent CoW faults.
> +                */

To nit pick I think the comment's confusing but also tells you you don't need to
specific anon check - writable private is sufficient. And it's not really just
CoW that's the issue, it's anon_vma population _at all_ as well as CoW.

> +               if (!mpnt->vm_file || (!(mpnt->vm_flags & VM_SHARED) &&
> +                                       (mpnt->vm_flags & VM_WRITE)))
> +                       retval = vma_start_write_killable(mpnt);

I think this has to be VM_MAYWRITE, because somebody could otherwise mprotect()
it R/W.

I also don't understand why !mpnt->vm_file for a read-only anon mapping (more
likely PROT_NONE) is here, just do the second check?

(Also please use the new interface, so !vma_test(mpnt, VMA_SHARED_BIT) &&
vma_test(mpnt, VMA_MAYWRITE_BIT))

>                 if (retval < 0)
>                         goto loop_out;
>                 if (mpnt->vm_flags & VM_DONTCOPY) {
>
> Based on the above, we may want to re-check whether fork()
> can be blocked by page faults. At the same time, if Suren,
> you, or anyone else has any comments, please feel free to
> share them.
>
> Best Regards
> Barry

Technical commentary above is sort of 'just cos' :) because I really question
doing this honestly.

I'd also like to get Suren's input, however.

Thanks, Lorenzo


^ permalink raw reply

* Re: [PATCH v2 0/5] mm: reduce mmap_lock contention and improve page fault performance
From: David Hildenbrand (Arm) @ 2026-05-18  9:53 UTC (permalink / raw)
  To: Barry Song, Matthew Wilcox, surenb
  Cc: akpm, linux-mm, ljs, liam, vbabka, rppt, mhocko, jack, pfalcato,
	wanglian, chentao, lianux.mm, kunwu.chan, liyangouwen1, chrisl,
	kasong, shikemeng, nphamcs, bhe, youngjun.park, linux-arm-kernel,
	linux-kernel, loongarch, linuxppc-dev, linux-riscv, linux-s390,
	Nanzhe Zhao
In-Reply-To: <CAGsJ_4ysMcrmDLSOwBkf7qwCQrcDWeEMXkHDajTJFMLKUk0bSQ@mail.gmail.com>

On 5/17/26 10:45, Barry Song wrote:
> On Sat, May 2, 2026 at 1:58 AM Matthew Wilcox <willy@infradead.org> wrote:
>>
>> On Sat, May 02, 2026 at 01:44:34AM +0800, Barry Song wrote:
>>>
>>> It doesn’t have to involve unmapping or applying mprotect to
>>> the entire VMA—just a portion of it is sufficient.
>>
>> Yes, but that still fails to answer "does this actually happen".  How much
>> performance is all this complexity in the page fault handler buying us?
>> If you don't answer this question, I'm just going to go in and rip it
>> all out.
>>
> 
> Hi Matthew (and Lorenzo, Jan, and anyone else who may be
> waiting for answers),
> 
> As promised during LSF/MM/BPF, we conducted thorough
> testing on Android phones to determine whether performing
> I/O in `filemap_fault()` can block `vma_start_write()`.
> I wanted to give a quick update on this question.
> 
> Nanzhe at Xiaomi created tracing scripts and ran various
> applications on Android devices with I/O performed under
> the VMA lock in `filemap_fault()`. We found that:
> 
> 1. There are very few cases where unmap() is blocked by
>    page faults. I assume this is due to buggy user code
>    or poor synchronization between reads and unmap().
> So I assume it is not a problem.
> 
> 2. We observed many cases where `vma_start_write()`
>    is blocked by page-fault I/O in some applications.
>    The blocking occurs in the `dup_mmap()` path during
>    fork().
> 
> With Suren's commit fb49c455323ff ("fork: lock VMAs of
> the parent process when forking"), we now always hold
> `vma_write_lock()` for each VMA. Note that the
> `mmap_lock` write lock is also held, which could lead to
> chained waiting if page-fault I/O is performed without
> releasing the VMA lock.
> 
> My gut feeling is that Suren's commit may be overshooting,
> so my rough idea is that we might want to do something like
> the following (we haven't tested it yet and it might be
> wrong):
> 
> diff --git a/mm/mmap.c b/mm/mmap.c
> index 2311ae7c2ff4..5ddaf297f31a 100644
> --- a/mm/mmap.c
> +++ b/mm/mmap.c
> @@ -1762,7 +1762,13 @@ __latent_entropy int dup_mmap(struct mm_struct
> *mm, struct mm_struct *oldmm)
>         for_each_vma(vmi, mpnt) {
>                 struct file *file;
> 
> -               retval = vma_start_write_killable(mpnt);
> +               /*
> +                * For anonymous or writable private VMAs, prevent
> +                * concurrent CoW faults.
> +                */
> +               if (!mpnt->vm_file || (!(mpnt->vm_flags & VM_SHARED) &&
> +                                       (mpnt->vm_flags & VM_WRITE)))
> +                       retval = vma_start_write_killable(mpnt);

Likely is_cow_mapping() is what you would want to check to handle VMAs that
could have anonymous pages in them.

-- 
Cheers,

David


^ permalink raw reply

* [PATCH 0/2] spi: aspeed: Fix __iomem annotation and VLA parameter
From: Chin-Ting Kuo @ 2026-05-18  9:57 UTC (permalink / raw)
  To: clg, broonie, joel, andrew, linux-aspeed, openbmc, linux-spi,
	linux-arm-kernel, linux-kernel, BMC-SW

This series fixes two sparse warnings reported by the kernel test robot.
The first patch fixes missing __iomem annotation on an MMIO pointer
parameter, which also caused a redundant cast at the call site.
A VLA function parameter warning is also fixed in this patch series.

Chin-Ting Kuo (2):
  spi: aspeed: Fix missing __iomem annotation in output transfer path
  spi: aspeed: Fix sparse warnings for VLA parameter in calibration
    helper

 drivers/spi/spi-aspeed-smc.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

-- 
2.34.1



^ permalink raw reply

* [PATCH 1/2] spi: aspeed: Fix missing __iomem annotation in output transfer path
From: Chin-Ting Kuo @ 2026-05-18  9:57 UTC (permalink / raw)
  To: clg, broonie, joel, andrew, linux-aspeed, openbmc, linux-spi,
	linux-arm-kernel, linux-kernel, BMC-SW
  Cc: kernel test robot
In-Reply-To: <20260518095708.2502537-1-chin-ting_kuo@aspeedtech.com>

The dst parameter of aspeed_spi_user_transfer_tx() is an MMIO address
obtained from chip->ahb_base, but it was typed as void * instead of
void __iomem *.  This caused a sparse warning report. Fix the
parameter type to void __iomem * and drop the now-unnecessary
cast at the call site.

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202605180441.uD3toFRJ-lkp@intel.com/
Signed-off-by: Chin-Ting Kuo <chin-ting_kuo@aspeedtech.com>
---
 drivers/spi/spi-aspeed-smc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c
index c21323e07d3c..808659a1f460 100644
--- a/drivers/spi/spi-aspeed-smc.c
+++ b/drivers/spi/spi-aspeed-smc.c
@@ -891,7 +891,7 @@ static int aspeed_spi_user_unprepare_msg(struct spi_controller *ctlr,
 static void aspeed_spi_user_transfer_tx(struct aspeed_spi *aspi,
 					struct spi_device *spi,
 					const u8 *tx_buf, u8 *rx_buf,
-					void *dst, u32 len)
+					void __iomem *dst, u32 len)
 {
 	const struct aspeed_spi_data *data = aspi->data;
 	bool full_duplex_transfer = data->full_duplex && tx_buf == rx_buf;
@@ -936,7 +936,7 @@ static int aspeed_spi_user_transfer(struct spi_controller *ctlr,
 			aspeed_spi_set_io_mode(chip, CTRL_IO_QUAD_DATA);
 
 		aspeed_spi_user_transfer_tx(aspi, spi, tx_buf, rx_buf,
-					    (void *)ahb_base, xfer->len);
+					    ahb_base, xfer->len);
 	}
 
 	if (rx_buf && rx_buf != tx_buf) {
-- 
2.34.1



^ permalink raw reply related

* [PATCH] spi: aspeed: Replace VLA parameter with flat pointer in calibration helper
From: Chin-Ting Kuo @ 2026-05-18  9:57 UTC (permalink / raw)
  To: clg, broonie, joel, andrew, linux-aspeed, openbmc, linux-spi,
	linux-arm-kernel, linux-kernel, BMC-SW
  Cc: kernel test robot
In-Reply-To: <20260518095708.2502537-1-chin-ting_kuo@aspeedtech.com>

aspeed_spi_ast2600_optimized_timing() declared its buffer argument as a
variable-length array parameter (u8 buf[rows][cols]), which causes a
sparse warning. Replace the VLA parameter with a plain u8 * and compute
the 2-D index manually. The corresponding call site is also updated.

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202605180441.uD3toFRJ-lkp@intel.com/
Signed-off-by: Chin-Ting Kuo <chin-ting_kuo@aspeedtech.com>
---
 drivers/spi/spi-aspeed-smc.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c
index 808659a1f460..c5275700de3d 100644
--- a/drivers/spi/spi-aspeed-smc.c
+++ b/drivers/spi/spi-aspeed-smc.c
@@ -1467,8 +1467,7 @@ static int aspeed_spi_do_calibration(struct aspeed_spi_chip *chip)
  * must contains the highest number of consecutive "pass"
  * results and not span across multiple rows.
  */
-static u32 aspeed_spi_ast2600_optimized_timing(u32 rows, u32 cols,
-					       u8 buf[rows][cols])
+static u32 aspeed_spi_ast2600_optimized_timing(u32 rows, u32 cols, u8 *buf)
 {
 	int r = 0, c = 0;
 	int max = 0;
@@ -1478,7 +1477,7 @@ static u32 aspeed_spi_ast2600_optimized_timing(u32 rows, u32 cols,
 		for (j = 0; j < cols;) {
 			int k = j;
 
-			while (k < cols && buf[i][k])
+			while (k < cols && buf[i * cols + k])
 				k++;
 
 			if (k - j > max) {
@@ -1541,7 +1540,7 @@ static int aspeed_spi_ast2600_calibrate(struct aspeed_spi_chip *chip, u32 hdiv,
 		}
 	}
 
-	calib_point = aspeed_spi_ast2600_optimized_timing(6, 17, calib_res);
+	calib_point = aspeed_spi_ast2600_optimized_timing(6, 17, &calib_res[0][0]);
 	/* No good setting for this frequency */
 	if (calib_point == 0)
 		return -1;
-- 
2.34.1



^ permalink raw reply related

* Re: [PATCH 2/3] memory: mtk-smi: Add a flag skip_rpm
From: AngeloGioacchino Del Regno @ 2026-05-18 10:02 UTC (permalink / raw)
  To: Xueqi Zhang (张雪琦), robh@kernel.org,
	matthias.bgg@gmail.com, Yong Wu (吴勇),
	krzk@kernel.org, conor+dt@kernel.org
  Cc: Wendy-ST Lin (林詩庭),
	linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
	linux-arm-kernel@lists.infradead.org, iommu@lists.linux.dev,
	Project_Global_Chrome_Upstream_Group, devicetree@vger.kernel.org
In-Reply-To: <198865fb3184926d0b1b4e4855b5f863ad0d6a20.camel@mediatek.com>

On 5/18/26 09:16, Xueqi Zhang (张雪琦) wrote:
> Hi Angelo,
> 
> First of all, please accept my apologies for the delayed response. I
> have been deeply occupied with MT8196 Aluminium pKVM SMMU and SMI
> related tasks recently.
> 
> Regarding your question, my previous description in the patch was not
> accurate enough and may have caused some confusion. In fact, not
> all SMI commons have their backup/restore handled by the RTFF
> hardware. The SMI commons are distributed across various subsystems
> (e.g., mminfra, venc, display, cam, etc.). Currently, only the SMI
> common under the mminfra subsystem is backed up and restored by
> the RTFF hardware.
> 
> Therefore, I believe adding a specific 'skip_rpm' flag is more
> appropriate here. If we were to differentiate this based on a new
> MTK_SMI_GEN3 type, it would imply that all SMI common modules of
> that generation would skip the RPM operations, which is not the
> intended behavior.
> 
> To make this clearer, I plan to update the commit message in the
> next version as follows:
> 
> Subject: memory: mtk-smi: Add skip_rpm flag for certain MT8196 SMI
> commons

memory: mtk-smi: Allow no clocks for RTFF managed SMI commons

> 
> Body:
> On MT8196, certain SMI commons are backed up and restored by the RTFF
> hardware rather than by software.
> 
> For these specific SMI commons, software-controlled register backup
> and restore in the runtime callback is no longer necessary. Therefore,
> introduce a 'skip_rpm' flag to bypass these redundant RPMoperations
> for these SMI commons.
> 
> What do you think about this approach?
> 

That would be kind-of ok, but keep in mind: pm_runtime doesn't only manage clocks.

I think that the best option here would be to allow having no clocks instead,
and to still call pm_runtime_{en,dis}able() - as that would get a bit more
future-proof, should any other (newer, older, etc) SoC need to declare any power
domain but still no clocks.

So at this point, I think that just doing something like:

	if (common->plat->has_gals) {
		if (common->plat->rtff_managed) <--- not "skip_rpm"
			clk_required = 0;
		else if (common->plat->type == MTK_SMI_GEN2)
			clk_required = MTK_SMI_COM_GALS_REQ_CLK_NR;
		else if (common->plat->type == MTK_SMI_GEN2_SUB_COMM)
			clk_required = MTK_SMI_SUB_COM_GALS_REQ_CLK_NR;
	}

should be sufficient (and/or check zero required clocks in smi_dts_clk_init).

Cheers,
Angelo

> Thanks,
> Xueqi
> 
> On Thu, 2025-03-20 at 13:11 +0100, AngeloGioacchino Del Regno wrote:
>> External email : Please do not click links or open attachments until
>> you have verified the sender or the content.
>>
>>
>> Il 20/03/25 08:36, Xueqi Zhang ha scritto:
>>> MT8196 SMI commons is backed up/restored by RTFF HW.
>>> It doesn't need SW control the register backup/store
>>> in the runtime callback.Therefore, add a flag skip_rpm
>>> to help skip RPM operations for SMI commons.
>>>
>>> Signed-off-by: Xueqi Zhang <xueqi.zhang@mediatek.com>
>>
>> So the MT8196 SMI common doesn't require any clocks?
>>
>> That's fine for me, but this looks bloody similar to MT6989's SMI
>> common, which
>> is SMI GEN3 and not GEN2....
>>
>> ....so, are you sure that you need a `skip_rpm` flag and not new
>> MTK_SMI_GEN3 and
>> MTK_SMI_GEN3_SUB_COMM types? :-)
>>
>> Regards,
>> Angelo
>>
>>> ---
>>>    drivers/memory/mtk-smi.c | 11 ++++++++---
>>>    1 file changed, 8 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
>>> index a8f5467d6b31..b9affa3c3185 100644
>>> --- a/drivers/memory/mtk-smi.c
>>> +++ b/drivers/memory/mtk-smi.c
>>> @@ -123,6 +123,7 @@ static const char * const mtk_smi_common_clks[]
>>> = {"apb", "smi", "gals0", "gals1
>>>    struct mtk_smi_common_plat {
>>>        enum mtk_smi_type       type;
>>>        bool                    has_gals;
>>> +     bool                    skip_rpm;
>>>        u32                     bus_sel; /* Balance some larbs to
>>> enter mmu0 or mmu1 */
>>>
>>>        const struct mtk_smi_reg_pair   *init;
>>> @@ -547,6 +548,9 @@ static int mtk_smi_dts_clk_init(struct device
>>> *dev, struct mtk_smi *smi,
>>>    {
>>>        int i, ret;
>>>
>>> +     if (smi->plat->skip_rpm)
>>> +             return 0;
>>> +
>>>        for (i = 0; i < clk_nr_required; i++)
>>>                smi->clks[i].id = clks[i];
>>>        ret = devm_clk_bulk_get(dev, clk_nr_required, smi->clks);
>>> @@ -783,7 +787,7 @@ static int mtk_smi_common_probe(struct
>>> platform_device *pdev)
>>>        common->dev = dev;
>>>        common->plat = of_device_get_match_data(dev);
>>>
>>> -     if (common->plat->has_gals) {
>>> +     if (!common->plat->skip_rpm && common->plat->has_gals) {
>>>                if (common->plat->type == MTK_SMI_GEN2)
>>>                        clk_required = MTK_SMI_COM_GALS_REQ_CLK_NR;
>>>                else if (common->plat->type == MTK_SMI_GEN2_SUB_COMM)
>>> @@ -814,13 +818,14 @@ static int mtk_smi_common_probe(struct
>>> platform_device *pdev)
>>>        }
>>>
>>>        /* link its smi-common if this is smi-sub-common */
>>> -     if (common->plat->type == MTK_SMI_GEN2_SUB_COMM) {
>>> +     if (common->plat->type == MTK_SMI_GEN2_SUB_COMM && !common-
>>>> plat->skip_rpm) {
>>>                ret = mtk_smi_device_link_common(dev, &common-
>>>> smi_common_dev);
>>>                if (ret < 0)
>>>                        return ret;
>>>        }
>>>
>>> -     pm_runtime_enable(dev);
>>> +     if (!common->plat->skip_rpm)
>>> +             pm_runtime_enable(dev);
>>>        platform_set_drvdata(pdev, common);
>>>        return 0;
>>>    }
>>
>>



^ permalink raw reply

* Re: [PATCH v4 07/13] dma-direct: make dma_direct_map_phys() honor DMA_ATTR_CC_SHARED
From: Christian Borntraeger @ 2026-05-18 10:04 UTC (permalink / raw)
  To: Aneesh Kumar K.V (Arm), iommu, linux-arm-kernel, linux-kernel,
	linux-coco
  Cc: Robin Murphy, Marek Szyprowski, Will Deacon, Marc Zyngier,
	Steven Price, Suzuki K Poulose, Catalin Marinas, Jiri Pirko,
	Jason Gunthorpe, Mostafa Saleh, Petr Tesarik,
	Alexey Kardashevskiy, Dan Williams, Xu Yilun, linuxppc-dev,
	linux-s390, Madhavan Srinivasan, Michael Ellerman,
	Nicholas Piggin, Christophe Leroy (CS GROUP), Alexander Gordeev,
	Gerald Schaefer, Heiko Carstens, Vasily Gorbik, Sven Schnelle,
	x86, Halil Pasic, Matthew Rosato, Jaehoon Kim
In-Reply-To: <20260512090408.794195-8-aneesh.kumar@kernel.org>

cc Halil, Matt, Jaehoon.
Can you have a look what this means for virtio on secure execution?

Am 12.05.26 um 11:04 schrieb Aneesh Kumar K.V (Arm):
> Teach dma_direct_map_phys() to select the DMA address encoding based on
> DMA_ATTR_CC_SHARED.
> 
> Use phys_to_dma_unencrypted() for decrypted mappings and
> phys_to_dma_encrypted() otherwise. If a device requires unencrypted DMA
> but the source physical address is still encrypted, force the mapping
> through swiotlb so the DMA address and backing memory attributes remain
> consistent.
> 
> Update the arm64, x86, s390 and powerpc secure-guest setup to not use
> swiotlb force option
> 
> Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
> ---
> Changes from v3:
> * Handle DMA_ATTR_MMIO
> ---
>   arch/arm64/mm/init.c                 |  4 +--
>   arch/powerpc/platforms/pseries/svm.c |  2 +-
>   arch/s390/mm/init.c                  |  2 +-
>   arch/x86/kernel/pci-dma.c            |  4 +--
>   kernel/dma/direct.c                  |  4 ++-
>   kernel/dma/direct.h                  | 38 +++++++++++++---------------
>   6 files changed, 24 insertions(+), 30 deletions(-)
> 
> diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
> index 97987f850a33..acf67c7064db 100644
> --- a/arch/arm64/mm/init.c
> +++ b/arch/arm64/mm/init.c
> @@ -338,10 +338,8 @@ void __init arch_mm_preinit(void)
>   	unsigned int flags = SWIOTLB_VERBOSE;
>   	bool swiotlb = max_pfn > PFN_DOWN(arm64_dma_phys_limit);
>   
> -	if (is_realm_world()) {
> +	if (is_realm_world())
>   		swiotlb = true;
> -		flags |= SWIOTLB_FORCE;
> -	}
>   
>   	if (IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) && !swiotlb) {
>   		/*
> diff --git a/arch/powerpc/platforms/pseries/svm.c b/arch/powerpc/platforms/pseries/svm.c
> index 384c9dc1899a..7a403dbd35ee 100644
> --- a/arch/powerpc/platforms/pseries/svm.c
> +++ b/arch/powerpc/platforms/pseries/svm.c
> @@ -29,7 +29,7 @@ static int __init init_svm(void)
>   	 * need to use the SWIOTLB buffer for DMA even if dma_capable() says
>   	 * otherwise.
>   	 */
> -	ppc_swiotlb_flags |= SWIOTLB_ANY | SWIOTLB_FORCE;
> +	ppc_swiotlb_flags |= SWIOTLB_ANY;
>   
>   	/* Share the SWIOTLB buffer with the host. */
>   	swiotlb_update_mem_attributes();
> diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
> index 1f72efc2a579..843dbd445124 100644
> --- a/arch/s390/mm/init.c
> +++ b/arch/s390/mm/init.c
> @@ -149,7 +149,7 @@ static void __init pv_init(void)
>   	virtio_set_mem_acc_cb(virtio_require_restricted_mem_acc);
>   
>   	/* make sure bounce buffers are shared */
> -	swiotlb_init(true, SWIOTLB_FORCE | SWIOTLB_VERBOSE);
> +	swiotlb_init(true, SWIOTLB_VERBOSE);
>   	swiotlb_update_mem_attributes();
>   }
>   
> diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
> index 6267363e0189..75cf8f6ae8cd 100644
> --- a/arch/x86/kernel/pci-dma.c
> +++ b/arch/x86/kernel/pci-dma.c
> @@ -59,10 +59,8 @@ static void __init pci_swiotlb_detect(void)
>   	 * bounce buffers as the hypervisor can't access arbitrary VM memory
>   	 * that is not explicitly shared with it.
>   	 */
> -	if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
> +	if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
>   		x86_swiotlb_enable = true;
> -		x86_swiotlb_flags |= SWIOTLB_FORCE;
> -	}
>   }
>   #else
>   static inline void __init pci_swiotlb_detect(void)
> diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
> index ac315dd046c4..5aaa813c5509 100644
> --- a/kernel/dma/direct.c
> +++ b/kernel/dma/direct.c
> @@ -691,8 +691,10 @@ size_t dma_direct_max_mapping_size(struct device *dev)
>   {
>   	/* If SWIOTLB is active, use its maximum mapping size */
>   	if (is_swiotlb_active(dev) &&
> -	    (dma_addressing_limited(dev) || is_swiotlb_force_bounce(dev)))
> +	    (dma_addressing_limited(dev) || is_swiotlb_force_bounce(dev) ||
> +	     force_dma_unencrypted(dev)))
>   		return swiotlb_max_mapping_size(dev);
> +
>   	return SIZE_MAX;
>   }
>   
> diff --git a/kernel/dma/direct.h b/kernel/dma/direct.h
> index e05dc7649366..4e35264ab6f8 100644
> --- a/kernel/dma/direct.h
> +++ b/kernel/dma/direct.h
> @@ -89,36 +89,32 @@ static inline dma_addr_t dma_direct_map_phys(struct device *dev,
>   	dma_addr_t dma_addr;
>   
>   	if (is_swiotlb_force_bounce(dev)) {
> -		if (!(attrs & DMA_ATTR_CC_SHARED)) {
> -			if (attrs & (DMA_ATTR_MMIO | DMA_ATTR_REQUIRE_COHERENT))
> -				return DMA_MAPPING_ERROR;
> +		if (attrs & (DMA_ATTR_MMIO | DMA_ATTR_REQUIRE_COHERENT))
> +			return DMA_MAPPING_ERROR;
>   
> -			return swiotlb_map(dev, phys, size, dir, attrs);
> -		}
> -	} else if (attrs & DMA_ATTR_CC_SHARED) {
> -		return DMA_MAPPING_ERROR;
> +		return swiotlb_map(dev, phys, size, dir, attrs);
>   	}
>   
> -	if (attrs & DMA_ATTR_MMIO) {
> -		dma_addr = phys;
> -		if (unlikely(!dma_capable(dev, dma_addr, size, false, attrs)))
> -			goto err_overflow;
> -	} else if (attrs & DMA_ATTR_CC_SHARED) {
> +	if (attrs & DMA_ATTR_CC_SHARED)
>   		dma_addr = phys_to_dma_unencrypted(dev, phys);
> +	else
> +		dma_addr = phys_to_dma_encrypted(dev, phys);
> +
> +	if (attrs & DMA_ATTR_MMIO) {
>   		if (unlikely(!dma_capable(dev, dma_addr, size, false, attrs)))
>   			goto err_overflow;
> -	} else {
> -		dma_addr = phys_to_dma(dev, phys);
> -		if (unlikely(!dma_capable(dev, dma_addr, size, true, attrs)) ||
> -		    dma_kmalloc_needs_bounce(dev, size, dir)) {
> -			if (is_swiotlb_active(dev) &&
> -			    !(attrs & DMA_ATTR_REQUIRE_COHERENT))
> -				return swiotlb_map(dev, phys, size, dir, attrs);
> +		goto dma_mapped;
> +	}
>   
> -			goto err_overflow;
> -		}
> +	if (unlikely(!dma_capable(dev, dma_addr, size, true, attrs)) ||
> +	    dma_kmalloc_needs_bounce(dev, size, dir)) {
> +		if (is_swiotlb_active(dev) &&
> +		    !(attrs & DMA_ATTR_REQUIRE_COHERENT))
> +			return swiotlb_map(dev, phys, size, dir, attrs);
> +		goto err_overflow;
>   	}
>   
> +dma_mapped:
>   	if (!dev_is_dma_coherent(dev) &&
>   	    !(attrs & (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_MMIO))) {
>   		arch_sync_dma_for_device(phys, size, dir);



^ permalink raw reply

* [PATCH v2] ARM: dts: aspeed: anacapa: correct SGPIO names for monitoring
From: Rex Fu via B4 Relay @ 2026-05-18 10:00 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Andrew Jeffery
  Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel, Rex Fu

From: Rex Fu <Rex.Fu@amd.com>

Update several Anacapa SGPIO line names to match the existing platform
hardware design and the signal names consumed by userspace monitoring.

The previous names did not match the actual Anacapa SGPIO usage. Some
lines were named as CPU or CPU power-good signals, but they are wired and
used on Anacapa for EDSFF presence, EDSFF power-good, boot EDSFF
presence, and thermal-trip assertion monitoring.

Correct the mappings as follows:

  PWRGD_PVDDCR_SOC_P0     -> L_PRSNT_EDSFF0_N
  PWRGD_PVDDIO_P0         -> L_PRSNT_EDSFF1_N
  PWRGD_PVDDIO_MEM_S3_P0  -> R_PRSNT_EDSFF2_N
  PWRGD_CHMP_CPU0_FPGA    -> R_PRSNT_EDSFF3_N
  PWRGD_CHIL_CPU0_FPGA    -> HPM_EDSFF_PG
  EAM2_CPU_MOD_PWR_GD_R   -> PRSNT_EDSFF_BOOT_N
  CPU0_SP7R1              -> L_EDSFF0_PG
  CPU0_SP7R2              -> L_EDSFF1_PG
  CPU0_SP7R3              -> R_EDSFF2_PG
  CPU0_SP7R4              -> R_EDSFF3_PG
  HPM_AMC_THERMTRIP_R_L   -> AMC_THERMTRIP_ASSERT
  FM_CPU0_THERMTRIP_N     -> CPU_THERMTRIP_ASSERT

The left-side EDSFF slots are numbered as EDSFF0 and EDSFF1 to match
the platform slot numbering used by userspace. The thermtrip names are
also updated to describe the asserted condition monitored by userspace
instead of the raw active-low signal names.

This is a naming correction for the existing Anacapa hardware design.
There is no new board revision or underlying hardware change involved.

Signed-off-by: Rex Fu <Rex.Fu@amd.com>
---
Update the Anacapa SGPIO line names to match the existing hardware
design and the platform signal names used by userspace monitoring.

The v2 commit message now explains why changing these userspace-visible
GPIO line names is appropriate and lists the exact old-to-new mappings.
---
Changes in v2:
- Reworked the commit message to explain why these userspace-visible
  GPIO line names are changed.
- Listed the exact old-to-new SGPIO line name mappings.
- Clarified that this is a naming correction for the existing hardware
  design and not a board revision or hardware change.
- Link to v1: https://patch.msgid.link/20260430-anacapa-sgpio-edsff-thermtrip-v1-1-2fd5e72435d0@amd.com

To: Rob Herring <robh@kernel.org>
To: Krzysztof Kozlowski <krzk+dt@kernel.org>
To: Conor Dooley <conor+dt@kernel.org>
To: Joel Stanley <joel@jms.id.au>
To: Andrew Jeffery <andrew@codeconstruct.com.au>
Cc: devicetree@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-aspeed@lists.ozlabs.org
Cc: linux-kernel@vger.kernel.org
---
 .../boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts  | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts
index 2cb7bd128d24..e898bc11e6f5 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts
@@ -908,11 +908,11 @@ &sgpiom0 {
 	"", "", "", "",
 
 	/* G0-G7 line 96-111 */
-	"PWRGD_PVDDCR_SOC_P0", "",
-	"PWRGD_PVDDIO_P0", "",
-	"PWRGD_PVDDIO_MEM_S3_P0", "",
-	"PWRGD_CHMP_CPU0_FPGA", "",
-	"PWRGD_CHIL_CPU0_FPGA", "",
+	"L_PRSNT_EDSFF0_N", "",
+	"L_PRSNT_EDSFF1_N", "",
+	"R_PRSNT_EDSFF2_N", "",
+	"R_PRSNT_EDSFF3_N", "",
+	"HPM_EDSFF_PG", "",
 	"PWRGD_CHEH_CPU0_FPGA", "",
 	"PWRGD_CHAD_CPU0_FPGA", "FM_BMC_READY_PLD",
 	"", "",
@@ -934,7 +934,7 @@ &sgpiom0 {
 	"EAM3_BRD_PRSNT_R_L", "",
 	"EAM0_CPU_MOD_PWR_GD_R", "",
 	"EAM1_CPU_MOD_PWR_GD_R", "",
-	"EAM2_CPU_MOD_PWR_GD_R", "",
+	"PRSNT_EDSFF_BOOT_N", "",
 	"EAM3_CPU_MOD_PWR_GD_R", "",
 
 	/* J0-J7 line 144-159 */
@@ -957,8 +957,8 @@ &sgpiom0 {
 	"PDB_ALERT_R_N", "",
 
 	/* L0-L7 line 176-191 */
-	"CPU0_SP7R1", "", "CPU0_SP7R2", "",
-	"CPU0_SP7R3", "", "CPU0_SP7R4", "",
+	"L_EDSFF0_PG", "", "L_EDSFF1_PG", "",
+	"R_EDSFF2_PG", "", "R_EDSFF3_PG", "",
 	"CPU0_CORETYPE0", "", "CPU0_CORETYPE1", "",
 	"CPU0_CORETYPE2", "", "FM_BIOS_POST_CMPLT_R_N", "",
 
@@ -984,8 +984,8 @@ &sgpiom0 {
 	"HPM_PWR_FAIL", "Port80_b0",
 	"FM_DIMM_IP_FAIL", "Port80_b1",
 	"FM_DIMM_AH_FAIL", "Port80_b2",
-	"HPM_AMC_THERMTRIP_R_L", "Port80_b3",
-	"FM_CPU0_THERMTRIP_N", "Port80_b4",
+	"AMC_THERMTRIP_ASSERT", "Port80_b3",
+	"CPU_THERMTRIP_ASSERT", "Port80_b4",
 	"PVDDCR_SOC_P0_OCP_L", "Port80_b5",
 	"CPLD_SGPIO_RDY", "Port80_b6",
 	"", "Port80_b7",

---
base-commit: 9974969c14031a097d6b45bcb7a06bb4aa525c40
change-id: 20260430-anacapa-sgpio-edsff-thermtrip-acb228bf61be

Best regards,
--  
Rex Fu <Rex.Fu@amd.com>




^ permalink raw reply related

* Re: [PATCH v2 3/3] arm64: dts: allwinner: A133: add support for Baijie Helper A133 board
From: Alexander Sverdlin @ 2026-05-18 10:12 UTC (permalink / raw)
  To: wens
  Cc: Andre Przywara, linux-sunxi, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Jernej Skrabec, Samuel Holland, devicetree,
	linux-arm-kernel, linux-kernel
In-Reply-To: <CAGb2v67tjOCE=Xk=pD84wBG4WTt1nYhDoW3gu_xfx4J0Ooc_VQ@mail.gmail.com>

Hi Checn-Yu,

thanks for the review!

On Mon, 2026-05-18 at 11:30 +0800, Chen-Yu Tsai wrote:
> > > And you should provide a top level 5V regulator here, to be the root of
> > > the regulator tree. Look at reg_vcc5v in the Liontron .dts.
> > 
> > It doesn't look to me as if Liontron had reg_vcc5v as its 5V "root" regulator.
> > It seems to be only used for reg_usb1_vbus, while HelperBoard A133 doesn't
> > have USB power control. The second issue with Helper/Core split is that
> > all PMIC story is inside Core board which has 5V input rail, while HelperBoard
> > around it has indeed 12V->5V DCDC regulator (similar to Liontron), but
> > putting it in the DT would introduce wierd dependency of the core to the
> > HelperBoard which carries it. Do you think it would make sense?
> 
> In that case I would probably put a 5v "fake root" regulator in the core
> dtsi. And in combined dts, I'd then add the 12v "real root", and use that
> as the supply for the 5v fake root.
> 
> Does that make sense?

"core" board has some battery management schematics, switching the 5V,
I'll look into specifying this part in "core" .dtsi, maybe it will result
in some kind of regulator in "core" part. I'll send v4.

-- 
Alexander Sverdlin.


^ permalink raw reply

* [PATCH v5 0/4] Enable sysfs module symlink for more built-in drivers
From: Shashank Balaji @ 2026-05-18 10:19 UTC (permalink / raw)
  To: Suzuki K Poulose, James Clark, Alexander Shishkin,
	Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Jonathan Corbet, Shuah Khan, Luis Chamberlain, Petr Pavlu,
	Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Mike Leach, Leo Yan,
	Thierry Reding, Jonathan Hunter, Mike Leach
  Cc: Rahul Bukte, Shashank Balaji, linux-kernel, coresight,
	linux-arm-kernel, driver-core, rust-for-linux, linux-doc,
	Daniel Palmer, Tim Bird, linux-modules, linux-tegra, Sumit Gupta
In-Reply-To: <20260427-acpi_mod_name-v4-0-22b42240c9bf@sony.com>

struct device_driver's mod_name is not set by a number of bus' driver registration
functions. Without that, built-in drivers don't have the module symlink in sysfs.
We want this to go from unbound driver name -> module name -> kernel config name.
This is useful on embedded platforms to minimize kernel config, reduce kernel size,
and reduce boot time.

In order to achieve this, mod_name has to be set to KBUILD_MODNAME, and this has
to be done for all buses which don't yet do this.

Here are some treewide stats:
- 110 registration functions across all bus types
- 20 of them set mod_name
- Remaining 90 do not set mod_name:
    1. 36 functions under pattern 1:
        They have a __register function + register macro. KBUILD_MODNAME needs to
        be passed and the function needs to take mod_name as input.
    2. 42 functions under pattern 2:
        These have no macro wrapper. They need a double-underscore rename + macro
        wrapper to make them similar to pattern 1.
    3. Remaining 12 do not have such a clean registration interface. More analysis
       is required.

We plan to start with pattern 1, since it's the easiest category of changes.
Within that, for now we're only sending the platform patch. If we get the go-ahead
on that, we'll send the remaining ones.

Patch 4 depends on patches 1, 2, and 3.

Co-developed-by: Rahul Bukte <rahul.bukte@sony.com>
Signed-off-by: Rahul Bukte <rahul.bukte@sony.com>
Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
---
Changes in v5:
- Move tegra cbb driver init to core_initcall and module_kset init to pure_initcall (Gary)
- Rename coresight_init_driver() to coresight_init_driver_with_owner(), and
  declare function prototype before use (Leo)
- Merge doc change patch with code change patch, so that __platform_register_drivers()
  prototype is changed everywhere in the same patch
- Link to v4: https://patch.msgid.link/20260427-acpi_mod_name-v4-0-22b42240c9bf@sony.com

Changes in v4:
- Initialize module_kset in do_basic_setup() before do_initcalls() (Gary)
- Add commit body to the documentation patch (Greg)
- Link to v3: https://patch.msgid.link/20260422-acpi_mod_name-v3-0-a184eff9ff6f@sony.com

Changes in v3:
- Initialize module_kset on-demand (Greg)
- Make coresight driver registration happen through a macro (Greg)
- Split up the patch adding mod_name to platform driver registrations (Greg)
- Link to v2: https://patch.msgid.link/20260421-acpi_mod_name-v2-0-e73f9310dad3@sony.com

Changes in v2:
- Drop acpi patch, send platform instead (Rafael)
- Link to v1: https://patch.msgid.link/20260416-acpi_mod_name-v1-0-1a4d96fd86c9@sony.com

To: Suzuki K Poulose <suzuki.poulose@arm.com>
To: Mike Leach <mike.leach@linaro.org>
To: James Clark <james.clark@linaro.org>
To: Alexander Shishkin <alexander.shishkin@linux.intel.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: "Rafael J. Wysocki" <rafael@kernel.org>
To: Danilo Krummrich <dakr@kernel.org>
To: Miguel Ojeda <ojeda@kernel.org>
To: Boqun Feng <boqun@kernel.org>
To: Gary Guo <gary@garyguo.net>
To: Björn Roy Baron <bjorn3_gh@protonmail.com>
To: Benno Lossin <lossin@kernel.org>
To: Andreas Hindborg <a.hindborg@kernel.org>
To: Alice Ryhl <aliceryhl@google.com>
To: Trevor Gross <tmgross@umich.edu>
To: Jonathan Corbet <corbet@lwn.net>
To: Shuah Khan <skhan@linuxfoundation.org>
To: Luis Chamberlain <mcgrof@kernel.org>
To: Petr Pavlu <petr.pavlu@suse.com>
To: Daniel Gomez <da.gomez@kernel.org>
To: Sami Tolvanen <samitolvanen@google.com>
To: Aaron Tomlin <atomlin@atomlin.com>
To: Mike Leach <mike.leach@arm.com>
To: Leo Yan <leo.yan@arm.com>
To: Thierry Reding <thierry.reding@kernel.org>
To: Jonathan Hunter <jonathanh@nvidia.com>
Cc: linux-kernel@vger.kernel.org
Cc: coresight@lists.linaro.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: driver-core@lists.linux.dev
Cc: rust-for-linux@vger.kernel.org
Cc: linux-doc@vger.kernel.org
Cc: Shashank Balaji <shashank.mahadasyam@sony.com>
Cc: Rahul Bukte <rahul.bukte@sony.com>
Cc: Daniel Palmer <daniel.palmer@sony.com>
Cc: Tim Bird <tim.bird@sony.com>
Cc: linux-modules@vger.kernel.org
Cc: linux-tegra@vger.kernel.org
Cc: Sumit Gupta <sumitg@nvidia.com>

---
Shashank Balaji (4):
      soc/tegra: cbb: Move driver registration from pure_initcall to core_initcall
      kernel: param: initialize module_kset in a pure_initcall
      coresight: pass THIS_MODULE implicitly through a macro
      driver core: platform: set mod_name in driver registration

 Documentation/driver-api/driver-model/platform.rst |  3 ++-
 drivers/base/platform.c                            | 21 ++++++++++++++-------
 drivers/hwtracing/coresight/coresight-catu.c       |  2 +-
 drivers/hwtracing/coresight/coresight-core.c       |  9 +++++----
 drivers/hwtracing/coresight/coresight-cpu-debug.c  |  3 +--
 drivers/hwtracing/coresight/coresight-funnel.c     |  3 +--
 drivers/hwtracing/coresight/coresight-replicator.c |  3 +--
 drivers/hwtracing/coresight/coresight-stm.c        |  2 +-
 drivers/hwtracing/coresight/coresight-tmc-core.c   |  2 +-
 drivers/hwtracing/coresight/coresight-tnoc.c       |  2 +-
 drivers/hwtracing/coresight/coresight-tpdm.c       |  3 +--
 drivers/hwtracing/coresight/coresight-tpiu.c       |  2 +-
 drivers/soc/tegra/cbb/tegra194-cbb.c               |  2 +-
 drivers/soc/tegra/cbb/tegra234-cbb.c               |  2 +-
 include/linux/coresight.h                          |  7 +++++--
 include/linux/platform_device.h                    | 17 +++++++++--------
 kernel/params.c                                    |  2 +-
 rust/kernel/platform.rs                            |  4 +++-
 18 files changed, 50 insertions(+), 39 deletions(-)
---
base-commit: 5200f5f493f79f14bbdc349e402a40dfb32f23c8
change-id: 20260416-acpi_mod_name-f645a76e337b

Best regards,
--  
Shashank Balaji <shashank.mahadasyam@sony.com>



^ permalink raw reply

* [PATCH v5 2/4] kernel: param: initialize module_kset in a pure_initcall
From: Shashank Balaji @ 2026-05-18 10:19 UTC (permalink / raw)
  To: Suzuki K Poulose, James Clark, Alexander Shishkin,
	Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Jonathan Corbet, Shuah Khan, Luis Chamberlain, Petr Pavlu,
	Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Mike Leach, Leo Yan,
	Thierry Reding, Jonathan Hunter, Mike Leach
  Cc: Rahul Bukte, Shashank Balaji, linux-kernel, coresight,
	linux-arm-kernel, driver-core, rust-for-linux, linux-doc,
	Daniel Palmer, Tim Bird, linux-modules, linux-tegra, Sumit Gupta
In-Reply-To: <20260518-acpi_mod_name-v5-0-705ccc430885@sony.com>

Commit "driver core: platform: set mod_name in driver registration" will set
struct device_driver's mod_name member for platform driver registration. For a
driver to be registered with its mod_name set, module_kset needs to be
initialized, which currently happens in a subsys_initcall in param_sysfs_init().
The tegra cbb drivers register themselves before module_kset init, in a
core_initcall. This works currently because lookup_or_create_module_kobject(),
which dereferences module_kset via kset_find_obj(), is not called if mod_name
is not set, which is the case now.

So in preparation for the commit "driver core: platform: set mod_name in driver registration",
move module_kset init to pure_initcall level, ensuring it happens before tegra
cbb driver registration.

Suggested-by: Gary Guo <gary@garyguo.net>
Co-developed-by: Rahul Bukte <rahul.bukte@sony.com>
Signed-off-by: Rahul Bukte <rahul.bukte@sony.com>
Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
---
Patch 4 depends on this patch
---
 kernel/params.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/params.c b/kernel/params.c
index 74d620bc2521..ac088d4b09a9 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -957,7 +957,7 @@ static int __init param_sysfs_init(void)
 
 	return 0;
 }
-subsys_initcall(param_sysfs_init);
+pure_initcall(param_sysfs_init);
 
 /*
  * param_sysfs_builtin_init - add sysfs version and parameter

-- 
2.43.0



^ permalink raw reply related

* [PATCH v5 1/4] soc/tegra: cbb: Move driver registration from pure_initcall to core_initcall
From: Shashank Balaji @ 2026-05-18 10:19 UTC (permalink / raw)
  To: Suzuki K Poulose, James Clark, Alexander Shishkin,
	Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Jonathan Corbet, Shuah Khan, Luis Chamberlain, Petr Pavlu,
	Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Mike Leach, Leo Yan,
	Thierry Reding, Jonathan Hunter, Mike Leach
  Cc: Rahul Bukte, Shashank Balaji, linux-kernel, coresight,
	linux-arm-kernel, driver-core, rust-for-linux, linux-doc,
	Daniel Palmer, Tim Bird, linux-modules, linux-tegra, Sumit Gupta
In-Reply-To: <20260518-acpi_mod_name-v5-0-705ccc430885@sony.com>

Commit "driver core: platform: set mod_name in driver registration" will set
struct device_driver's mod_name member for platform driver registration. For a
driver to be registered with its mod_name set, module_kset needs to be
initialized, which currently happens in a subsys_initcall in param_sysfs_init().
The tegra cbb drivers register themselves before module_kset init, in a
pure_initcall. This works currently because lookup_or_create_module_kobject(),
which dereferences module_kset via kset_find_obj(), is not called if mod_name
is not set, which is the case now.

So in preparation for the commit "driver core: platform: set mod_name in driver registration",
move tegra cbb driver registration to core_initcall level, and commit
"kernel: param: initialize module_kset in a pure_initcall" will move module_kset
init to pure_initcall level, ensuring module_kset init happens before tegra cbb
driver registration.

Suggested-by: Gary Guo <gary@garyguo.net>
Acked-by: Sumit Gupta <sumitg@nvidia.com>
Co-developed-by: Rahul Bukte <rahul.bukte@sony.com>
Signed-off-by: Rahul Bukte <rahul.bukte@sony.com>
Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
---
Patch 4 depends on this patch
---
 drivers/soc/tegra/cbb/tegra194-cbb.c | 2 +-
 drivers/soc/tegra/cbb/tegra234-cbb.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/tegra/cbb/tegra194-cbb.c b/drivers/soc/tegra/cbb/tegra194-cbb.c
index ab75d50cc85c..2f69e104c838 100644
--- a/drivers/soc/tegra/cbb/tegra194-cbb.c
+++ b/drivers/soc/tegra/cbb/tegra194-cbb.c
@@ -2342,7 +2342,7 @@ static int __init tegra194_cbb_init(void)
 {
 	return platform_driver_register(&tegra194_cbb_driver);
 }
-pure_initcall(tegra194_cbb_init);
+core_initcall(tegra194_cbb_init);
 
 static void __exit tegra194_cbb_exit(void)
 {
diff --git a/drivers/soc/tegra/cbb/tegra234-cbb.c b/drivers/soc/tegra/cbb/tegra234-cbb.c
index fb26f085f691..785072fa4e85 100644
--- a/drivers/soc/tegra/cbb/tegra234-cbb.c
+++ b/drivers/soc/tegra/cbb/tegra234-cbb.c
@@ -1774,7 +1774,7 @@ static int __init tegra234_cbb_init(void)
 {
 	return platform_driver_register(&tegra234_cbb_driver);
 }
-pure_initcall(tegra234_cbb_init);
+core_initcall(tegra234_cbb_init);
 
 static void __exit tegra234_cbb_exit(void)
 {

-- 
2.43.0



^ permalink raw reply related

* [PATCH v5 3/4] coresight: pass THIS_MODULE implicitly through a macro
From: Shashank Balaji @ 2026-05-18 10:19 UTC (permalink / raw)
  To: Suzuki K Poulose, James Clark, Alexander Shishkin,
	Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Jonathan Corbet, Shuah Khan, Luis Chamberlain, Petr Pavlu,
	Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Mike Leach, Leo Yan,
	Thierry Reding, Jonathan Hunter, Mike Leach
  Cc: Rahul Bukte, Shashank Balaji, linux-kernel, coresight,
	linux-arm-kernel, driver-core, rust-for-linux, linux-doc,
	Daniel Palmer, Tim Bird, linux-modules, linux-tegra, Sumit Gupta
In-Reply-To: <20260518-acpi_mod_name-v5-0-705ccc430885@sony.com>

Rename coresight_init_driver() to coresight_init_driver_with_owner() and replace
it with a macro wrapper that passes THIS_MODULE implicitly. This is in line with
what other buses do.

Suggested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Leo Yan <leo.yan@arm.com>
Co-developed-by: Rahul Bukte <rahul.bukte@sony.com>
Signed-off-by: Rahul Bukte <rahul.bukte@sony.com>
Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
---
Patch 4 depends on this patch
---
 drivers/hwtracing/coresight/coresight-catu.c       | 2 +-
 drivers/hwtracing/coresight/coresight-core.c       | 6 +++---
 drivers/hwtracing/coresight/coresight-cpu-debug.c  | 3 +--
 drivers/hwtracing/coresight/coresight-funnel.c     | 3 +--
 drivers/hwtracing/coresight/coresight-replicator.c | 3 +--
 drivers/hwtracing/coresight/coresight-stm.c        | 2 +-
 drivers/hwtracing/coresight/coresight-tmc-core.c   | 2 +-
 drivers/hwtracing/coresight/coresight-tnoc.c       | 2 +-
 drivers/hwtracing/coresight/coresight-tpdm.c       | 3 +--
 drivers/hwtracing/coresight/coresight-tpiu.c       | 2 +-
 include/linux/coresight.h                          | 6 ++++--
 11 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
index ce71dcddfca2..0c8698c8fc5e 100644
--- a/drivers/hwtracing/coresight/coresight-catu.c
+++ b/drivers/hwtracing/coresight/coresight-catu.c
@@ -706,7 +706,7 @@ static int __init catu_init(void)
 {
 	int ret;
 
-	ret = coresight_init_driver("catu", &catu_driver, &catu_platform_driver, THIS_MODULE);
+	ret = coresight_init_driver("catu", &catu_driver, &catu_platform_driver);
 	tmc_etr_set_catu_ops(&etr_catu_buf_ops);
 	return ret;
 }
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 46f247f73cf6..54ad5193b850 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -1694,8 +1694,8 @@ static void __exit coresight_exit(void)
 module_init(coresight_init);
 module_exit(coresight_exit);
 
-int coresight_init_driver(const char *drv, struct amba_driver *amba_drv,
-			  struct platform_driver *pdev_drv, struct module *owner)
+int coresight_init_driver_with_owner(const char *drv, struct amba_driver *amba_drv,
+				     struct platform_driver *pdev_drv, struct module *owner)
 {
 	int ret;
 
@@ -1713,7 +1713,7 @@ int coresight_init_driver(const char *drv, struct amba_driver *amba_drv,
 	amba_driver_unregister(amba_drv);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(coresight_init_driver);
+EXPORT_SYMBOL_GPL(coresight_init_driver_with_owner);
 
 void coresight_remove_driver(struct amba_driver *amba_drv,
 			     struct platform_driver *pdev_drv)
diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/drivers/hwtracing/coresight/coresight-cpu-debug.c
index 629614278e46..3a806c1d50ea 100644
--- a/drivers/hwtracing/coresight/coresight-cpu-debug.c
+++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c
@@ -757,8 +757,7 @@ static struct platform_driver debug_platform_driver = {
 
 static int __init debug_init(void)
 {
-	return coresight_init_driver("debug", &debug_driver, &debug_platform_driver,
-				     THIS_MODULE);
+	return coresight_init_driver("debug", &debug_driver, &debug_platform_driver);
 }
 
 static void __exit debug_exit(void)
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
index 3f56ceccd8c9..0abc11f0690c 100644
--- a/drivers/hwtracing/coresight/coresight-funnel.c
+++ b/drivers/hwtracing/coresight/coresight-funnel.c
@@ -412,8 +412,7 @@ static struct amba_driver dynamic_funnel_driver = {
 
 static int __init funnel_init(void)
 {
-	return coresight_init_driver("funnel", &dynamic_funnel_driver, &funnel_driver,
-				     THIS_MODULE);
+	return coresight_init_driver("funnel", &dynamic_funnel_driver, &funnel_driver);
 }
 
 static void __exit funnel_exit(void)
diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
index 07fc04f53b88..2f382de357ee 100644
--- a/drivers/hwtracing/coresight/coresight-replicator.c
+++ b/drivers/hwtracing/coresight/coresight-replicator.c
@@ -418,8 +418,7 @@ static struct amba_driver dynamic_replicator_driver = {
 
 static int __init replicator_init(void)
 {
-	return coresight_init_driver("replicator", &dynamic_replicator_driver, &replicator_driver,
-				     THIS_MODULE);
+	return coresight_init_driver("replicator", &dynamic_replicator_driver, &replicator_driver);
 }
 
 static void __exit replicator_exit(void)
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
index aca6cec7885a..4e860519a73f 100644
--- a/drivers/hwtracing/coresight/coresight-stm.c
+++ b/drivers/hwtracing/coresight/coresight-stm.c
@@ -1050,7 +1050,7 @@ static struct platform_driver stm_platform_driver = {
 
 static int __init stm_init(void)
 {
-	return coresight_init_driver("stm", &stm_driver, &stm_platform_driver, THIS_MODULE);
+	return coresight_init_driver("stm", &stm_driver, &stm_platform_driver);
 }
 
 static void __exit stm_exit(void)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
index c89fe996af23..bc5a133ada3e 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-core.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
@@ -1046,7 +1046,7 @@ static struct platform_driver tmc_platform_driver = {
 
 static int __init tmc_init(void)
 {
-	return coresight_init_driver("tmc", &tmc_driver, &tmc_platform_driver, THIS_MODULE);
+	return coresight_init_driver("tmc", &tmc_driver, &tmc_platform_driver);
 }
 
 static void __exit tmc_exit(void)
diff --git a/drivers/hwtracing/coresight/coresight-tnoc.c b/drivers/hwtracing/coresight/coresight-tnoc.c
index 96a25877b824..9e8de4323d28 100644
--- a/drivers/hwtracing/coresight/coresight-tnoc.c
+++ b/drivers/hwtracing/coresight/coresight-tnoc.c
@@ -344,7 +344,7 @@ static struct platform_driver itnoc_driver = {
 
 static int __init tnoc_init(void)
 {
-	return coresight_init_driver("tnoc", &trace_noc_driver, &itnoc_driver, THIS_MODULE);
+	return coresight_init_driver("tnoc", &trace_noc_driver, &itnoc_driver);
 }
 
 static void __exit tnoc_exit(void)
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index eaf7210af648..8464edbba2d4 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -1563,8 +1563,7 @@ static struct platform_driver static_tpdm_driver = {
 
 static int __init tpdm_init(void)
 {
-	return coresight_init_driver("tpdm", &dynamic_tpdm_driver, &static_tpdm_driver,
-				     THIS_MODULE);
+	return coresight_init_driver("tpdm", &dynamic_tpdm_driver, &static_tpdm_driver);
 }
 
 static void __exit tpdm_exit(void)
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
index b8560b140e0f..7b029d2eb389 100644
--- a/drivers/hwtracing/coresight/coresight-tpiu.c
+++ b/drivers/hwtracing/coresight/coresight-tpiu.c
@@ -310,7 +310,7 @@ static struct platform_driver tpiu_platform_driver = {
 
 static int __init tpiu_init(void)
 {
-	return coresight_init_driver("tpiu", &tpiu_driver, &tpiu_platform_driver, THIS_MODULE);
+	return coresight_init_driver("tpiu", &tpiu_driver, &tpiu_platform_driver);
 }
 
 static void __exit tpiu_exit(void)
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 2131febebee9..cd8fb47a1192 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -691,8 +691,10 @@ coresight_find_output_type(struct coresight_platform_data *pdata,
 			   enum coresight_dev_type type,
 			   union coresight_dev_subtype subtype);
 
-int coresight_init_driver(const char *drv, struct amba_driver *amba_drv,
-			  struct platform_driver *pdev_drv, struct module *owner);
+int coresight_init_driver_with_owner(const char *drv, struct amba_driver *amba_drv,
+				     struct platform_driver *pdev_drv, struct module *owner);
+#define coresight_init_driver(drv, amba_drv, pdev_drv) \
+	coresight_init_driver_with_owner(drv, amba_drv, pdev_drv, THIS_MODULE)
 
 void coresight_remove_driver(struct amba_driver *amba_drv,
 			     struct platform_driver *pdev_drv);

-- 
2.43.0



^ permalink raw reply related

* [PATCH v5 4/4] driver core: platform: set mod_name in driver registration
From: Shashank Balaji @ 2026-05-18 10:20 UTC (permalink / raw)
  To: Suzuki K Poulose, James Clark, Alexander Shishkin,
	Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Jonathan Corbet, Shuah Khan, Luis Chamberlain, Petr Pavlu,
	Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Mike Leach, Leo Yan,
	Thierry Reding, Jonathan Hunter, Mike Leach
  Cc: Rahul Bukte, Shashank Balaji, linux-kernel, coresight,
	linux-arm-kernel, driver-core, rust-for-linux, linux-doc,
	Daniel Palmer, Tim Bird, linux-modules, linux-tegra, Sumit Gupta
In-Reply-To: <20260518-acpi_mod_name-v5-0-705ccc430885@sony.com>

Pass KBUILD_MODNAME through the driver registration macro so that
the driver core can create the module symlink in sysfs for built-in
drivers, and fixup all callers.

The Rust platform adapter is updated to pass the module name through to the new
parameter.

Tested on qemu with:
- x86 defconfig + CONFIG_RUST
- arm64 defconfig + CONFIG_RUST + CONFIG_CORESIGHT stuff

Examples after this patch:

    /sys/bus/platform/drivers/...
        coresight-itnoc/module		-> coresight_tnoc
        coresight-static-tpdm/module	-> coresight_tpdm
        coresight-catu-platform/module	-> coresight_catu
        serial8250/module		-> 8250
        acpi-ged/module			-> acpi
        vmclock/module			-> ptp_vmclock

Co-developed-by: Rahul Bukte <rahul.bukte@sony.com>
Signed-off-by: Rahul Bukte <rahul.bukte@sony.com>
Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
---
This patch depends on patches 1, 2, 3
---
 Documentation/driver-api/driver-model/platform.rst |  3 ++-
 drivers/base/platform.c                            | 21 ++++++++++++++-------
 drivers/hwtracing/coresight/coresight-core.c       |  5 +++--
 include/linux/coresight.h                          |  5 +++--
 include/linux/platform_device.h                    | 17 +++++++++--------
 rust/kernel/platform.rs                            |  4 +++-
 6 files changed, 34 insertions(+), 21 deletions(-)

diff --git a/Documentation/driver-api/driver-model/platform.rst b/Documentation/driver-api/driver-model/platform.rst
index cf5ff48d3115..9673470bded2 100644
--- a/Documentation/driver-api/driver-model/platform.rst
+++ b/Documentation/driver-api/driver-model/platform.rst
@@ -70,7 +70,8 @@ Kernel modules can be composed of several platform drivers. The platform core
 provides helpers to register and unregister an array of drivers::
 
 	int __platform_register_drivers(struct platform_driver * const *drivers,
-				      unsigned int count, struct module *owner);
+				      unsigned int count, struct module *owner,
+				      const char *mod_name);
 	void platform_unregister_drivers(struct platform_driver * const *drivers,
 					 unsigned int count);
 
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 75b4698d0e58..2b0cc0889386 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -901,11 +901,14 @@ EXPORT_SYMBOL_GPL(platform_device_register_full);
  * __platform_driver_register - register a driver for platform-level devices
  * @drv: platform driver structure
  * @owner: owning module/driver
+ * @mod_name: module name string
  */
-int __platform_driver_register(struct platform_driver *drv, struct module *owner)
+int __platform_driver_register(struct platform_driver *drv, struct module *owner,
+			       const char *mod_name)
 {
 	drv->driver.owner = owner;
 	drv->driver.bus = &platform_bus_type;
+	drv->driver.mod_name = mod_name;
 
 	return driver_register(&drv->driver);
 }
@@ -938,6 +941,7 @@ static int is_bound_to_driver(struct device *dev, void *driver)
  * @drv: platform driver structure
  * @probe: the driver probe routine, probably from an __init section
  * @module: module which will be the owner of the driver
+ * @mod_name: module name string
  *
  * Use this instead of platform_driver_register() when you know the device
  * is not hotpluggable and has already been registered, and you want to
@@ -955,7 +959,8 @@ static int is_bound_to_driver(struct device *dev, void *driver)
  */
 int __init_or_module __platform_driver_probe(struct platform_driver *drv,
 					     int (*probe)(struct platform_device *),
-					     struct module *module)
+					     struct module *module,
+					     const char *mod_name)
 {
 	int retval;
 
@@ -983,7 +988,7 @@ int __init_or_module __platform_driver_probe(struct platform_driver *drv,
 
 	/* temporary section violation during probe() */
 	drv->probe = probe;
-	retval = __platform_driver_register(drv, module);
+	retval = __platform_driver_register(drv, module, mod_name);
 	if (retval)
 		return retval;
 
@@ -1011,6 +1016,7 @@ EXPORT_SYMBOL_GPL(__platform_driver_probe);
  * @data: platform specific data for this platform device
  * @size: size of platform specific data
  * @module: module which will be the owner of the driver
+ * @mod_name: module name string
  *
  * Use this in legacy-style modules that probe hardware directly and
  * register a single platform device and corresponding platform driver.
@@ -1021,7 +1027,7 @@ struct platform_device * __init_or_module
 __platform_create_bundle(struct platform_driver *driver,
 			 int (*probe)(struct platform_device *),
 			 struct resource *res, unsigned int n_res,
-			 const void *data, size_t size, struct module *module)
+			 const void *data, size_t size, struct module *module, const char *mod_name)
 {
 	struct platform_device *pdev;
 	int error;
@@ -1044,7 +1050,7 @@ __platform_create_bundle(struct platform_driver *driver,
 	if (error)
 		goto err_pdev_put;
 
-	error = __platform_driver_probe(driver, probe, module);
+	error = __platform_driver_probe(driver, probe, module, mod_name);
 	if (error)
 		goto err_pdev_del;
 
@@ -1064,6 +1070,7 @@ EXPORT_SYMBOL_GPL(__platform_create_bundle);
  * @drivers: an array of drivers to register
  * @count: the number of drivers to register
  * @owner: module owning the drivers
+ * @mod_name: module name string
  *
  * Registers platform drivers specified by an array. On failure to register a
  * driver, all previously registered drivers will be unregistered. Callers of
@@ -1073,7 +1080,7 @@ EXPORT_SYMBOL_GPL(__platform_create_bundle);
  * Returns: 0 on success or a negative error code on failure.
  */
 int __platform_register_drivers(struct platform_driver * const *drivers,
-				unsigned int count, struct module *owner)
+				unsigned int count, struct module *owner, const char *mod_name)
 {
 	unsigned int i;
 	int err;
@@ -1081,7 +1088,7 @@ int __platform_register_drivers(struct platform_driver * const *drivers,
 	for (i = 0; i < count; i++) {
 		pr_debug("registering platform driver %ps\n", drivers[i]);
 
-		err = __platform_driver_register(drivers[i], owner);
+		err = __platform_driver_register(drivers[i], owner, mod_name);
 		if (err < 0) {
 			pr_err("failed to register platform driver %ps: %d\n",
 			       drivers[i], err);
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 54ad5193b850..94ee24afdc6d 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -1695,7 +1695,8 @@ module_init(coresight_init);
 module_exit(coresight_exit);
 
 int coresight_init_driver_with_owner(const char *drv, struct amba_driver *amba_drv,
-				     struct platform_driver *pdev_drv, struct module *owner)
+				     struct platform_driver *pdev_drv, struct module *owner,
+				     const char *mod_name)
 {
 	int ret;
 
@@ -1705,7 +1706,7 @@ int coresight_init_driver_with_owner(const char *drv, struct amba_driver *amba_d
 		return ret;
 	}
 
-	ret = __platform_driver_register(pdev_drv, owner);
+	ret = __platform_driver_register(pdev_drv, owner, mod_name);
 	if (!ret)
 		return 0;
 
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index cd8fb47a1192..1cf85d772bea 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -692,9 +692,10 @@ coresight_find_output_type(struct coresight_platform_data *pdata,
 			   union coresight_dev_subtype subtype);
 
 int coresight_init_driver_with_owner(const char *drv, struct amba_driver *amba_drv,
-				     struct platform_driver *pdev_drv, struct module *owner);
+				     struct platform_driver *pdev_drv, struct module *owner,
+				     const char *mod_name);
 #define coresight_init_driver(drv, amba_drv, pdev_drv) \
-	coresight_init_driver_with_owner(drv, amba_drv, pdev_drv, THIS_MODULE)
+	coresight_init_driver_with_owner(drv, amba_drv, pdev_drv, THIS_MODULE, KBUILD_MODNAME)
 
 void coresight_remove_driver(struct amba_driver *amba_drv,
 			     struct platform_driver *pdev_drv);
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 975400a472e3..26e6a43358e2 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -293,18 +293,19 @@ struct platform_driver {
  * use a macro to avoid include chaining to get THIS_MODULE
  */
 #define platform_driver_register(drv) \
-	__platform_driver_register(drv, THIS_MODULE)
+	__platform_driver_register(drv, THIS_MODULE, KBUILD_MODNAME)
 extern int __platform_driver_register(struct platform_driver *,
-					struct module *);
+					struct module *, const char *mod_name);
 extern void platform_driver_unregister(struct platform_driver *);
 
 /* non-hotpluggable platform devices may use this so that probe() and
  * its support may live in __init sections, conserving runtime memory.
  */
 #define platform_driver_probe(drv, probe) \
-	__platform_driver_probe(drv, probe, THIS_MODULE)
+	__platform_driver_probe(drv, probe, THIS_MODULE, KBUILD_MODNAME)
 extern int __platform_driver_probe(struct platform_driver *driver,
-		int (*probe)(struct platform_device *), struct module *module);
+		int (*probe)(struct platform_device *), struct module *module,
+		const char *mod_name);
 
 static inline void *platform_get_drvdata(const struct platform_device *pdev)
 {
@@ -368,19 +369,19 @@ static int __init __platform_driver##_init(void) \
 device_initcall(__platform_driver##_init); \
 
 #define platform_create_bundle(driver, probe, res, n_res, data, size) \
-	__platform_create_bundle(driver, probe, res, n_res, data, size, THIS_MODULE)
+	__platform_create_bundle(driver, probe, res, n_res, data, size, THIS_MODULE, KBUILD_MODNAME)
 extern struct platform_device *__platform_create_bundle(
 	struct platform_driver *driver, int (*probe)(struct platform_device *),
 	struct resource *res, unsigned int n_res,
-	const void *data, size_t size, struct module *module);
+	const void *data, size_t size, struct module *module, const char *mod_name);
 
 int __platform_register_drivers(struct platform_driver * const *drivers,
-				unsigned int count, struct module *owner);
+				unsigned int count, struct module *owner, const char *mod_name);
 void platform_unregister_drivers(struct platform_driver * const *drivers,
 				 unsigned int count);
 
 #define platform_register_drivers(drivers, count) \
-	__platform_register_drivers(drivers, count, THIS_MODULE)
+	__platform_register_drivers(drivers, count, THIS_MODULE, KBUILD_MODNAME)
 
 #ifdef CONFIG_SUSPEND
 extern int platform_pm_suspend(struct device *dev);
diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs
index 8917d4ee499f..2d626eecc450 100644
--- a/rust/kernel/platform.rs
+++ b/rust/kernel/platform.rs
@@ -82,7 +82,9 @@ unsafe fn register(
         }
 
         // SAFETY: `pdrv` is guaranteed to be a valid `DriverType`.
-        to_result(unsafe { bindings::__platform_driver_register(pdrv.get(), module.0) })
+        to_result(unsafe {
+            bindings::__platform_driver_register(pdrv.get(), module.0, name.as_char_ptr())
+        })
     }
 
     unsafe fn unregister(pdrv: &Opaque<Self::DriverType>) {

-- 
2.43.0



^ permalink raw reply related

* [PATCH 00/16] media: sun6i-csi/isp MC-centric support and cleanups
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
  To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
	linux-staging
  Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
	Laurent Pinchart, Nicolas Dufresne

This series first introduces some fixes and new formats to v4l2 format
info, one of which we need for the sun6i-csi driver. Support for
MC-centric format enumeration is then added, along with cleanups and
improvements for both the sun6i-csi and sun6i-isp drivers.

The first 4 patches are already reviewed and ready to go and are
included here as a reminder that this series depends on them.

Arash Golgol (4):
  media: sun6i-csi: bridge: Use V4L2 subdev active state
  media: sun6i-csi: capture: Implement vidioc_enum_framesizes
  media: sun6i-mipi-csi2: Use V4L2 subdev active state
  media: sun8i-a83t-mipi-csi2: Use V4L2 subdev active state

Paul Kocialkowski (12):
  media: v4l2-common: Fix NV15_4L4 format info block height
  media: v4l2-common: Add missing tiled format info block sizes
  media: v4l2-common: Add NV12_16L16 pixel format to v4l2 format info
  media: v4l2-common: Add NV12_32L32 pixel format to v4l2 format info
  media: sun6i-csi: Split format validation to a dedicated helper
  media: sun6i-csi: Add support for MC-centric format enumeration
  media: sun6i-csi: Tidy up and unify coding style
  media: sun6i-mipi-csi2: Fix parenthesis alignment
  media: sun6i-isp: Add dummy params link_validate implementation
  media: sun6i-isp: Use V4L2 subdev active state
  media: sun6i-isp: Add support for MC-centric format enumeration
  media: sun6i-isp: Add support for frame size enumeration

 .../sunxi/sun6i-csi/sun6i_csi_bridge.c        | 153 +++++++---------
 .../sunxi/sun6i-csi/sun6i_csi_bridge.h        |   9 -
 .../sunxi/sun6i-csi/sun6i_csi_capture.c       | 168 +++++++++++++-----
 .../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c   | 107 ++++++-----
 .../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.h   |   2 -
 .../sun8i_a83t_mipi_csi2.c                    | 113 ++++++------
 .../sun8i_a83t_mipi_csi2.h                    |   2 -
 drivers/media/v4l2-core/v4l2-common.c         |  12 +-
 .../media/sunxi/sun6i-isp/sun6i_isp_capture.c |  47 ++++-
 .../media/sunxi/sun6i-isp/sun6i_isp_params.c  |  37 +++-
 .../media/sunxi/sun6i-isp/sun6i_isp_params.h  |   4 +-
 .../media/sunxi/sun6i-isp/sun6i_isp_proc.c    | 117 ++++++------
 .../media/sunxi/sun6i-isp/sun6i_isp_proc.h    |   7 -
 13 files changed, 437 insertions(+), 341 deletions(-)

-- 
2.54.0



^ permalink raw reply

* [PATCH 01/16] media: sun6i-csi: bridge: Use V4L2 subdev active state
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
  To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
	linux-staging
  Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
	Laurent Pinchart, Nicolas Dufresne
In-Reply-To: <20260518102451.417971-1-paulk@sys-base.io>

From: Arash Golgol <arash.golgol@gmail.com>

Use the V4L2 subdev active state API to store the active format.
This simplifies the driver not only by dropping the bridge mbus_format
field, but it also allows dropping the bridge lock, replaced with
the state lock.

Previously, capture accessed bridge private state directly. After
moving to framework-managed state, resolve the format through the
subdev pad API.

The sun6i-csi-bridge hardware does not perform any format conversion.
Enforce identical formats on the sink and source pads in the set_fmt()
and init_state() callbacks.

Signed-off-by: Arash Golgol <arash.golgol@gmail.com>
Reviewed-by: Paul Kocialkowski <paulk@sys-base.io>
Tested-by: Paul Kocialkowski <paulk@sys-base.io>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 .../sunxi/sun6i-csi/sun6i_csi_bridge.c        | 155 ++++++++----------
 .../sunxi/sun6i-csi/sun6i_csi_bridge.h        |   9 -
 .../sunxi/sun6i-csi/sun6i_csi_capture.c       |  27 ++-
 3 files changed, 86 insertions(+), 105 deletions(-)

diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
index d006d9dd0170..43a85bcc2ba2 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
@@ -13,26 +13,6 @@
 #include "sun6i_csi_bridge.h"
 #include "sun6i_csi_reg.h"
 
-/* Helpers */
-
-void sun6i_csi_bridge_dimensions(struct sun6i_csi_device *csi_dev,
-				 unsigned int *width, unsigned int *height)
-{
-	if (width)
-		*width = csi_dev->bridge.mbus_format.width;
-	if (height)
-		*height = csi_dev->bridge.mbus_format.height;
-}
-
-void sun6i_csi_bridge_format(struct sun6i_csi_device *csi_dev,
-			     u32 *mbus_code, u32 *field)
-{
-	if (mbus_code)
-		*mbus_code = csi_dev->bridge.mbus_format.code;
-	if (field)
-		*field = csi_dev->bridge.mbus_format.field;
-}
-
 /* Format */
 
 static const struct sun6i_csi_bridge_format sun6i_csi_bridge_formats[] = {
@@ -226,7 +206,8 @@ static void sun6i_csi_bridge_disable(struct sun6i_csi_device *csi_dev)
 }
 
 static void
-sun6i_csi_bridge_configure_parallel(struct sun6i_csi_device *csi_dev)
+sun6i_csi_bridge_configure_parallel(struct sun6i_csi_device *csi_dev,
+				    const struct v4l2_mbus_framefmt *mbus_format)
 {
 	struct device *dev = csi_dev->dev;
 	struct regmap *regmap = csi_dev->regmap;
@@ -234,11 +215,9 @@ sun6i_csi_bridge_configure_parallel(struct sun6i_csi_device *csi_dev)
 		&csi_dev->bridge.source_parallel.endpoint;
 	unsigned char bus_width = endpoint->bus.parallel.bus_width;
 	unsigned int flags = endpoint->bus.parallel.flags;
-	u32 field;
+	u32 field = mbus_format->field;
 	u32 value = SUN6I_CSI_IF_CFG_IF_CSI;
 
-	sun6i_csi_bridge_format(csi_dev, NULL, &field);
-
 	if (field == V4L2_FIELD_INTERLACED ||
 	    field == V4L2_FIELD_INTERLACED_TB ||
 	    field == V4L2_FIELD_INTERLACED_BT)
@@ -317,13 +296,12 @@ sun6i_csi_bridge_configure_parallel(struct sun6i_csi_device *csi_dev)
 }
 
 static void
-sun6i_csi_bridge_configure_mipi_csi2(struct sun6i_csi_device *csi_dev)
+sun6i_csi_bridge_configure_mipi_csi2(struct sun6i_csi_device *csi_dev,
+				     const struct v4l2_mbus_framefmt *mbus_format)
 {
 	struct regmap *regmap = csi_dev->regmap;
 	u32 value = SUN6I_CSI_IF_CFG_IF_MIPI;
-	u32 field;
-
-	sun6i_csi_bridge_format(csi_dev, NULL, &field);
+	u32 field = mbus_format->field;
 
 	if (field == V4L2_FIELD_INTERLACED ||
 	    field == V4L2_FIELD_INTERLACED_TB ||
@@ -335,19 +313,20 @@ sun6i_csi_bridge_configure_mipi_csi2(struct sun6i_csi_device *csi_dev)
 	regmap_write(regmap, SUN6I_CSI_IF_CFG_REG, value);
 }
 
-static void sun6i_csi_bridge_configure_format(struct sun6i_csi_device *csi_dev)
+static void
+sun6i_csi_bridge_configure_format(struct sun6i_csi_device *csi_dev,
+				  const struct v4l2_mbus_framefmt *mbus_format)
 {
 	struct regmap *regmap = csi_dev->regmap;
 	bool capture_streaming = csi_dev->capture.state.streaming;
 	const struct sun6i_csi_bridge_format *bridge_format;
 	const struct sun6i_csi_capture_format *capture_format;
-	u32 mbus_code, field, pixelformat;
+	u32 pixelformat;
+	u32 field = mbus_format->field;
 	u8 input_format, input_yuv_seq, output_format;
 	u32 value = 0;
 
-	sun6i_csi_bridge_format(csi_dev, &mbus_code, &field);
-
-	bridge_format = sun6i_csi_bridge_format_find(mbus_code);
+	bridge_format = sun6i_csi_bridge_format_find(mbus_format->code);
 	if (WARN_ON(!bridge_format))
 		return;
 
@@ -391,16 +370,17 @@ static void sun6i_csi_bridge_configure_format(struct sun6i_csi_device *csi_dev)
 }
 
 static void sun6i_csi_bridge_configure(struct sun6i_csi_device *csi_dev,
-				       struct sun6i_csi_bridge_source *source)
+				       struct sun6i_csi_bridge_source *source,
+				       const struct v4l2_mbus_framefmt *mbus_format)
 {
 	struct sun6i_csi_bridge *bridge = &csi_dev->bridge;
 
 	if (source == &bridge->source_parallel)
-		sun6i_csi_bridge_configure_parallel(csi_dev);
+		sun6i_csi_bridge_configure_parallel(csi_dev, mbus_format);
 	else
-		sun6i_csi_bridge_configure_mipi_csi2(csi_dev);
+		sun6i_csi_bridge_configure_mipi_csi2(csi_dev, mbus_format);
 
-	sun6i_csi_bridge_configure_format(csi_dev);
+	sun6i_csi_bridge_configure_format(csi_dev, mbus_format);
 }
 
 /* V4L2 Subdev */
@@ -415,6 +395,8 @@ static int sun6i_csi_bridge_s_stream(struct v4l2_subdev *subdev, int on)
 	struct sun6i_csi_bridge_source *source;
 	struct v4l2_subdev *source_subdev;
 	struct media_pad *remote_pad;
+	struct v4l2_subdev_state *state;
+	const struct v4l2_mbus_framefmt *mbus_format;
 	int ret;
 
 	/* Source */
@@ -433,6 +415,10 @@ static int sun6i_csi_bridge_s_stream(struct v4l2_subdev *subdev, int on)
 	else
 		source = &bridge->source_mipi_csi2;
 
+	/* Active State */
+
+	state = v4l2_subdev_lock_and_get_active_state(subdev);
+
 	if (!on) {
 		v4l2_subdev_call(source_subdev, video, s_stream, 0);
 		ret = 0;
@@ -443,7 +429,7 @@ static int sun6i_csi_bridge_s_stream(struct v4l2_subdev *subdev, int on)
 
 	ret = pm_runtime_resume_and_get(dev);
 	if (ret < 0)
-		return ret;
+		goto unlock;
 
 	/* Clear */
 
@@ -451,7 +437,9 @@ static int sun6i_csi_bridge_s_stream(struct v4l2_subdev *subdev, int on)
 
 	/* Configure */
 
-	sun6i_csi_bridge_configure(csi_dev, source);
+	mbus_format = v4l2_subdev_state_get_format(state,
+						   SUN6I_CSI_BRIDGE_PAD_SINK);
+	sun6i_csi_bridge_configure(csi_dev, source, mbus_format);
 
 	if (capture_streaming)
 		sun6i_csi_capture_configure(csi_dev);
@@ -472,7 +460,8 @@ static int sun6i_csi_bridge_s_stream(struct v4l2_subdev *subdev, int on)
 	if (ret && ret != -ENOIOCTLCMD)
 		goto disable;
 
-	return 0;
+	ret = 0;
+	goto unlock;
 
 disable:
 	if (capture_streaming)
@@ -482,6 +471,8 @@ static int sun6i_csi_bridge_s_stream(struct v4l2_subdev *subdev, int on)
 
 	pm_runtime_put(dev);
 
+unlock:
+	v4l2_subdev_unlock_state(state);
 	return ret;
 }
 
@@ -504,21 +495,23 @@ sun6i_csi_bridge_mbus_format_prepare(struct v4l2_mbus_framefmt *mbus_format)
 static int sun6i_csi_bridge_init_state(struct v4l2_subdev *subdev,
 				       struct v4l2_subdev_state *state)
 {
-	struct sun6i_csi_device *csi_dev = v4l2_get_subdevdata(subdev);
-	unsigned int pad = SUN6I_CSI_BRIDGE_PAD_SINK;
-	struct v4l2_mbus_framefmt *mbus_format =
-		v4l2_subdev_state_get_format(state, pad);
-	struct mutex *lock = &csi_dev->bridge.lock;
+	unsigned int pad;
 
-	mutex_lock(lock);
+	/*
+	 * This subdev does not perform format conversion,
+	 * initialize both pads identically.
+	 */
+	for (pad = 0; pad < subdev->entity.num_pads; pad++) {
+		struct v4l2_mbus_framefmt *mbus_format;
 
-	mbus_format->code = sun6i_csi_bridge_formats[0].mbus_code;
-	mbus_format->width = 1280;
-	mbus_format->height = 720;
+		mbus_format = v4l2_subdev_state_get_format(state, pad);
 
-	sun6i_csi_bridge_mbus_format_prepare(mbus_format);
+		mbus_format->code = sun6i_csi_bridge_formats[0].mbus_code;
+		mbus_format->width = 1280;
+		mbus_format->height = 720;
 
-	mutex_unlock(lock);
+		sun6i_csi_bridge_mbus_format_prepare(mbus_format);
+	}
 
 	return 0;
 }
@@ -536,53 +529,32 @@ sun6i_csi_bridge_enum_mbus_code(struct v4l2_subdev *subdev,
 	return 0;
 }
 
-static int sun6i_csi_bridge_get_fmt(struct v4l2_subdev *subdev,
-				    struct v4l2_subdev_state *state,
-				    struct v4l2_subdev_format *format)
-{
-	struct sun6i_csi_device *csi_dev = v4l2_get_subdevdata(subdev);
-	struct v4l2_mbus_framefmt *mbus_format = &format->format;
-	struct mutex *lock = &csi_dev->bridge.lock;
-
-	mutex_lock(lock);
-
-	if (format->which == V4L2_SUBDEV_FORMAT_TRY)
-		*mbus_format = *v4l2_subdev_state_get_format(state,
-							     format->pad);
-	else
-		*mbus_format = csi_dev->bridge.mbus_format;
-
-	mutex_unlock(lock);
-
-	return 0;
-}
-
 static int sun6i_csi_bridge_set_fmt(struct v4l2_subdev *subdev,
 				    struct v4l2_subdev_state *state,
 				    struct v4l2_subdev_format *format)
 {
-	struct sun6i_csi_device *csi_dev = v4l2_get_subdevdata(subdev);
-	struct v4l2_mbus_framefmt *mbus_format = &format->format;
-	struct mutex *lock = &csi_dev->bridge.lock;
+	struct v4l2_mbus_framefmt *fmt;
 
-	mutex_lock(lock);
+	/* The format on the source pad always matches the sink pad. */
+	if (format->pad != SUN6I_CSI_BRIDGE_PAD_SINK)
+		return v4l2_subdev_get_fmt(subdev, state, format);
 
-	sun6i_csi_bridge_mbus_format_prepare(mbus_format);
+	sun6i_csi_bridge_mbus_format_prepare(&format->format);
 
-	if (format->which == V4L2_SUBDEV_FORMAT_TRY)
-		*v4l2_subdev_state_get_format(state, format->pad) =
-			*mbus_format;
-	else
-		csi_dev->bridge.mbus_format = *mbus_format;
+	/* Set the format on the sink pad. */
+	fmt = v4l2_subdev_state_get_format(state, format->pad);
+	*fmt = format->format;
 
-	mutex_unlock(lock);
+	/* Propagate the format to the source pad. */
+	fmt = v4l2_subdev_state_get_format(state, SUN6I_CSI_BRIDGE_PAD_SOURCE);
+	*fmt = format->format;
 
 	return 0;
 }
 
 static const struct v4l2_subdev_pad_ops sun6i_csi_bridge_pad_ops = {
 	.enum_mbus_code	= sun6i_csi_bridge_enum_mbus_code,
-	.get_fmt	= sun6i_csi_bridge_get_fmt,
+	.get_fmt	= v4l2_subdev_get_fmt,
 	.set_fmt	= sun6i_csi_bridge_set_fmt,
 };
 
@@ -780,8 +752,6 @@ int sun6i_csi_bridge_setup(struct sun6i_csi_device *csi_dev)
 	};
 	int ret;
 
-	mutex_init(&bridge->lock);
-
 	/* V4L2 Subdev */
 
 	v4l2_subdev_init(subdev, &sun6i_csi_bridge_subdev_ops);
@@ -809,6 +779,12 @@ int sun6i_csi_bridge_setup(struct sun6i_csi_device *csi_dev)
 	if (ret < 0)
 		return ret;
 
+	/* V4L2 Subdev finalize */
+
+	ret = v4l2_subdev_init_finalize(subdev);
+	if (ret < 0)
+		goto error_media_entity;
+
 	/* V4L2 Subdev */
 
 	if (csi_dev->isp_available)
@@ -818,7 +794,7 @@ int sun6i_csi_bridge_setup(struct sun6i_csi_device *csi_dev)
 
 	if (ret) {
 		dev_err(dev, "failed to register v4l2 subdev: %d\n", ret);
-		goto error_media_entity;
+		goto error_subdev_finalize;
 	}
 
 	/* V4L2 Async */
@@ -852,6 +828,9 @@ int sun6i_csi_bridge_setup(struct sun6i_csi_device *csi_dev)
 	else
 		v4l2_device_unregister_subdev(subdev);
 
+error_subdev_finalize:
+	v4l2_subdev_cleanup(subdev);
+
 error_media_entity:
 	media_entity_cleanup(&subdev->entity);
 
@@ -868,5 +847,7 @@ void sun6i_csi_bridge_cleanup(struct sun6i_csi_device *csi_dev)
 
 	v4l2_device_unregister_subdev(subdev);
 
+	v4l2_subdev_cleanup(subdev);
+
 	media_entity_cleanup(&subdev->entity);
 }
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h
index 44653b38f722..a5b0a6f064dd 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h
@@ -42,20 +42,11 @@ struct sun6i_csi_bridge {
 	struct v4l2_subdev		subdev;
 	struct v4l2_async_notifier	notifier;
 	struct media_pad		pads[2];
-	struct v4l2_mbus_framefmt	mbus_format;
-	struct mutex			lock; /* Mbus format lock. */
 
 	struct sun6i_csi_bridge_source	source_parallel;
 	struct sun6i_csi_bridge_source	source_mipi_csi2;
 };
 
-/* Helpers */
-
-void sun6i_csi_bridge_dimensions(struct sun6i_csi_device *csi_dev,
-				 unsigned int *width, unsigned int *height);
-void sun6i_csi_bridge_format(struct sun6i_csi_device *csi_dev,
-			     u32 *mbus_code, u32 *field);
-
 /* Format */
 
 const struct sun6i_csi_bridge_format *
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
index 65879f4802c0..d90abba21309 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
@@ -888,14 +888,19 @@ static int sun6i_csi_capture_link_validate(struct media_link *link)
 		media_entity_to_video_device(link->sink->entity);
 	struct sun6i_csi_device *csi_dev = video_get_drvdata(video_dev);
 	struct v4l2_device *v4l2_dev = csi_dev->v4l2_dev;
+	struct v4l2_subdev *src_subdev =
+		media_entity_to_v4l2_subdev(link->source->entity);
 	const struct sun6i_csi_capture_format *capture_format;
 	const struct sun6i_csi_bridge_format *bridge_format;
 	unsigned int capture_width, capture_height;
-	unsigned int bridge_width, bridge_height;
 	const struct v4l2_format_info *format_info;
+	struct v4l2_subdev_format src_fmt = {
+		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
+		.pad = link->source->index
+	};
 	u32 pixelformat, capture_field;
-	u32 mbus_code, bridge_field;
 	bool match;
+	int ret;
 
 	sun6i_csi_capture_dimensions(csi_dev, &capture_width, &capture_height);
 
@@ -904,19 +909,22 @@ static int sun6i_csi_capture_link_validate(struct media_link *link)
 	if (WARN_ON(!capture_format))
 		return -EINVAL;
 
-	sun6i_csi_bridge_dimensions(csi_dev, &bridge_width, &bridge_height);
+	/* Resolve csi bridge format. */
+	ret = v4l2_subdev_call(src_subdev, pad, get_fmt, NULL, &src_fmt);
+	if (ret)
+		return ret;
 
-	sun6i_csi_bridge_format(csi_dev, &mbus_code, &bridge_field);
-	bridge_format = sun6i_csi_bridge_format_find(mbus_code);
+	bridge_format = sun6i_csi_bridge_format_find(src_fmt.format.code);
 	if (WARN_ON(!bridge_format))
 		return -EINVAL;
 
 	/* No cropping/scaling is supported. */
-	if (capture_width != bridge_width || capture_height != bridge_height) {
+	if (capture_width != src_fmt.format.width ||
+	    capture_height != src_fmt.format.height) {
 		v4l2_err(v4l2_dev,
 			 "invalid input/output dimensions: %ux%u/%ux%u\n",
-			 bridge_width, bridge_height, capture_width,
-			 capture_height);
+			 src_fmt.format.width, src_fmt.format.height,
+			 capture_width, capture_height);
 		return -EINVAL;
 	}
 
@@ -947,7 +955,8 @@ static int sun6i_csi_capture_link_validate(struct media_link *link)
 	/* With raw input mode, we need a 1:1 match between input and output. */
 	if (bridge_format->input_format == SUN6I_CSI_INPUT_FMT_RAW ||
 	    capture_format->input_format_raw) {
-		match = sun6i_csi_capture_format_match(pixelformat, mbus_code);
+		match = sun6i_csi_capture_format_match(pixelformat,
+						       src_fmt.format.code);
 		if (!match)
 			goto invalid;
 	}
-- 
2.54.0



^ permalink raw reply related

* [PATCH 02/16] media: sun6i-csi: capture: Implement vidioc_enum_framesizes
From: Paul Kocialkowski @ 2026-05-18 10:24 UTC (permalink / raw)
  To: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
	linux-staging
  Cc: Paul Kocialkowski, Mauro Carvalho Chehab, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman, Arash Golgol,
	Laurent Pinchart, Nicolas Dufresne
In-Reply-To: <20260518102451.417971-1-paulk@sys-base.io>

From: Arash Golgol <arash.golgol@gmail.com>

Report the stepwise frame size range supported by the CSI capture
hardware for the pixel formats exposed by the driver.

The hardware does not perform scaling and accepts any even width and
height within the reported limits.

Signed-off-by: Arash Golgol <arash.golgol@gmail.com>
Reviewed-by: Paul Kocialkowski <paulk@sys-base.io>
Tested-by: Paul Kocialkowski <paulk@sys-base.io>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 .../sunxi/sun6i-csi/sun6i_csi_capture.c       | 22 +++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
index d90abba21309..f788b4234673 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c
@@ -738,6 +738,27 @@ static int sun6i_csi_capture_enum_fmt(struct file *file, void *priv,
 	return 0;
 }
 
+static int sun6i_csi_capture_enum_framesize(struct file *file, void *fh,
+					    struct v4l2_frmsizeenum *fsize)
+{
+	if (fsize->index)
+		return -EINVAL;
+
+	/* Only accept format in map table. */
+	if (!sun6i_csi_capture_format_find(fsize->pixel_format))
+		return -EINVAL;
+
+	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+	fsize->stepwise.min_width = SUN6I_CSI_CAPTURE_WIDTH_MIN;
+	fsize->stepwise.max_width = SUN6I_CSI_CAPTURE_WIDTH_MAX;
+	fsize->stepwise.min_height = SUN6I_CSI_CAPTURE_HEIGHT_MIN;
+	fsize->stepwise.max_height = SUN6I_CSI_CAPTURE_HEIGHT_MAX;
+	fsize->stepwise.step_width = 2;
+	fsize->stepwise.step_height = 2;
+
+	return 0;
+}
+
 static int sun6i_csi_capture_g_fmt(struct file *file, void *priv,
 				   struct v4l2_format *format)
 {
@@ -805,6 +826,7 @@ static const struct v4l2_ioctl_ops sun6i_csi_capture_ioctl_ops = {
 	.vidioc_querycap		= sun6i_csi_capture_querycap,
 
 	.vidioc_enum_fmt_vid_cap	= sun6i_csi_capture_enum_fmt,
+	.vidioc_enum_framesizes		= sun6i_csi_capture_enum_framesize,
 	.vidioc_g_fmt_vid_cap		= sun6i_csi_capture_g_fmt,
 	.vidioc_s_fmt_vid_cap		= sun6i_csi_capture_s_fmt,
 	.vidioc_try_fmt_vid_cap		= sun6i_csi_capture_try_fmt,
-- 
2.54.0



^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox