Linux Documentation
 help / color / mirror / Atom feed
* Re: [PATCH V10 0/8] dax: prepare for famfs
From: Alison Schofield @ 2026-04-13 22:41 UTC (permalink / raw)
  To: John Groves
  Cc: John Groves, Miklos Szeredi, Dan Williams, Bernd Schubert,
	John Groves, Jonathan Corbet, Shuah Khan, Vishal Verma,
	Dave Jiang, Matthew Wilcox, Jan Kara, Alexander Viro,
	David Hildenbrand, Christian Brauner, Darrick J . Wong,
	Randy Dunlap, Jeff Layton, Amir Goldstein, Jonathan Cameron,
	Stefan Hajnoczi, Joanne Koong, Josef Bacik, Bagas Sanjaya,
	Chen Linxuan, James Morse, Fuad Tabba, Sean Christopherson,
	Shivank Garg, Ackerley Tng, Gregory Price, Aravind Ramesh,
	Ajay Joshi, venkataravis@micron.com, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org, nvdimm@lists.linux.dev,
	linux-cxl@vger.kernel.org, linux-fsdevel@vger.kernel.org
In-Reply-To: <acrpbBt5UsWEiEbm@aschofie-mobl2.lan>

On Mon, Mar 30, 2026 at 02:21:48PM -0700, Alison Schofield wrote:
> On Fri, Mar 27, 2026 at 09:03:26PM +0000, John Groves wrote:
> > From: John Groves <john@groves.net>
> > 
> > This patch series along with the bundled patches to fuse are available
> > as a git tag at [0].
> > 
> > Dropped the "bundle" thread. If this submission goes smoothly, I'll update
> > the fuse patches to v10 (very little change there as yet).
> > 
> > Changes v9 -> v10
> > - Minor modernizations per comments from (mostly) Jonathan
> > - Minor Kconfig simplification
> > - bus.c:dax_match_type(): don't make fsdev_dax eligible for automatic binding
> >   where devdax would otherwise bind
> > - dax-private.h: add missing kerneldoc comment for field cached_size in
> >   struct dev_dax_range (thanks Dave)
> > - fsdev_write_dax(): s/pmem_addr/addr/ (thanks Dave)
> > - include/linux/dax.h: remove a spuriously-added declaration of inode_dax()
> >   (thanks Jonathan)
> > 
> > Description:
> > 
> > This patch series introduces the required dax support for famfs.
> > Previous versions of the famfs series included both dax and fuse patches.
> > This series separates them into separate patch series' (and the fuse
> > series dependends on this dax series).
> > 
> > The famfs user space code can be found at [1]
> > 
> > Dax Overview:
> > 
> > This series introduces a new "famfs mode" of devdax, whose driver is
> > drivers/dax/fsdev.c. This driver supports dax_iomap_rw() and
> > dax_iomap_fault() calls against a character dax instance. A dax device
> > now can be converted among three modes: 'system-ram', 'devdax' and
> > 'famfs' via daxctl or sysfs (e.g. unbind devdax and bind famfs instead).
> > 
> > In famfs mode, a dax device initializes its pages consistent with the
> > fsdaxmode of pmem. Raw read/write/mmap are not supported in this mode,
> > but famfs is happy in this mode - using dax_iomap_rw() for read/write and
> > dax_iomap_fault() for mmap faults.
> > 
> 
> Here's what I found:
> 
> famfs-v10 on 7.0-rc5 + ndctl v84:
> 	dax suite all pass 13/13, so no regression appears
> 
> famfs-v10 on 7.0-rc5 +
> (ndctl v84 w https://github.com/jagalactic/ndctl/tree/famfs
> top 3 patches + edit daxctl-famfs.sh to use cxl-test:
> 
> 	existing dax suite keeps passing
> 	daxctl-famfs.sh oops w the new test at # Restore original mode"
> 	seems easy to repoduce, maybe cannot go back to system-ram???

My stack trace differed from Ira's.  I hit:

[   88.991865] probe of dax0.0 returned 0 after 2371506 usecs
[   88.996717] page: refcount:0 mapcount:1 mapping:0000000000000000 index:0x0 pfn:0x3ff028000
[   88.997592] BUG: unable to handle page fault for address: ffffc9000f4c8033
[   88.998256] #PF: supervisor read access in kernel mode
[   88.998728] #PF: error_code(0x0000) - not-present page
[   88.999254] PGD 80a067 P4D 80a067 PUD 193e067 PMD 79baf067 PTE 0
[   88.999799] Oops: Oops: 0000 [#1] SMP NOPTI
[   89.000253] CPU: 5 UID: 0 PID: 1476 Comm: daxctl Tainted: G           O        7.0.0-rc5+ #182 PREEMPT(full) 
[   89.001092] Tainted: [O]=OOT_MODULE
[   89.001630] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
[   89.002345] RIP: 0010:is_free_buddy_page+0x39/0x60
[   89.002816] Code: 00 00 00 48 c1 fe 06 eb 0a 48 83 c1 01 48 83 f9 0b 74 30 44 89 c0 48 89 fa d3 e0 83 e8 01 48 98 48 21 f0 48 c1 e0 06 48 29 c2 <80> 7a 33 f0 75 d9 48 8b 42 28 48 39 c8 72 d0 b8 01 00 00 00 e9 ce
[   89.004504] RSP: 0018:ffffc9000f4cf828 EFLAGS: 00010286
[   89.005039] RAX: 0000000000007a80 RBX: ffffc9000f4cf8a0 RCX: 0000000000000009
[   89.005674] RDX: ffffc9000f4c8000 RSI: ffffff7c003d33ea RDI: ffffc9000f4cfa80
[   89.006350] RBP: ffffc9000f4cf838 R08: 0000000000000001 R09: 00000000ffefffff
[   89.007000] R10: ffffc9000f4cfa38 R11: ffff888376ffe000 R12: ffffc9000f4cfa80
[   89.007673] R13: ffffc9000f4cf9a0 R14: 0000000000000006 R15: 0000000000000001
[   89.008395] FS:  00007f3fbca2e7c0(0000) GS:ffff8881fa75f000(0000) knlGS:0000000000000000
[   89.009156] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   89.009715] CR2: ffffc9000f4c8033 CR3: 000000012f638003 CR4: 0000000000370ef0
[   89.010447] Call Trace:
[   89.010767]  <TASK>
[   89.011083]  ? set_ps_flags.constprop.0+0x3c/0x70
[   89.011559]  snapshot_page+0x2ca/0x330
[   89.011974]  __dump_page+0x2e/0x380
[   89.012362]  ? up+0x5a/0x90
[   89.012704]  dump_page+0x16/0x50
[   89.013108]  ? dump_page+0x16/0x50
[   89.013489]  __get_pfnblock_flags_mask+0x6f/0xd0
[   89.013958]  get_pfnblock_migratetype+0xe/0x30
[   89.014412]  __dump_page+0x15b/0x380
[   89.014816]  dump_page+0x16/0x50
[   89.015210]  ? dump_page+0x16/0x50
[   89.015587]  __set_pfnblock_flags_mask.constprop.0+0x6f/0xf0
[   89.016195]  init_pageblock_migratetype+0x39/0x60
[   89.016692]  memmap_init_range+0x165/0x290
[   89.017205]  move_pfn_range_to_zone+0xed/0x200
[   89.017688]  mhp_init_memmap_on_memory+0x23/0xb0
[   89.018223]  memory_subsys_online+0x127/0x1a0
[   89.018693]  device_online+0x4d/0x90
[   89.019149]  state_store+0x96/0xa0
[   89.019552]  dev_attr_store+0x12/0x30
[   89.019975]  sysfs_kf_write+0x48/0x70
[   89.020381]  kernfs_fop_write_iter+0x160/0x210
[   89.020876]  vfs_write+0x261/0x500
[   89.021311]  ksys_write+0x5c/0xf0
[   89.021701]  __x64_sys_write+0x14/0x20
[   89.022180]  x64_sys_call+0x1cb7/0x2010
[   89.022640]  do_syscall_64+0xb1/0x560
[   89.023096]  entry_SYSCALL_64_after_hwframe+0x71/0x79
[   89.023615] RIP: 0033:0x7f3fbc901c37
[   89.024050] Code: 0f 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 00 f3 0f 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 51 c3 48 83 ec 28 48 89 54 24 18 48 89 74 24
[   89.025768] RSP: 002b:00007ffdbdf63c68 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
[   89.026517] RAX: ffffffffffffffda RBX: 00007ffdbdf64228 RCX: 00007f3fbc901c37
[   89.027280] RDX: 000000000000000f RSI: 00007f3fbcb554de RDI: 0000000000000004
[   89.027934] RBP: 00007ffdbdf63ca0 R08: 0000000000000000 R09: 0000000000000073
[   89.028610] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
[   89.029337] R13: 00007ffdbdf64260 R14: 0000000000414da0 R15: 00007f3fbcb9b000
[   89.030051]  </TASK>
[   89.030364] Modules linked in: cxl_test(O) cxl_acpi(O) cxl_pmem(O) device_dax(O) fsdev_dax kmem dax_pmem(O) nd_pmem(O) dax_cxl nd_btt(O) nd_e820(O) nfit(O) cxl_mock_mem(O) cxl_mem(O) cxl_port(O) cxl_mock(O) libnvdimm(O) nfit_test_iomap(O) cxl_core(O) fwctl [last unloaded: cxl_pmem(O)]
[   89.032575] CR2: ffffc9000f4c8033
[   89.032960] ---[ end trace 0000000000000000 ]---
[   89.033460] RIP: 0010:is_free_buddy_page+0x39/0x60
[   89.033948] Code: 00 00 00 48 c1 fe 06 eb 0a 48 83 c1 01 48 83 f9 0b 74 30 44 89 c0 48 89 fa d3 e0 83 e8 01 48 98 48 21 f0 48 c1 e0 06 48 29 c2 <80> 7a 33 f0 75 d9 48 8b 42 28 48 39 c8 72 d0 b8 01 00 00 00 e9 ce
[   89.035645] RSP: 0018:ffffc9000f4cf828 EFLAGS: 00010286
[   89.036235] RAX: 0000000000007a80 RBX: ffffc9000f4cf8a0 RCX: 0000000000000009
[   89.036910] RDX: ffffc9000f4c8000 RSI: ffffff7c003d33ea RDI: ffffc9000f4cfa80
[   89.037588] RBP: ffffc9000f4cf838 R08: 0000000000000001 R09: 00000000ffefffff
[   89.038310] R10: ffffc9000f4cfa38 R11: ffff888376ffe000 R12: ffffc9000f4cfa80
[   89.039008] R13: ffffc9000f4cf9a0 R14: 0000000000000006 R15: 0000000000000001
[   89.039710] FS:  00007f3fbca2e7c0(0000) GS:ffff8881fa75f000(0000) knlGS:0000000000000000
[   89.040506] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   89.041129] CR2: ffffc9000f4c8033 CR3: 000000012f638003 CR4: 0000000000370ef0
[   89.041836] note: daxctl[1476] exited with irqs disabled
 


> 
> Let me know if you need more info.
> 
> -- Alison
> 
> 

^ permalink raw reply

* Re: [PATCH v10 12/21] gpu: nova-core: mm: Add unified page table entry wrapper enums
From: John Hubbard @ 2026-04-13 22:50 UTC (permalink / raw)
  To: Joel Fernandes, Danilo Krummrich
  Cc: Eliot Courtney, linux-kernel, Miguel Ojeda, Boqun Feng, Gary Guo,
	Bjorn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Dave Airlie, Daniel Almeida, Koen Koning, dri-devel,
	rust-for-linux, Nikola Djukic, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Jonathan Corbet,
	Alex Deucher, Christian Koenig, Jani Nikula, Joonas Lahtinen,
	Vivi Rodrigo, Tvrtko Ursulin, Rui Huang, Matthew Auld,
	Matthew Brost, Lucas De Marchi, Thomas Hellstrom, Helge Deller,
	Alex Gaynor, Boqun Feng, Alistair Popple, Timur Tabi, Edwin Peer,
	Alexandre Courbot, Andrea Righi, Andy Ritger, Zhi Wang,
	Balbir Singh, Philipp Stanner, Elle Rhumsaa, Alexey Ivanov,
	linux-doc, amd-gfx, intel-gfx, intel-xe, linux-fbdev
In-Reply-To: <56526b93-72a3-4b07-9aa7-7822bd561cd5@nvidia.com>

On 4/13/26 3:27 PM, Joel Fernandes wrote:
> 
> 
> On 4/13/2026 4:10 PM, Joel Fernandes wrote:
>> Hi Danilo,
>>
>> On 4/9/2026 7:00 AM, Danilo Krummrich wrote:
>>> On Thu Apr 9, 2026 at 12:33 PM CEST, Joel Fernandes wrote:
>>>> Since it is 3 against 1 here, I rest my case :-).
>>>
>>> That's not how I'd view it. :)
>>>
>>> Anyways, in case I'm included in "3", that's not my position. My point was to
>>> ensure we keep discussing advantages and disadvantages on their merits, as I
>>> think you both have good points.
>>
>> Heh, yes I actually *did not* include you in the 3 since you sounded to be open
>> to both. ;-)
>>
>>>
>>>> I am still in disagreement since I do not see much benefit (that is why I said
>>>> pointless above).
>>>
>>> That is fair -- in this case please explain why the advantages pointed out by
>>> others are not worth it, propose something that picks up the best of both
>>> worlds, etc.
>>>
>>> You can also turn it around and ask people whether they can tweak their counter
>>> proposal to get rid of specific parts you dislike for a reason.
>>>
>>> IOW, keep the ball rolling, so we can come up with the best possible solution.
>>
>> Good advice, thanks! I will try to come up with something that is acceptable to
>> everyone and we can further debate pros/cons on v11.
>>
>> There are some merits on the alternative proposal from Eliot/Alex that I'd like
>> to explore while seeing if I can keep some of the merits in mine as well.
> I think I found a nice approach. IMO the MMU version dispatch does not belong in
> Vmm/BarUser layers. Those are version-independent code. However I agree that
> doing version dispatch at every low-level page table operation is a bit heavy on
> matches (if we put the MMIO overhead counter-argument aside).
> 
> So how about the following approach?
> 
> PtWalk, PtMap and everything below it are monomorphized. Vmm and BarUser are
> not. Version dispatch is handled on PtWalk and PtMap entry points.

Conceptually it sounds pretty good.

> 
> I think it makes it cleaner and splits the code up better too and the
> organizations makes sense because the version differences are related to page
> tables, not to generic concepts like Vmm and Bar.
> 
> Thoughts? Here is a preview:
> https://git.kernel.org/pub/scm/linux/kernel/git/jfern/linux.git/commit/?h=pt-traits-v2&id=ff22ba64f729f9f73258777231763a7b9804123b
> 

Probably impractical to review that here, so let's do the review in
a v11 posting, I think.

thanks,
-- 
John Hubbard


^ permalink raw reply

* Re: maintainer profiles
From: Randy Dunlap @ 2026-04-13 23:08 UTC (permalink / raw)
  To: Dan Williams, Jonathan Corbet, Linux Documentation,
	Linux Kernel Mailing List
  Cc: Linux Kernel Workflows
In-Reply-To: <69dd6299440be_147c801005b@djbw-dev.notmuch>

Hi,

On 4/13/26 2:39 PM, Dan Williams wrote:
> Jonathan Corbet wrote:
>> Randy Dunlap <rdunlap@infradead.org> writes:
>>
>>> Hi,
>>>
>>> Is there supposed to be a difference (or distinction) in the contents of
>>>
>>> Documentation/process/maintainer-handbooks.rst
>>> and
>>> Documentation/maintainer/maintainer-entry-profile.rst
>>> ?
>>>
>>> Can they be combined into one location?
>>
>> Late to the party, sorry ... the original idea, I believe, was that
>> maintainer-handbooks.rst would be for developers looking for a guidebook
>> for a specific subsystem, while maintainer-entry-profile.rst was about
>> how maintainers themselves should write their subsystem guide.
>> Doubtless things have drifted since then...  But the intended audiences
>> were different, so it might be good to think about bringing them back
>> into focus.
> 
> Right, I think something (roughly / hand-wavy) like the below is the
> intent. However, as I write that I notice that the combined list is a
> bit of a mess. I also notice that there are more "P:" entries in
> MAINTAINERS than there are entries in this maintainer-handbooks.rst
> list.
> 
> So this probably wants to be a script that can build Documentation links
> from MAINTAINERS, or otherwise provide a script for developers to query
> a kernel tree for additional submission guides. It is probably not as
> important for the built docs to link all guides as it is for developers
> (or their agents) to live query a tree they are developing against.
> 
> Note the problem goes both ways, there are P: entries not in the
> combined handbook list, like the Security subsystem, and there are
> handbook entries without a P:, like the Tip tree.

I had not (and have not) checked on the P: entries.
However, this patch is close to where I already was, but it (and my
patch) causes some problems. (I dropped the duplicate
maintainer-soc-clean-dts entry.)

E.g., maintainer-handbooks uses :numbered:, but the Media and XFS
entries are already numbered, so Sphinx complains about that.
I think that numbering isn't needed, so I tried dropping that,
but the Media and XFS entries are still numbered, so it looks
messy, but that may be OK (better) than 2 mixed lists.

I'm not finding a satisfactory answer here (yet).


diff --git a/Documentation/maintainer/maintainer-entry-profile.rst b/Documentation/maintainer/maintainer-entry-profile.rst> index 6020d188e13d..58e2af333692 100644
> --- a/Documentation/maintainer/maintainer-entry-profile.rst
> +++ b/Documentation/maintainer/maintainer-entry-profile.rst
> @@ -92,24 +92,8 @@ full series, or privately send a reminder email. This section might also
>  list how review works for this code area and methods to get feedback
>  that are not directly from the maintainer.
>  
> -Existing profiles
> ------------------
> -
> -For now, existing maintainer profiles are listed here; we will likely want
> -to do something different in the near future.
> -
> -.. toctree::
> -   :maxdepth: 1
> -
> -   ../doc-guide/maintainer-profile
> -   ../nvdimm/maintainer-entry-profile
> -   ../arch/riscv/patch-acceptance
> -   ../process/maintainer-soc
> -   ../process/maintainer-soc-clean-dts
> -   ../driver-api/media/maintainer-entry-profile
> -   ../process/maintainer-netdev
> -   ../driver-api/vfio-pci-device-specific-driver-acceptance
> -   ../nvme/feature-and-quirk-policy
> -   ../filesystems/nfs/nfsd-maintainer-entry-profile
> -   ../filesystems/xfs/xfs-maintainer-entry-profile
> -   ../mm/damon/maintainer-profile
> +Maintainer Handbooks
> +--------------------
> +
> +For examples of other subsystem handbooks see
> +Documentation/process/maintainer-handbooks.rst.
> diff --git a/Documentation/process/maintainer-handbooks.rst b/Documentation/process/maintainer-handbooks.rst
> index 976391cec528..bc9299a04b1f 100644
> --- a/Documentation/process/maintainer-handbooks.rst
> +++ b/Documentation/process/maintainer-handbooks.rst
> @@ -9,14 +9,33 @@ The purpose of this document is to provide subsystem specific information
>  which is supplementary to the general development process handbook
>  :ref:`Documentation/process <development_process_main>`.
>  
> +For developers, see below for all the known subsystem specific guides.
> +If the subsystem you are contributing to does not have a guide listed
> +here, it is fair to seek clarification of questions raised in
> +Documentation/maintainer/maintainer-entry-profile.rst.
> +
> +For maintainers, consider documenting additional requirements and
> +expectations if submissions routinely overlook specific submission
> +criteria. See Documentation/maintainer/maintainer-entry-profile.rst.
> +
>  Contents:
>  
>  .. toctree::
>     :numbered:
>     :maxdepth: 2
>  
> +   maintainer-kvm-x86
>     maintainer-netdev
>     maintainer-soc
>     maintainer-soc-clean-dts
> +   maintainer-soc-clean-dts
>     maintainer-tip
> -   maintainer-kvm-x86
> +   ../arch/riscv/patch-acceptance
> +   ../doc-guide/maintainer-profile
> +   ../driver-api/media/maintainer-entry-profile
> +   ../driver-api/vfio-pci-device-specific-driver-acceptance
> +   ../filesystems/nfs/nfsd-maintainer-entry-profile
> +   ../filesystems/xfs/xfs-maintainer-entry-profile
> +   ../mm/damon/maintainer-profile
> +   ../nvdimm/maintainer-entry-profile
> +   ../nvme/feature-and-quirk-policy
> 
> 

-- 
~Randy


^ permalink raw reply

* Re: [PATCH] docs: xforms_lists: allow __maybe_unused in func parameters
From: Bart Van Assche @ 2026-04-13 23:36 UTC (permalink / raw)
  To: Randy Dunlap, linux-kernel
  Cc: kernel test robot, Jonathan Corbet, Shuah Khan, linux-doc,
	Mauro Carvalho Chehab
In-Reply-To: <20260411233526.3909303-1-rdunlap@infradead.org>

On 4/11/26 4:35 PM, Randy Dunlap wrote:
> --- linext-2026-0410.orig/tools/lib/python/kdoc/xforms_lists.py
> +++ linext-2026-0410/tools/lib/python/kdoc/xforms_lists.py
> @@ -93,6 +93,7 @@ class CTransforms:
>           (CMatch("__weak"), ""),
>           (CMatch("__sched"), ""),
>           (CMatch("__always_unused"), ""),
> +        (CMatch("__maybe_unused"), ""),
>           (CMatch("__printf"), ""),
>           (CMatch("__(?:re)?alloc_size"), ""),
>           (CMatch("__diagnose_as"), ""),

Thanks!

Reviewed-by: Bart Van Assche <bvanassche@acm.org>


^ permalink raw reply

* Re: [PATCH net-next v05 1/6] hinic3: Add ethtool queue ops
From: Jakub Kicinski @ 2026-04-14  0:18 UTC (permalink / raw)
  To: Fan Gong
  Cc: Zhu Yikai, netdev, David S. Miller, Eric Dumazet, Paolo Abeni,
	Simon Horman, Andrew Lunn, Ioana Ciornei, Mohsin Bashir,
	linux-kernel, linux-doc, luosifu, Xin Guo, Zhou Shuai, Wu Like,
	Shi Jing, Zheng Jiezhen, Maxime Chevallier
In-Reply-To: <157d5cc6e757ffa77eee01dfdc3f2159dc97905f.1775711066.git.zhuyikai1@h-partners.com>

On Sat, 11 Apr 2026 11:36:59 +0800 Fan Gong wrote:
>   Implement following ethtool callback function:
> .get_ringparam
> .set_ringparam
> 
>   These callbacks allow users to utilize ethtool for detailed
> queue depth configuration and monitoring.

> +static int hinic3_check_ringparam_valid(struct net_device *netdev,
> +					const struct ethtool_ringparam *ring)
> +{
> +	if (ring->rx_jumbo_pending || ring->rx_mini_pending) {

Can driver actually be called with non-zero values if max is not set?

> +		netdev_err(netdev, "Unsupported rx_jumbo_pending/rx_mini_pending\n");
> +		return -EINVAL;
> +	}


> +	if (ring->tx_pending > HINIC3_MAX_TX_QUEUE_DEPTH ||
> +	    ring->tx_pending < HINIC3_MIN_QUEUE_DEPTH ||
> +	    ring->rx_pending > HINIC3_MAX_RX_QUEUE_DEPTH ||
> +	    ring->rx_pending < HINIC3_MIN_QUEUE_DEPTH) {

similar question - do you need to check the upper bound?
kernel should check the input against max returned by .get

> +		netdev_err(netdev,

please use extack for errors

> +			   "Queue depth out of range tx[%d-%d] rx[%d-%d]\n",
> +			   HINIC3_MIN_QUEUE_DEPTH, HINIC3_MAX_TX_QUEUE_DEPTH,
> +			   HINIC3_MIN_QUEUE_DEPTH, HINIC3_MAX_RX_QUEUE_DEPTH);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int hinic3_set_ringparam(struct net_device *netdev,
> +				struct ethtool_ringparam *ring,
> +				struct kernel_ethtool_ringparam *kernel_ring,
> +				struct netlink_ext_ack *extack)
> +{
> +	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
> +	struct hinic3_dyna_txrxq_params q_params = {};
> +	u32 new_sq_depth, new_rq_depth;
> +	int err;
> +
> +	err = hinic3_check_ringparam_valid(netdev, ring);
> +	if (err)
> +		return err;
> +
> +	new_sq_depth = 1U << ilog2(ring->tx_pending);
> +	new_rq_depth = 1U << ilog2(ring->rx_pending);
> +	if (new_sq_depth == nic_dev->q_params.sq_depth &&
> +	    new_rq_depth == nic_dev->q_params.rq_depth)
> +		return 0;
> +
> +	if (new_sq_depth != ring->tx_pending)
> +		netdev_info(netdev, "Requested Tx depth trimmed to %d\n",
> +			    new_sq_depth);

please use extack for warnings

> +	if (new_rq_depth != ring->rx_pending)
> +		netdev_info(netdev, "Requested Rx depth trimmed to %d\n",
> +			    new_rq_depth);
> +
> +	netdev_info(netdev, "Change Tx/Rx ring depth from %u/%u to %u/%u\n",
> +		    nic_dev->q_params.sq_depth, nic_dev->q_params.rq_depth,
> +		    new_sq_depth, new_rq_depth);
> +
> +	if (!netif_running(netdev)) {
> +		hinic3_update_qp_depth(netdev, new_sq_depth, new_rq_depth);
> +	} else {
> +		q_params = nic_dev->q_params;
> +		q_params.sq_depth = new_sq_depth;
> +		q_params.rq_depth = new_rq_depth;
> +
> +		err = hinic3_change_channel_settings(netdev, &q_params);
> +		if (err) {
> +			netdev_err(netdev, "Failed to change channel settings\n");
> +			return err;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
>  static const struct ethtool_ops hinic3_ethtool_ops = {
>  	.supported_coalesce_params      = ETHTOOL_COALESCE_USECS |
>  					  ETHTOOL_COALESCE_PKT_RATE_RX_USECS,
> @@ -417,6 +516,8 @@ static const struct ethtool_ops hinic3_ethtool_ops = {
>  	.get_msglevel                   = hinic3_get_msglevel,
>  	.set_msglevel                   = hinic3_set_msglevel,
>  	.get_link                       = ethtool_op_get_link,
> +	.get_ringparam                  = hinic3_get_ringparam,
> +	.set_ringparam                  = hinic3_set_ringparam,
>  };

> diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_main.c b/drivers/net/ethernet/huawei/hinic3/hinic3_main.c
> index 0a888fe4c975..3b470978714a 100644
> --- a/drivers/net/ethernet/huawei/hinic3/hinic3_main.c
> +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_main.c
> @@ -179,6 +179,8 @@ static int hinic3_sw_init(struct net_device *netdev)
>  	int err;
>  
>  	mutex_init(&nic_dev->port_state_mutex);
> +	mutex_init(&nic_dev->channel_cfg_lock);

Why do you need this mutex?
Aren't all the places you take it under rtnl_lock anyway?

> +	spin_lock_init(&nic_dev->channel_res_lock);
>  
>  	nic_dev->q_params.sq_depth = HINIC3_SQ_DEPTH;
>  	nic_dev->q_params.rq_depth = HINIC3_RQ_DEPTH;
> @@ -314,6 +316,15 @@ static void hinic3_link_status_change(struct net_device *netdev,
>  				      bool link_status_up)
>  {
>  	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
> +	unsigned long flags;
> +	bool valid;
> +
> +	spin_lock_irqsave(&nic_dev->channel_res_lock, flags);
> +	valid = HINIC3_CHANNEL_RES_VALID(nic_dev);
> +	spin_unlock_irqrestore(&nic_dev->channel_res_lock, flags);
> +
> +	if (!valid)

Why are you checking valid here? What if the state changes immediately
after unlocking?

> +		return;
>  
>  	if (link_status_up) {
>  		if (netif_carrier_ok(netdev))
> diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
> index da73811641a9..d652a5ffdc2c 100644
> --- a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
> +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
> @@ -428,6 +428,85 @@ static void hinic3_vport_down(struct net_device *netdev)
>  	}
>  }
>  
> +int
> +hinic3_change_channel_settings(struct net_device *netdev,
> +			       struct hinic3_dyna_txrxq_params *trxq_params)
> +{
> +	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
> +	struct hinic3_dyna_txrxq_params old_qp_params = {};
> +	struct hinic3_dyna_qp_params new_qp_params = {};
> +	struct hinic3_dyna_qp_params cur_qp_params = {};
> +	bool need_teardown = false;
> +	unsigned long flags;
> +	int err;
> +
> +	mutex_lock(&nic_dev->channel_cfg_lock);
> +
> +	hinic3_config_num_qps(netdev, trxq_params);
> +
> +	err = hinic3_alloc_channel_resources(netdev, &new_qp_params,
> +					     trxq_params);
> +	if (err) {
> +		netdev_err(netdev, "Failed to alloc channel resources\n");
> +		mutex_unlock(&nic_dev->channel_cfg_lock);
> +		return err;
> +	}
> +
> +	spin_lock_irqsave(&nic_dev->channel_res_lock, flags);
> +	if (!test_and_set_bit(HINIC3_CHANGE_RES_INVALID, &nic_dev->flags))
> +		need_teardown = true;
> +	spin_unlock_irqrestore(&nic_dev->channel_res_lock, flags);
> +
> +	if (need_teardown) {
> +		hinic3_vport_down(netdev);
> +		hinic3_close_channel(netdev);
> +		hinic3_uninit_qps(nic_dev, &cur_qp_params);
> +		hinic3_free_channel_resources(netdev, &cur_qp_params,
> +					      &nic_dev->q_params);
> +	}
> +
> +	if (nic_dev->num_qp_irq > trxq_params->num_qps)
> +		hinic3_qp_irq_change(netdev, trxq_params->num_qps);
> +
> +	spin_lock_irqsave(&nic_dev->channel_res_lock, flags);
> +	old_qp_params = nic_dev->q_params;
> +	nic_dev->q_params = *trxq_params;
> +	spin_unlock_irqrestore(&nic_dev->channel_res_lock, flags);
> +
> +	hinic3_init_qps(nic_dev, &new_qp_params);
> +
> +	err = hinic3_open_channel(netdev);

This "open" function allocates Rx buffers, and fails if it couldn't get
even one. That's no good.

> +	if (err)
> +		goto err_uninit_qps;
> +
> +	err = hinic3_vport_up(netdev);
> +	if (err)
> +		goto err_close_channel;
> +
> +	spin_lock_irqsave(&nic_dev->channel_res_lock, flags);
> +	clear_bit(HINIC3_CHANGE_RES_INVALID, &nic_dev->flags);
> +	spin_unlock_irqrestore(&nic_dev->channel_res_lock, flags);
> +
> +	mutex_unlock(&nic_dev->channel_cfg_lock);
> +
> +	return 0;
> +
> +err_close_channel:
> +	hinic3_close_channel(netdev);
> +err_uninit_qps:
> +	spin_lock_irqsave(&nic_dev->channel_res_lock, flags);
> +	nic_dev->q_params = old_qp_params;
> +	clear_bit(HINIC3_CHANGE_RES_INVALID, &nic_dev->flags);
> +	spin_unlock_irqrestore(&nic_dev->channel_res_lock, flags);
> +
> +	hinic3_uninit_qps(nic_dev, &new_qp_params);
> +	hinic3_free_channel_resources(netdev, &new_qp_params, trxq_params);
> +
> +	mutex_unlock(&nic_dev->channel_cfg_lock);

AI says:

  Can this error path lead to memory corruption?
  If need_teardown was true, the old channel resources were freed earlier in
  the function. If hinic3_open_channel() or hinic3_vport_up() fails, the code
  jumps to err_uninit_qps and restores nic_dev->q_params = old_qp_params.
  However, it doesn't appear to re-allocate those old resources or mark the
  interface as down. Could a subsequent administrative teardown or network
  traffic dereference these freed pointers?

> +
>  static int hinic3_open(struct net_device *netdev)
>  {
>  	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
> @@ -487,16 +566,33 @@ static int hinic3_close(struct net_device *netdev)
>  {
>  	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
>  	struct hinic3_dyna_qp_params qp_params;
> +	bool need_teardown = false;
> +	unsigned long flags;
>  
>  	if (!test_and_clear_bit(HINIC3_INTF_UP, &nic_dev->flags)) {
>  		netdev_dbg(netdev, "Netdev already close, do nothing\n");
>  		return 0;
>  	}
>  
> -	hinic3_vport_down(netdev);
> -	hinic3_close_channel(netdev);
> -	hinic3_uninit_qps(nic_dev, &qp_params);
> -	hinic3_free_channel_resources(netdev, &qp_params, &nic_dev->q_params);
> +	mutex_lock(&nic_dev->channel_cfg_lock);
> +
> +	spin_lock_irqsave(&nic_dev->channel_res_lock, flags);
> +	if (!test_and_set_bit(HINIC3_CHANGE_RES_INVALID, &nic_dev->flags))
> +		need_teardown = true;
> +	spin_unlock_irqrestore(&nic_dev->channel_res_lock, flags);
> +
> +	if (need_teardown) {
> +		hinic3_vport_down(netdev);
> +		hinic3_close_channel(netdev);
> +		hinic3_uninit_qps(nic_dev, &qp_params);
> +		hinic3_free_channel_resources(netdev, &qp_params,
> +					      &nic_dev->q_params);
> +	}
> +
> +	hinic3_free_nicio_res(nic_dev);
> +	hinic3_destroy_num_qps(netdev);
> +
> +	mutex_unlock(&nic_dev->channel_cfg_lock);
>  
>  	return 0;
>  }
> diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h
> index 9502293ff710..55b280888ad8 100644
> --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h
> +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h
> @@ -10,6 +10,9 @@
>  #include "hinic3_hw_cfg.h"
>  #include "hinic3_hwdev.h"
>  #include "hinic3_mgmt_interface.h"
> +#include "hinic3_nic_io.h"
> +#include "hinic3_tx.h"
> +#include "hinic3_rx.h"
>  
>  #define HINIC3_VLAN_BITMAP_BYTE_SIZE(nic_dev)  (sizeof(*(nic_dev)->vlan_bitmap))
>  #define HINIC3_VLAN_BITMAP_SIZE(nic_dev)  \
> @@ -20,8 +23,13 @@ enum hinic3_flags {
>  	HINIC3_MAC_FILTER_CHANGED,
>  	HINIC3_RSS_ENABLE,
>  	HINIC3_UPDATE_MAC_FILTER,
> +	HINIC3_CHANGE_RES_INVALID,
>  };
>  
> +#define HINIC3_CHANNEL_RES_VALID(nic_dev) \
> +	(test_bit(HINIC3_INTF_UP, &(nic_dev)->flags) && \
> +	 !test_bit(HINIC3_CHANGE_RES_INVALID, &(nic_dev)->flags))

I don't get why you need to check both of these bits.
Can't there be one bit for "resources valid" ?
And it will only be set while device is up (of course) so no need to
also check UP (this way checking can be atomic without the spin lock).

>  enum hinic3_event_work_flags {
>  	HINIC3_EVENT_WORK_TX_TIMEOUT,
>  };
> @@ -129,6 +137,10 @@ struct hinic3_nic_dev {
>  	struct work_struct              rx_mode_work;
>  	/* lock for enable/disable port */
>  	struct mutex                    port_state_mutex;
> +	/* lock for channel configuration */
> +	struct mutex                    channel_cfg_lock;
> +	/* lock for channel resources */
> +	spinlock_t                      channel_res_lock;
>  
>  	struct list_head                uc_filter_list;
>  	struct list_head                mc_filter_list;
> @@ -143,6 +155,10 @@ struct hinic3_nic_dev {
>  
>  void hinic3_set_netdev_ops(struct net_device *netdev);
>  int hinic3_set_hw_features(struct net_device *netdev);
> +int
> +hinic3_change_channel_settings(struct net_device *netdev,
> +			       struct hinic3_dyna_txrxq_params *trxq_params);
> +
>  int hinic3_qps_irq_init(struct net_device *netdev);
>  void hinic3_qps_irq_uninit(struct net_device *netdev);
>  
> diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h
> index 12eefabcf1db..3791b9bc865b 100644
> --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h
> +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h
> @@ -14,6 +14,10 @@ struct hinic3_nic_dev;
>  #define HINIC3_RQ_WQEBB_SHIFT      3
>  #define HINIC3_SQ_WQEBB_SIZE       BIT(HINIC3_SQ_WQEBB_SHIFT)
>  
> +#define HINIC3_MAX_TX_QUEUE_DEPTH  65536
> +#define HINIC3_MAX_RX_QUEUE_DEPTH  16384
> +#define HINIC3_MIN_QUEUE_DEPTH     128
> +
>  /* ******************** RQ_CTRL ******************** */
>  enum hinic3_rq_wqe_type {
>  	HINIC3_NORMAL_RQ_WQE = 1,


^ permalink raw reply

* Re: [PATCH v5 00/21] Virtual Swap Space
From: YoungJun Park @ 2026-04-14  2:50 UTC (permalink / raw)
  To: Nhat Pham
  Cc: kasong, Liam.Howlett, akpm, apopple, axelrasmussen, baohua,
	baolin.wang, bhe, byungchul, cgroups, chengming.zhou, chrisl,
	corbet, david, dev.jain, gourry, hannes, hughd, jannh,
	joshua.hahnjy, lance.yang, lenb, linux-doc, linux-kernel,
	linux-mm, linux-pm, lorenzo.stoakes, matthew.brost, mhocko,
	muchun.song, npache, pavel, peterx, peterz, pfalcato, rafael,
	rakie.kim, roman.gushchin, rppt, ryan.roberts, shakeel.butt,
	shikemeng, surenb, tglx, vbabka, weixugc, ying.huang, yosry.ahmed,
	yuanchu, zhengqi.arch, ziy, kernel-team, riel
In-Reply-To: <CAKEwX=NnHxpQKp9qBg2=r_euyjgxw2nHXjbgof3MymHTgJmRAQ@mail.gmail.com>

On Sat, Apr 11, 2026 at 06:40:44PM -0700, Nhat Pham wrote:

Hello Nhat!

> > 1. Modularization
> >
> > You removed CONFIG_* and went with a unified approach. I recall
> > you were also considering a module-based structure at some point.
> > What are your thoughts on that direction?
> >
>
> The CONFIG-based approach was a huge mess. It makes me not want to
> look at the code, and I'm the author :)
>
> > If we take that approach, we could extend the recent swap ops
> > patchset (https://lore.kernel.org/linux-mm/20260302104016.163542-1-bhe@redhat.com/)
> > as follows:
> > - Make vswap a swap module
> > - Have cluster allocation functions reside in swapops
> > - Enable vswap through swapon
>
> Hmmmmm.

I think this would be a happy world, but I wonder what others think.
Anyway, I'm looking forward to the future direction.

> > 2. Flash-friendly swap integration (for my use case)
> >
> > I've been thinking about the flash-friendly swap concept that
> > I mentioned before and recently proposed:
> > (https://lore.kernel.org/linux-mm/aZW0voL4MmnMQlaR@yjaykim-PowerEdge-T330/)
> >
> > One of its core functions requires buffering RAM-swapped pages
> > and writing them sequentially at an appropriate time -- not
> > immediately, but in proper block-sized units, sequentially.
> >
> > This means allocated offsets must essentially be virtual, and
> > physical offsets need to be managed separately at the actual
> > write time.
> >
> > If we integrate this into the current vswap, we would either
> > need vswap itself to handle the sequential writes (bypassing
> > the physical device and receiving pages directly), or swapon
> > a swap device and have vswap obtain physical offsets from it.
> > But since those offsets cannot be used directly (due to
> > buffering and sequential write requirements), they become
> > virtual too, resulting in:
> >
> >   virtual -> virtual -> physical
> >
> > This triple indirection is not ideal.
> >
> > However, if the modularization from point 1 is achieved and
> > vswap acts as a swap device itself, then we can cleanly
> > establish a:
> >
> >   virtual -> physical
>
> I read that thread sometimes ago. Some remarks:
>
> 1. I think Christoph has a point. Seems like some of your ideas ( are
> broadly applicable to swap in general. Maybe fixing swap infra
> generally would make a lot of sense?

Broadly speaking, there are two main ideas:
1. Swap I/O buffering (which is also tied to cluster management issues)
2. Deduplication

Are you leaning towards the view that these two should be placed in a
higher layer?

> 2. Why do we need to do two virtual layers here? For example, If you
> want to buffer multiple swap outs and turn them into a sequential
> request, you can:
>
> a. Allocate virtual swap space for them as you wish. They don't even
> need to be sequential.
>
> b. At swap_writeout() time, don't allocate physical swap space for
> them right away. Instead, accumulate them into a buffer. You can add a
> new virtual swap entry type to flag it if necessary.
>
> c. Once that buffer reaches a certain size, you can now allocate
> contiguous physical swap space for them. Then flush etc. You can flush
> at swap_writeout() time, or use a dedicated threads etc.

I initially thought implementing this in vswap would be complicated
(due to the ripple effects of altering behavior at swap_writeout timing),
but it seems entirely possible!

1. We could change the behavior (e.g., buffering) at vswap_alloc_swap_slot
   timing by checking things like the si type.
2. Additionally, if we can handle the cluster data structures and
   mechanisms in the swap_info_struct privately, a virtual-to-physical
   one-direction approach seems feasible.
   (Come to think of it, it might be better to refactor the infra to let
   other modules handle this, potentially removing the swap_info_struct
   mechanism entirely. Just imagination ;) )

> Deduplication sounds like something that should live at a lower layer
> - I was thinking about it for zswap/zsmalloc back then. I mean, I
> assume you don't want content sharing across different swap media? :)
> Something along the line of:
>
> 1. Maintain an content index for swapped out pages.
>
> 2. For the swap media that support deduplication, you'll need to add
> some sort of reference count (more overhead ew).
>
> 3. Each time we swapped out, we can content-check to see if the same
> piece of conent has been swapped out before. If so, set the vswap
> backend to the physical location of the data, increment some sort of
> reference count (perhaps we can use swap count) of the older entry,
> and have the swap type point to it.

As for reference count management, applying it loosely might be a good
approach. Instead of strictly managing the lifecycle of the dedup contents
with refcounts, we could just periodically clean up the hash. This also
has the benefit of reducing I/O for the same swap content compared to
deleting it immediately.

> But have you considered the implications of sharing swap data like
> this? I need to read the paper you cite - seems like a potential fun
> read. But what happen when these two pages that share the content
> belong to two different cgroups? How does the
> charging/uncharging/charge transferring story work? That's one of the
> things that made me pause when I wanted to implement deduplication for
> zswap/zsmalloc. Zram does not charge memory towards cgroup, but zswap
> does, so we'll need to handle this somehow, and at that point all the
> complexity might no longer be worth it.

Since our private swap device is similar to ZRAM, I hadn't considered
the charging aspect. It is indeed a complex issue.

If it goes into ZSWAP, there would definitely be a clear advantage of
seeing dedup benefits across all swap devices. It's a technically
interesting area, and I'd like to discuss it in a separate thread if
I have more ideas or thoughts.

Just a thought that comes to mind here: if vswap becomes modularized,
how about doing memcg charging for this entire area? 
(Come to think of it, to fully benefit from vswap modularization,
zswap should also be applied within its scope.)

Best regards,
Youngjun Park

^ permalink raw reply

* Re: [PATCH v5 00/21] Virtual Swap Space
From: YoungJun Park @ 2026-04-14  3:09 UTC (permalink / raw)
  To: Nhat Pham
  Cc: Kairui Song, Liam.Howlett, akpm, apopple, axelrasmussen, baohua,
	baolin.wang, bhe, byungchul, cgroups, chengming.zhou, chrisl,
	corbet, david, dev.jain, gourry, hannes, hughd, jannh,
	joshua.hahnjy, lance.yang, lenb, linux-doc, linux-kernel,
	linux-mm, linux-pm, lorenzo.stoakes, matthew.brost, mhocko,
	muchun.song, npache, pavel, peterx, peterz, pfalcato, rafael,
	rakie.kim, roman.gushchin, rppt, ryan.roberts, shakeel.butt,
	shikemeng, surenb, tglx, vbabka, weixugc, ying.huang, yosry.ahmed,
	yuanchu, zhengqi.arch, ziy, kernel-team, riel
In-Reply-To: <CAKEwX=Pt04pYfhYOwmtXJKU5OqcxBC14SAf1wpBxBo1D7rPpGw@mail.gmail.com>

On Sat, Apr 11, 2026 at 06:03:04PM -0700, Nhat Pham wrote:
> On Wed, Mar 25, 2026 at 11:53 AM YoungJun Park <youngjun.park@lge.com> wrote:
> >
> > On Mon, Mar 23, 2026 at 11:32:57AM -0400, Nhat Pham wrote:
> >
> > > Interesting. Normally "lots of zero-filled page" is a very beneficial
> > > case for vswap. You don't need a swapfile, or any zram/zswap metadata
> > > overhead - it's a native swap backend. If production workload has this
> > > many zero-filled pages, I think the numbers of vswap would be much
> > > less alarming - perhaps even matching memory overhead because you
> > > don't need to maintain a zram entry metadata (it's at least 2 words
> > > per zram entry right?), while there's no reverse map overhead induced
> > > (so it's 24 bytes on both side), and no need to do zram-side locking
> > > :)
> > >
> > > So I was surprised to see that it's not working out very well here. I
> > > checked the implementation of memhog - let me know if this is wrong
> > > place to look:
> > >
> > > https://man7.org/linux/man-pages/man8/memhog.8.html
> > > https://github.com/numactl/numactl/blob/master/memhog.c#L52
> > >
> > > I think this is what happened here: memhog was populating the memory
> > > 0xff, which triggers the full overhead of a swapfile-backed swap entry
> > > because even though it's "same-filled" it's not zero-filled! I was
> > > following Usama's observation - "less than 1% of the same-filled pages
> > > were non-zero" - and so I only handled the zero-filled case here:
> > >
> > > https://lore.kernel.org/all/20240530102126.357438-1-usamaarif642@gmail.com/
> > >
> > > This sounds a bit artificial IMHO - as Usama pointed out above, I
> > > think most samefilled pages are zero pages, in real production
> > > workloads. However, if you think there are real use cases with a lot
> > > of non-zero samefilled pages, please let me know I can fix this real
> > > quick. We can support this in vswap with zero extra metadata overhead
> > > - change the VSWAP_ZERO swap entry type to VSWAP_SAME_FILLED, then use
> > > the backend field to store that value. I can send you a patch if
> > > you're interested.
> >
> > This brings back memories -- I'm pretty sure we talked about
> > exactly this at LPC. Our custom swap device already handles both
> > zero-filled and same-filled pages on its own, so what we really
> > wanted was a way to tell the swap layer "just skip the detection
> > and let it through."
> >
> > I looked at two approaches back then but never submitted either:
> >
> >   - A per-swap_info flag to opt out of zero/same-filled handling.
> >     But this felt wrong from vswap's perspective -- if even one
> >     device opts out of the zeromap, the model gets messy.
> >
> >   - Revisiting Usama's patch 2 approach.
> >     Sounded good in theory, but as you said,
> >     it's not as simple to verify in practice. And it is more clean design
> >     swapout time zero check as I see. So,  I gave up on it.
> >
> > Seeing this come up again is actually kind of nice :)
> >
> > One thought -- maybe a compile-time CONFIG or a boot param to
> > control the scope? e.g. zero-only, same-filled, or disabled.
> > That way vendors like us just turn it off, and setups like
> > Kairui's can opt into broader detection. Just an idea though --
> > open to other approaches if you have something in mind.
> 
> Yeah for vswap it's probably going to be a CONFIG or boot param.
> 
> But in the status quo, we can always add a swapfile flag. That one
> should work already, right?

I'm a bit hesitant about the swapfile flag approach. If vswap gets merged,
handling devices with this flag set might complicate the vswap design.

Moreover, exposing a new swap flag to the user interface (e.g., at swapon)
raises concerns about backward compatibility. Do you think that would be safe?

Since our use case isn't very common, we just need a simple knob to tune it.
That's why I still prefer a boot param or CONFIG approach.

Thanks :D
Youngjun Park

^ permalink raw reply

* Re: [PATCH v5 00/21] Virtual Swap Space
From: Kairui Song @ 2026-04-14  3:28 UTC (permalink / raw)
  To: YoungJun Park
  Cc: Nhat Pham, Liam.Howlett, akpm, apopple, axelrasmussen, baohua,
	baolin.wang, bhe, byungchul, cgroups, chengming.zhou, chrisl,
	corbet, david, dev.jain, gourry, hannes, hughd, jannh,
	joshua.hahnjy, lance.yang, lenb, linux-doc, linux-kernel,
	linux-mm, linux-pm, lorenzo.stoakes, matthew.brost, mhocko,
	muchun.song, npache, pavel, peterx, peterz, pfalcato, rafael,
	rakie.kim, roman.gushchin, rppt, ryan.roberts, shakeel.butt,
	shikemeng, surenb, tglx, vbabka, weixugc, ying.huang, yosry.ahmed,
	yuanchu, zhengqi.arch, ziy, kernel-team, riel
In-Reply-To: <ad2rYH9tUPthHFoj@yjaykim-PowerEdge-T330>

On Tue, Apr 14, 2026 at 11:05 AM YoungJun Park <youngjun.park@lge.com> wrote:
>

Hi All,

> On Sat, Apr 11, 2026 at 06:40:44PM -0700, Nhat Pham wrote:
> > > 1. Modularization
> > >
> > > You removed CONFIG_* and went with a unified approach. I recall
> > > you were also considering a module-based structure at some point.
> > > What are your thoughts on that direction?
> > >
> >
> > The CONFIG-based approach was a huge mess. It makes me not want to
> > look at the code, and I'm the author :)
> >
> > > If we take that approach, we could extend the recent swap ops
> > > patchset (https://lore.kernel.org/linux-mm/20260302104016.163542-1-bhe@redhat.com/)
> > > as follows:
> > > - Make vswap a swap module
> > > - Have cluster allocation functions reside in swapops
> > > - Enable vswap through swapon
> >
> > Hmmmmm.
>
> I think this would be a happy world, but I wonder what others think.
> Anyway, I'm looking forward to the future direction.
>

Yeah, I agree with this.

And I do think swapoff of the virtual space itself is also necessary,
we really need a failsafe, e.g. a clean way to drop the swap
cache and data, kind of like drop_caches or shrinker fs are
commonly used.

> > > 2. Flash-friendly swap integration (for my use case)
> > >
> > > I've been thinking about the flash-friendly swap concept that
> > > I mentioned before and recently proposed:
> > > (https://lore.kernel.org/linux-mm/aZW0voL4MmnMQlaR@yjaykim-PowerEdge-T330/)
> > >
> > > One of its core functions requires buffering RAM-swapped pages
> > > and writing them sequentially at an appropriate time -- not
> > > immediately, but in proper block-sized units, sequentially.
> > >
> > > This means allocated offsets must essentially be virtual, and
> > > physical offsets need to be managed separately at the actual
> > > write time.
> > >
> > > If we integrate this into the current vswap, we would either
> > > need vswap itself to handle the sequential writes (bypassing
> > > the physical device and receiving pages directly), or swapon
> > > a swap device and have vswap obtain physical offsets from it.
> > > But since those offsets cannot be used directly (due to
> > > buffering and sequential write requirements), they become
> > > virtual too, resulting in:
> > >
> > >   virtual -> virtual -> physical
> > >
> > > This triple indirection is not ideal.
> > >
> > > However, if the modularization from point 1 is achieved and
> > > vswap acts as a swap device itself, then we can cleanly
> > > establish a:
> > >
> > >   virtual -> physical
> >
> > I read that thread sometimes ago. Some remarks:
> >
> > 1. I think Christoph has a point. Seems like some of your ideas ( are
> > broadly applicable to swap in general. Maybe fixing swap infra
> > generally would make a lot of sense?
>
> Broadly speaking, there are two main ideas:
> 1. Swap I/O buffering (which is also tied to cluster management issues)
> 2. Deduplication
>
> Are you leaning towards the view that these two should be placed in a
> higher layer?

IMHO the swap infra should be doing less, not more, so we can have
more flexible design, and different backends can implement their own
way to manage the data and layer. e.g. Having one backend being
flash friendly and it can do this without caring or affecting other devices
or backends.

> If it goes into ZSWAP, there would definitely be a clear advantage of
> seeing dedup benefits across all swap devices. It's a technically
> interesting area, and I'd like to discuss it in a separate thread if
> I have more ideas or thoughts.

Just branstorm... Why don't we just merge these identical pages like
KSM? Maybe at least zero folios might benefit a lot if we keep them
mapped as RO instead of recording them in swap, seems better in the
long term?

^ permalink raw reply

* [PATCH 0/2] Add support for MAX20830 PMBUS
From: Alexis Czezar Torreno @ 2026-04-14  4:28 UTC (permalink / raw)
  To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Jonathan Corbet, Shuah Khan
  Cc: linux-hwmon, devicetree, linux-kernel, linux-doc,
	Alexis Czezar Torreno

This series adds support for the Analog Devices MAX20830 step-down
switching regulator with PMBus interface.

The MAX20830 provides 2.7V to 16V input, 0.4V to 5.8V output, and up
to 30A output current. It supports monitoring of input/output voltage,
output current, and temperature via PMBus.

Datasheet: https://www.analog.com/en/products/max20830.html

Signed-off-by: Alexis Czezar Torreno <alexisczezar.torreno@analog.com>
---
Alexis Czezar Torreno (2):
      dt-bindings: hwmon: pmbus: add max20830
      hwmon: (pmbus/max20830) add driver for max20830

 .../bindings/hwmon/pmbus/adi,max20830.yaml         | 58 +++++++++++++++++
 Documentation/hwmon/index.rst                      |  1 +
 Documentation/hwmon/max20830.rst                   | 48 ++++++++++++++
 MAINTAINERS                                        |  9 +++
 drivers/hwmon/pmbus/Kconfig                        |  9 +++
 drivers/hwmon/pmbus/Makefile                       |  1 +
 drivers/hwmon/pmbus/max20830.c                     | 74 ++++++++++++++++++++++
 7 files changed, 200 insertions(+)
---
base-commit: fb447217c59a13b2fff22d94de2498c185cd9032
change-id: 20260414-dev_max20830-9460b92cf6aa

Best regards,
-- 
Alexis Czezar Torreno <alexisczezar.torreno@analog.com>


^ permalink raw reply

* [PATCH 2/2] hwmon: (pmbus/max20830) add driver for max20830
From: Alexis Czezar Torreno @ 2026-04-14  4:28 UTC (permalink / raw)
  To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Jonathan Corbet, Shuah Khan
  Cc: linux-hwmon, devicetree, linux-kernel, linux-doc,
	Alexis Czezar Torreno
In-Reply-To: <20260414-dev_max20830-v1-0-210d3f82c571@analog.com>

Add support for MAX20830 step-down DC-DC switching regulator with
PMBus interface. It allows monitoring of input/output voltage,
output current and temperature through the PMBus serial interface.

Signed-off-by: Alexis Czezar Torreno <alexisczezar.torreno@analog.com>
---
 Documentation/hwmon/index.rst    |  1 +
 Documentation/hwmon/max20830.rst | 48 ++++++++++++++++++++++++++
 MAINTAINERS                      |  2 ++
 drivers/hwmon/pmbus/Kconfig      |  9 +++++
 drivers/hwmon/pmbus/Makefile     |  1 +
 drivers/hwmon/pmbus/max20830.c   | 74 ++++++++++++++++++++++++++++++++++++++++
 6 files changed, 135 insertions(+)

diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
index 8b655e5d6b68b90c697a52c7bf526e81d370caf7..56f7eb761be76dd627a2f34135abad05203b0582 100644
--- a/Documentation/hwmon/index.rst
+++ b/Documentation/hwmon/index.rst
@@ -158,6 +158,7 @@ Hardware Monitoring Kernel Drivers
    max197
    max20730
    max20751
+   max20830
    max31722
    max31730
    max31760
diff --git a/Documentation/hwmon/max20830.rst b/Documentation/hwmon/max20830.rst
new file mode 100644
index 0000000000000000000000000000000000000000..b9dffb76059781932d383ed798cecff69e738873
--- /dev/null
+++ b/Documentation/hwmon/max20830.rst
@@ -0,0 +1,48 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Kernel driver max20830
+======================
+
+Supported chips:
+
+  * Analog Devices MAX20830
+
+    Prefix: 'max20830'
+
+    Addresses scanned: -
+
+    Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/max20830.pdf
+
+Author:
+
+  - Alexis Czezar Torreno <alexisczezar.torreno@analog.com>
+
+
+Description
+-----------
+
+This driver supports hardware monitoring for Analog Devices MAX20830
+Step-Down Switching Regulator with PMBus Interface.
+
+The MAX20830 is a 2.7V to 16V, 30A fully integrated step-down DC-DC switching
+regulator. Through the PMBus interface, the device can monitor input/output
+voltages, output current and temperature.
+
+The driver is a client driver to the core PMBus driver. Please see
+Documentation/hwmon/pmbus.rst for details on PMBus client drivers.
+
+Sysfs entries
+-------------
+
+================= ========================================
+in1_label         "vin"
+in1_input         Measured input voltage
+in1_alarm         Input voltage alarm
+in2_label         "vout1"
+in2_input         Measured output voltage
+curr1_label       "iout1"
+curr1_input       Measured output current
+curr1_alarm       Output current alarm
+temp1_input       Measured temperature
+temp1_alarm       Chip temperature alarm
+================= ========================================
diff --git a/MAINTAINERS b/MAINTAINERS
index 031c743e979521a92ed9ac67915c178ce31727bd..d6a6745e2dae29c3b8f80bbe61c54a2f5ecd9f47 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15585,6 +15585,8 @@ L:	linux-hwmon@vger.kernel.org
 S:	Supported
 W:	https://ez.analog.com/linux-software-drivers
 F:	Documentation/devicetree/bindings/hwmon/pmbus/adi,max20830.yaml
+F:	Documentation/hwmon/max20830.rst
+F:	drivers/hwmon/pmbus/max20830.c
 
 MAX2175 SDR TUNER DRIVER
 M:	Ramesh Shanmugasundaram <rashanmu@gmail.com>
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index 8f4bff375ecbc355f5ed3400855c2852ec2aa5ef..987705bf45b75b7b91ccc469247909f3c3f53d77 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -365,6 +365,15 @@ config SENSORS_MAX20751
 	  This driver can also be built as a module. If so, the module will
 	  be called max20751.
 
+config SENSORS_MAX20830
+	tristate "Analog Devices MAX20830"
+	help
+	  If you say yes here you get hardware monitoring support for Analog
+	  Devices MAX20830.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called max20830.
+
 config SENSORS_MAX31785
 	tristate "Maxim MAX31785 and compatibles"
 	help
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
index 7129b62bc00f8a2e98de14004997752a856dfda2..bc52f930e0825a902a0dd1c9e2b44f2e8d577c35 100644
--- a/drivers/hwmon/pmbus/Makefile
+++ b/drivers/hwmon/pmbus/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_SENSORS_MAX16601)	+= max16601.o
 obj-$(CONFIG_SENSORS_MAX17616)	+= max17616.o
 obj-$(CONFIG_SENSORS_MAX20730)	+= max20730.o
 obj-$(CONFIG_SENSORS_MAX20751)	+= max20751.o
+obj-$(CONFIG_SENSORS_MAX20830)	+= max20830.o
 obj-$(CONFIG_SENSORS_MAX31785)	+= max31785.o
 obj-$(CONFIG_SENSORS_MAX34440)	+= max34440.o
 obj-$(CONFIG_SENSORS_MAX8688)	+= max8688.o
diff --git a/drivers/hwmon/pmbus/max20830.c b/drivers/hwmon/pmbus/max20830.c
new file mode 100644
index 0000000000000000000000000000000000000000..bcf60fd948e3437f47267747547142704ae96378
--- /dev/null
+++ b/drivers/hwmon/pmbus/max20830.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Hardware monitoring driver for Analog Devices MAX20830
+ *
+ * Copyright (C) 2026 Analog Devices, Inc.
+ */
+
+#include <linux/i2c.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include "pmbus.h"
+
+static struct pmbus_driver_info max20830_info = {
+	.pages = 1,
+	.format[PSC_VOLTAGE_IN] = linear,
+	.format[PSC_VOLTAGE_OUT] = linear,
+	.format[PSC_CURRENT_OUT] = linear,
+	.format[PSC_TEMPERATURE] = linear,
+	.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT |
+		PMBUS_HAVE_TEMP |
+		PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT |
+		PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP,
+};
+
+static int max20830_probe(struct i2c_client *client)
+{
+	u8 buf[I2C_SMBUS_BLOCK_MAX + 1];
+	int ret;
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_READ_I2C_BLOCK))
+		return -ENODEV;
+
+	ret = i2c_smbus_read_i2c_block_data(client, PMBUS_IC_DEVICE_ID,
+					    I2C_SMBUS_BLOCK_MAX, buf);
+	if (ret < 0)
+		return dev_err_probe(&client->dev, ret,
+				     "Failed to read IC_DEVICE_ID\n");
+
+	buf[ret] = '\0';
+	if (ret < 9 || strncmp(buf + 1, "MAX20830", 8))
+		return dev_err_probe(&client->dev, -ENODEV,
+				     "Unsupported device: '%s'\n", buf);
+
+	return pmbus_do_probe(client, &max20830_info);
+}
+
+static const struct i2c_device_id max20830_id[] = {
+	{"max20830"},
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, max20830_id);
+
+static const struct of_device_id max20830_of_match[] = {
+	{ .compatible = "adi,max20830" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, max20830_of_match);
+
+static struct i2c_driver max20830_driver = {
+	.driver = {
+		.name = "max20830",
+		.of_match_table = max20830_of_match,
+	},
+	.probe = max20830_probe,
+	.id_table = max20830_id,
+};
+
+module_i2c_driver(max20830_driver);
+
+MODULE_AUTHOR("Alexis Czezar Torreno <alexisczezar.torreno@analog.com>");
+MODULE_DESCRIPTION("PMBus driver for Analog Devices MAX20830");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(PMBUS);

-- 
2.34.1


^ permalink raw reply related

* [PATCH 1/2] dt-bindings: hwmon: pmbus: add max20830
From: Alexis Czezar Torreno @ 2026-04-14  4:28 UTC (permalink / raw)
  To: Guenter Roeck, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Jonathan Corbet, Shuah Khan
  Cc: linux-hwmon, devicetree, linux-kernel, linux-doc,
	Alexis Czezar Torreno
In-Reply-To: <20260414-dev_max20830-v1-0-210d3f82c571@analog.com>

Add device tree documentation for MAX20830 step-down DC-DC switching
regulator with PMBus interface.

Signed-off-by: Alexis Czezar Torreno <alexisczezar.torreno@analog.com>
---
 .../bindings/hwmon/pmbus/adi,max20830.yaml         | 58 ++++++++++++++++++++++
 MAINTAINERS                                        |  7 +++
 2 files changed, 65 insertions(+)

diff --git a/Documentation/devicetree/bindings/hwmon/pmbus/adi,max20830.yaml b/Documentation/devicetree/bindings/hwmon/pmbus/adi,max20830.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b20f3be176615895e70e74bfb2a534d82d124a15
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/pmbus/adi,max20830.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/hwmon/pmbus/adi,max20830.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices MAX20830 Step-Down Switching Regulator with PMBus
+
+maintainers:
+  - Alexis Czezar Torreno <alexisczezar.torreno@analog.com>
+
+description: |
+  The MAX20830 is a fully integrated step-down DC-DC switching regulator with
+  PMBus interface. It provides 2.7V to 16V input, 0.4V to 5.8V adjustable
+  output, and up to 30A output current. It allows monitoring of input/output
+  voltage, output current and temperature through the PMBus serial interface.
+  Datasheet:
+    https://www.analog.com/en/products/max20830.html
+
+properties:
+  compatible:
+    const: adi,max20830
+
+  reg:
+    maxItems: 1
+
+  vddh-supply:
+    description:
+      Phandle to the regulator that provides the VDDH power supply.
+
+  avdd-supply:
+    description:
+      Phandle to the regulator that provides the AVDD power supply.
+
+  ldoin-supply:
+    description:
+      Optional 2.5V to 5.5V LDO input supply.
+
+required:
+  - compatible
+  - reg
+  - vddh-supply
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        hwmon@30 {
+            compatible = "adi,max20830";
+            reg = <0x30>;
+            vddh-supply = <&vddh>;
+        };
+    };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 0a3991c10ade20dd79cc7d1bf2a1d307ba6bd19d..031c743e979521a92ed9ac67915c178ce31727bd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15579,6 +15579,13 @@ F:	Documentation/devicetree/bindings/hwmon/pmbus/adi,max17616.yaml
 F:	Documentation/hwmon/max17616.rst
 F:	drivers/hwmon/pmbus/max17616.c
 
+MAX20830 HARDWARE MONITOR DRIVER
+M:	Alexis Czezar Torreno <alexisczezar.torreno@analog.com>
+L:	linux-hwmon@vger.kernel.org
+S:	Supported
+W:	https://ez.analog.com/linux-software-drivers
+F:	Documentation/devicetree/bindings/hwmon/pmbus/adi,max20830.yaml
+
 MAX2175 SDR TUNER DRIVER
 M:	Ramesh Shanmugasundaram <rashanmu@gmail.com>
 L:	linux-media@vger.kernel.org

-- 
2.34.1


^ permalink raw reply related

* [RFC PATCH 0/2] mm/damon/stat: add kdamond_pid parameter
From: SeongJae Park @ 2026-04-14  4:49 UTC (permalink / raw)
  Cc: SeongJae Park, Liam R. Howlett, Andrew Morton, David Hildenbrand,
	Jonathan Corbet, Lorenzo Stoakes, Michal Hocko, Mike Rapoport,
	Shuah Khan, Suren Baghdasaryan, Vlastimil Babka, damon, linux-doc,
	linux-kernel, linux-mm

DAMON_STAT doesn't provide the pid of its kdamond, unlike DAMON_RECLAIM
and DAMON_LRU_SORT.  This makes user-space management of DAMON_STAT
unnecessarily complicated.  Provide the information via a new parameter,
namely kdamond_pid, and document it.

SeongJae Park (2):
  mm/damon/stat: add a parameter for reading kdamond pid
  Docs/admin-guide/mm/damon/stat: document kdamond_pid parameter

 Documentation/admin-guide/mm/damon/stat.rst |  7 +++++++
 mm/damon/stat.c                             | 13 +++++++++++++
 2 files changed, 20 insertions(+)


base-commit: 5262d0a487d50faeefbca2e4ebbdfbed3f69426e
-- 
2.47.3

^ permalink raw reply

* [RFC PATCH 2/2] Docs/admin-guide/mm/damon/stat: document kdamond_pid parameter
From: SeongJae Park @ 2026-04-14  4:50 UTC (permalink / raw)
  Cc: SeongJae Park, Liam R. Howlett, Andrew Morton, David Hildenbrand,
	Jonathan Corbet, Lorenzo Stoakes, Michal Hocko, Mike Rapoport,
	Shuah Khan, Suren Baghdasaryan, Vlastimil Babka, damon, linux-doc,
	linux-kernel, linux-mm
In-Reply-To: <20260414045002.88110-1-sj@kernel.org>

Update DAMON_STAT usage document for newly added kdamond_pid parameter.

Signed-off-by: SeongJae Park <sj@kernel.org>
---
 Documentation/admin-guide/mm/damon/stat.rst | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/Documentation/admin-guide/mm/damon/stat.rst b/Documentation/admin-guide/mm/damon/stat.rst
index c4b14daeb2dd6..46c5dd96aa2ed 100644
--- a/Documentation/admin-guide/mm/damon/stat.rst
+++ b/Documentation/admin-guide/mm/damon/stat.rst
@@ -89,3 +89,10 @@ percentiles of the idle time values via this read-only parameter.  Reading the
 parameter returns 101 idle time values in milliseconds, separated by comma.
 Each value represents 0-th, 1st, 2nd, 3rd, ..., 99th and 100th percentile idle
 times.
+
+kdamond_pid
+-----------
+
+PID of the DAMON thread.
+
+If DAMON_STAT is enabled, this becomes the PID of the worker thread.  Else, -1.
-- 
2.47.3

^ permalink raw reply related

* [RFC PATCH 0/2] mm/damon/reclaim: support monitoring intervals auto-tuning
From: SeongJae Park @ 2026-04-14  4:52 UTC (permalink / raw)
  Cc: SeongJae Park, Liam R. Howlett, Andrew Morton, David Hildenbrand,
	Jonathan Corbet, Lorenzo Stoakes, Michal Hocko, Mike Rapoport,
	Shuah Khan, Suren Baghdasaryan, Vlastimil Babka, damon, linux-doc,
	linux-kernel, linux-mm

The monitoring intervals auto-tuning feature of DAMON has proven to be
useful in multiple environments.  Add a new DAMON_RECLAIM parameter for
supporting the feature, and update the document for the new parameter.

SeongJae Park (2):
  mm/damon/reclaim: add autotune_monitoring_intervals parameter
  Docs/admin-guide/mm/damon/reclaim: update for
    autotune_monitoring_intervals

 .../admin-guide/mm/damon/reclaim.rst          | 11 +++++++
 mm/damon/reclaim.c                            | 33 ++++++++++++++++---
 2 files changed, 39 insertions(+), 5 deletions(-)


base-commit: 02f9b1619307bbcf7028704a50f6b31909f360ce
-- 
2.47.3

^ permalink raw reply

* [RFC PATCH 2/2] Docs/admin-guide/mm/damon/reclaim: update for autotune_monitoring_intervals
From: SeongJae Park @ 2026-04-14  4:52 UTC (permalink / raw)
  Cc: SeongJae Park, Liam R. Howlett, Andrew Morton, David Hildenbrand,
	Jonathan Corbet, Lorenzo Stoakes, Michal Hocko, Mike Rapoport,
	Shuah Khan, Suren Baghdasaryan, Vlastimil Babka, damon, linux-doc,
	linux-kernel, linux-mm
In-Reply-To: <20260414045253.88529-1-sj@kernel.org>

Update DAMON_RECLAIM usage document for the newly added monitoring
intervals auto-tuning enablement parameter.

Signed-off-by: SeongJae Park <sj@kernel.org>
---
 Documentation/admin-guide/mm/damon/reclaim.rst | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/Documentation/admin-guide/mm/damon/reclaim.rst b/Documentation/admin-guide/mm/damon/reclaim.rst
index 01a34c215b66f..b14a065586271 100644
--- a/Documentation/admin-guide/mm/damon/reclaim.rst
+++ b/Documentation/admin-guide/mm/damon/reclaim.rst
@@ -85,6 +85,17 @@ identifies the region as cold, and reclaims it.
 
 120 seconds by default.
 
+autotune_monitoring_intervals
+-----------------------------
+
+If this parameter is set as ``Y``, DAMON_RECLAIM automatically tunes DAMON's
+sampling and aggregation intervals.  The auto-tuning aims to capture meaningful
+amount of access events in each DAMON-snapshot, while keeping the sampling
+interval 5 milliseconds in minimum, and 10 seconds in maximum.  Setting this as
+``N`` disables the auto-tuning.
+
+Disabled by default.
+
 quota_ms
 --------
 
-- 
2.47.3

^ permalink raw reply related

* [PATCH v4 00/13] Support for Samsung S2MU005 PMIC and its sub-devices
From: Kaustabh Chakraborty @ 2026-04-14  6:32 UTC (permalink / raw)
  To: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, MyungJoo Ham, Chanwoo Choi, Sebastian Reichel,
	Krzysztof Kozlowski, André Draszik, Alexandre Belloni,
	Jonathan Corbet, Shuah Khan, Nam Tran,
	Łukasz Lebiedziński
  Cc: linux-leds, devicetree, linux-kernel, linux-pm, linux-samsung-soc,
	linux-rtc, linux-doc, Kaustabh Chakraborty, Conor Dooley

S2MU005 is an MFD chip manufactured by Samsung Electronics. This is
found in various devices manufactured by Samsung and others, including
all Exynos 7870 devices. It is known to have the following features:

1. Two LED channels with adjustable brightness for use as a torch, or a
   flash strobe.
2. An RGB LED with 8-bit channels. Usually programmed as a notification
   indicator.
3. An MUIC, which works with USB micro-B (and USB-C?). For the micro-B
   variant though, it measures the ID-GND resistance using an internal
   ADC.
4. A charger device, which reports if charger is online, voltage,
   resistance, etc.

This patch series implements a lot of these features. Naturally, this
series touches upon a lot of subsystems. The 'parent' is the MFD driver,
so the subsystems have some form of dependency to the MFD driver, so
they are not separable.

Here are the subsystems corresponding to the patch numbers:
dt-bindings - 01, 02, 03, 04, 05
mfd         - 05, 06, 07, 08
led         - 01, 02, 09, 10, 11
extcon      - 03, 12
power       - 04, 13

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
Changes in v4:
- Use OF graph to connect charger with MUIC in device tree
- Move DMA coherent mask to all MFD PMICs (André Draszik)
- Modify pointer names for flash/RGB drivers (Lee Jones)
- Use 100-char line wrap for flash/RGB drivers (Lee Jones)
- Revamp LED device initialization in flash driver (Lee Jones)
- Add proper USB 2.0 support in charger driver (Łukasz Lebiedziński)
- Link to v3: https://lore.kernel.org/r/20260225-s2mu005-pmic-v3-0-b4afee947603@disroot.org

Changes in v3:
- Remove "extcon" text from dt-bindings documentation (Rob Herring)
- Add connector for MUIC node
- Fix dt binding errors reported by robh's bot
- Fix kernel test robot const errors 
- Remove FIELD_PREP() values in register header file (André Draszik)
- Add max_register, volatile_reg, cache_type (André Draszik)
- Redo [v2 07/12] to NOT store the PMIC revision (André Draszik)
- Add a commit to fix DMA coherent mask in I2C PMICs
- Implement various flow changes in flash LED driver (André Draszik)
- Use device_for_each_child_node_scoped() (André Draszik)
- Fix CFI panic in devm_add_action_or_reset()
- Link to v2: https://lore.kernel.org/r/20260126-s2mu005-pmic-v2-0-78f1a75f547a@disroot.org

Changes in v2:
- Drop [v1 06/13], instead use regmap_irq_chip::get_irq_regs() 
- Remove references to driver in devicetree commits (Conor Dooley)
- Propagate errors of sec_pmic_store_rev() (André Draszik)
- Fix documentation language errors (Randy Dunlap)
- Link to v1: https://lore.kernel.org/r/20251114-s2mu005-pmic-v1-0-9e3184d3a0c9@disroot.org

---
Kaustabh Chakraborty (13):
      dt-bindings: leds: document Samsung S2M series PMIC flash LED device
      dt-bindings: leds: document Samsung S2M series PMIC RGB LED device
      dt-bindings: extcon: document Samsung S2M series PMIC extcon device
      dt-bindings: power: supply: document Samsung S2M series PMIC charger device
      dt-bindings: mfd: s2mps11: add documentation for S2MU005 PMIC
      mfd: sec: add support for S2MU005 PMIC
      mfd: sec: set DMA coherent mask
      mfd: sec: resolve PMIC revision in S2MU005
      leds: flash: add support for Samsung S2M series PMIC flash LED device
      leds: rgb: add support for Samsung S2M series PMIC RGB LED device
      Documentation: leds: document pattern behavior of Samsung S2M series PMIC RGB LEDs
      extcon: add support for Samsung S2M series PMIC extcon devices
      power: supply: add support for Samsung S2M series PMIC charger device

 .../bindings/extcon/samsung,s2mu005-muic.yaml      |  39 ++
 .../bindings/leds/samsung,s2mu005-flash.yaml       |  52 +++
 .../bindings/leds/samsung,s2mu005-rgb.yaml         |  34 ++
 .../devicetree/bindings/mfd/samsung,s2mps11.yaml   | 124 +++++-
 .../power/supply/samsung,s2mu005-charger.yaml      |  39 ++
 Documentation/leds/index.rst                       |   1 +
 Documentation/leds/leds-s2m-rgb.rst                |  60 +++
 drivers/extcon/Kconfig                             |  10 +
 drivers/extcon/Makefile                            |   1 +
 drivers/extcon/extcon-s2m.c                        | 354 ++++++++++++++++
 drivers/leds/flash/Kconfig                         |  12 +
 drivers/leds/flash/Makefile                        |   1 +
 drivers/leds/flash/leds-s2m-flash.c                | 357 +++++++++++++++++
 drivers/leds/rgb/Kconfig                           |  11 +
 drivers/leds/rgb/Makefile                          |   1 +
 drivers/leds/rgb/leds-s2m-rgb.c                    | 446 +++++++++++++++++++++
 drivers/mfd/sec-common.c                           |  37 +-
 drivers/mfd/sec-i2c.c                              |  29 ++
 drivers/mfd/sec-irq.c                              |  74 ++++
 drivers/power/supply/Kconfig                       |  11 +
 drivers/power/supply/Makefile                      |   1 +
 drivers/power/supply/s2m-charger.c                 | 300 ++++++++++++++
 include/linux/mfd/samsung/core.h                   |   1 +
 include/linux/mfd/samsung/irq.h                    |  66 +++
 include/linux/mfd/samsung/s2mu005.h                | 332 +++++++++++++++
 25 files changed, 2387 insertions(+), 6 deletions(-)
---
base-commit: 1c7cc4904160c6fc6377564140062d68a3dc93a0
change-id: 20251112-s2mu005-pmic-0c67fa6bac3c

Best regards,
-- 
Kaustabh Chakraborty <kauschluss@disroot.org>


^ permalink raw reply

* [PATCH v4 01/13] dt-bindings: leds: document Samsung S2M series PMIC flash LED device
From: Kaustabh Chakraborty @ 2026-04-14  6:32 UTC (permalink / raw)
  To: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, MyungJoo Ham, Chanwoo Choi, Sebastian Reichel,
	Krzysztof Kozlowski, André Draszik, Alexandre Belloni,
	Jonathan Corbet, Shuah Khan, Nam Tran,
	Łukasz Lebiedziński
  Cc: linux-leds, devicetree, linux-kernel, linux-pm, linux-samsung-soc,
	linux-rtc, linux-doc, Kaustabh Chakraborty, Conor Dooley
In-Reply-To: <20260414-s2mu005-pmic-v4-0-7fe7480577e6@disroot.org>

Certain Samsung S2M series PMICs have a flash LED controller with
two LED channels, and with torch and flash control modes. Document the
devicetree schema for the device.

Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
 .../bindings/leds/samsung,s2mu005-flash.yaml       | 52 ++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/Documentation/devicetree/bindings/leds/samsung,s2mu005-flash.yaml b/Documentation/devicetree/bindings/leds/samsung,s2mu005-flash.yaml
new file mode 100644
index 0000000000000..36051ab20509f
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/samsung,s2mu005-flash.yaml
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/samsung,s2mu005-flash.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Flash and Torch LED Controller for Samsung S2M series PMICs
+
+maintainers:
+  - Kaustabh Chakraborty <kauschluss@disroot.org>
+
+description: |
+  The Samsung S2M series PMIC flash LED has two led channels (typically
+  as back and front camera flashes), with support for both torch and
+  flash modes.
+
+  This is a part of device tree bindings for S2M and S5M family of Power
+  Management IC (PMIC).
+
+  See also Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml for
+  additional information and example.
+
+properties:
+  compatible:
+    enum:
+      - samsung,s2mu005-flash
+
+  "#address-cells":
+    const: 1
+
+  "#size-cells":
+    const: 0
+
+patternProperties:
+  "^led@[0-1]$":
+    type: object
+    $ref: common.yaml#
+    unevaluatedProperties: false
+
+    properties:
+      reg:
+        enum: [0, 1]
+
+    required:
+      - reg
+
+required:
+  - compatible
+  - "#address-cells"
+  - "#size-cells"
+
+additionalProperties: false

-- 
2.53.0


^ permalink raw reply related

* [PATCH v4 02/13] dt-bindings: leds: document Samsung S2M series PMIC RGB LED device
From: Kaustabh Chakraborty @ 2026-04-14  6:32 UTC (permalink / raw)
  To: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, MyungJoo Ham, Chanwoo Choi, Sebastian Reichel,
	Krzysztof Kozlowski, André Draszik, Alexandre Belloni,
	Jonathan Corbet, Shuah Khan, Nam Tran,
	Łukasz Lebiedziński
  Cc: linux-leds, devicetree, linux-kernel, linux-pm, linux-samsung-soc,
	linux-rtc, linux-doc, Kaustabh Chakraborty
In-Reply-To: <20260414-s2mu005-pmic-v4-0-7fe7480577e6@disroot.org>

Certain Samsung S2M series PMICs have a three-channel LED device with
independent brightness control for each channel, typically used as
status indicators in mobile phones. Document the devicetree schema for
this device.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
 .../bindings/leds/samsung,s2mu005-rgb.yaml         | 34 ++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/Documentation/devicetree/bindings/leds/samsung,s2mu005-rgb.yaml b/Documentation/devicetree/bindings/leds/samsung,s2mu005-rgb.yaml
new file mode 100644
index 0000000000000..6806b6d869ff7
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/samsung,s2mu005-rgb.yaml
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/samsung,s2mu005-rgb.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: RGB LED Controller for Samsung S2M series PMICs
+
+maintainers:
+  - Kaustabh Chakraborty <kauschluss@disroot.org>
+
+description: |
+  The Samsung S2M series PMIC RGB LED is a three-channel LED device with
+  8-bit brightness control for each channel, typically used as status
+  indicators in mobile phones.
+
+  This is a part of device tree bindings for S2M and S5M family of Power
+  Management IC (PMIC).
+
+  See also Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml for
+  additional information and example.
+
+allOf:
+  - $ref: common.yaml#
+
+properties:
+  compatible:
+    enum:
+      - samsung,s2mu005-rgb
+
+required:
+  - compatible
+
+unevaluatedProperties: false

-- 
2.53.0


^ permalink raw reply related

* [PATCH v4 03/13] dt-bindings: extcon: document Samsung S2M series PMIC extcon device
From: Kaustabh Chakraborty @ 2026-04-14  6:32 UTC (permalink / raw)
  To: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, MyungJoo Ham, Chanwoo Choi, Sebastian Reichel,
	Krzysztof Kozlowski, André Draszik, Alexandre Belloni,
	Jonathan Corbet, Shuah Khan, Nam Tran,
	Łukasz Lebiedziński
  Cc: linux-leds, devicetree, linux-kernel, linux-pm, linux-samsung-soc,
	linux-rtc, linux-doc, Kaustabh Chakraborty
In-Reply-To: <20260414-s2mu005-pmic-v4-0-7fe7480577e6@disroot.org>

Certain Samsung S2M series PMICs have a MUIC device which reports
various cable states by measuring the ID-GND resistance with an internal
ADC. Document the devicetree schema for this device.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
 .../bindings/extcon/samsung,s2mu005-muic.yaml      | 39 ++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/Documentation/devicetree/bindings/extcon/samsung,s2mu005-muic.yaml b/Documentation/devicetree/bindings/extcon/samsung,s2mu005-muic.yaml
new file mode 100644
index 0000000000000..e047e8cbc264e
--- /dev/null
+++ b/Documentation/devicetree/bindings/extcon/samsung,s2mu005-muic.yaml
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/extcon/samsung,s2mu005-muic.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MUIC Device for Samsung S2M series PMICs
+
+maintainers:
+  - Kaustabh Chakraborty <kauschluss@disroot.org>
+
+description: |
+  The Samsung S2M series PMIC MUIC device is a USB port accessory
+  detector. It reports multiple states depending on the ID-GND
+  resistance measured by an internal ADC.
+
+  This is a part of device tree bindings for S2M and S5M family of Power
+  Management IC (PMIC).
+
+  See also Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml for
+  additional information and example.
+
+properties:
+  compatible:
+    enum:
+      - samsung,s2mu005-muic
+
+  connector:
+    $ref: /schemas/connector/usb-connector.yaml#
+
+  port:
+    $ref: /schemas/graph.yaml#/properties/port
+
+required:
+  - compatible
+  - connector
+  - port
+
+additionalProperties: false

-- 
2.53.0


^ permalink raw reply related

* [PATCH v4 04/13] dt-bindings: power: supply: document Samsung S2M series PMIC charger device
From: Kaustabh Chakraborty @ 2026-04-14  6:32 UTC (permalink / raw)
  To: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, MyungJoo Ham, Chanwoo Choi, Sebastian Reichel,
	Krzysztof Kozlowski, André Draszik, Alexandre Belloni,
	Jonathan Corbet, Shuah Khan, Nam Tran,
	Łukasz Lebiedziński
  Cc: linux-leds, devicetree, linux-kernel, linux-pm, linux-samsung-soc,
	linux-rtc, linux-doc, Kaustabh Chakraborty
In-Reply-To: <20260414-s2mu005-pmic-v4-0-7fe7480577e6@disroot.org>

Certain Samsung S2M series PMICs have a battery charger device which,
among other things, manages power interfacing of the USB port. It may
supply power, as done in USB OTG operation mode, or it may accept power
and redirect it to the battery fuelgauge for charging. Document this
device.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
 .../power/supply/samsung,s2mu005-charger.yaml      | 39 ++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/Documentation/devicetree/bindings/power/supply/samsung,s2mu005-charger.yaml b/Documentation/devicetree/bindings/power/supply/samsung,s2mu005-charger.yaml
new file mode 100644
index 0000000000000..4ae45165b85fb
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/samsung,s2mu005-charger.yaml
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/power/supply/samsung,s2mu005-charger.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Battery Charger for Samsung S2M series PMICs
+
+maintainers:
+  - Kaustabh Chakraborty <kauschluss@disroot.org>
+
+description: |
+  The Samsung S2M series PMIC battery charger manages power interfacing
+  of the USB port. It may supply power, as done in USB OTG operation
+  mode, or it may accept power and redirect it to the battery fuelgauge
+  for charging.
+
+  This is a part of device tree bindings for S2M and S5M family of Power
+  Management IC (PMIC).
+
+  See also Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml for
+  additional information and example.
+
+allOf:
+  - $ref: power-supply.yaml#
+
+properties:
+  compatible:
+    enum:
+      - samsung,s2mu005-charger
+
+  port:
+    $ref: /schemas/graph.yaml#/properties/port
+
+required:
+  - compatible
+  - port
+
+unevaluatedProperties: false

-- 
2.53.0


^ permalink raw reply related

* [PATCH v4 05/13] dt-bindings: mfd: s2mps11: add documentation for S2MU005 PMIC
From: Kaustabh Chakraborty @ 2026-04-14  6:32 UTC (permalink / raw)
  To: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, MyungJoo Ham, Chanwoo Choi, Sebastian Reichel,
	Krzysztof Kozlowski, André Draszik, Alexandre Belloni,
	Jonathan Corbet, Shuah Khan, Nam Tran,
	Łukasz Lebiedziński
  Cc: linux-leds, devicetree, linux-kernel, linux-pm, linux-samsung-soc,
	linux-rtc, linux-doc, Kaustabh Chakraborty
In-Reply-To: <20260414-s2mu005-pmic-v4-0-7fe7480577e6@disroot.org>

Samsung's S2MU005 PMIC includes subdevices for a charger, an MUIC (Micro
USB Interface Controller), and flash and RGB LED controllers.

Since regulators are not supported by this device, unmark this property
as required and instead set this in a per-device basis for ones which
need it.

Add the compatible and documentation for the S2MU005 PMIC. Also, add an
example for nodes for supported sub-devices, i.e. charger, extcon,
flash, and rgb.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
 .../devicetree/bindings/mfd/samsung,s2mps11.yaml   | 121 ++++++++++++++++++++-
 1 file changed, 120 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml b/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml
index ac5d0c149796b..d3d305b9aa765 100644
--- a/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml
+++ b/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml
@@ -26,12 +26,28 @@ properties:
       - samsung,s2mps15-pmic
       - samsung,s2mpu02-pmic
       - samsung,s2mpu05-pmic
+      - samsung,s2mu005-pmic
 
   clocks:
     $ref: /schemas/clock/samsung,s2mps11.yaml
     description:
       Child node describing clock provider.
 
+  charger:
+    $ref: /schemas/power/supply/samsung,s2mu005-charger.yaml
+    description:
+      Child node describing battery charger device.
+
+  extcon:
+    $ref: /schemas/extcon/samsung,s2mu005-muic.yaml
+    description:
+      Child node describing extcon device.
+
+  flash:
+    $ref: /schemas/leds/samsung,s2mu005-flash.yaml
+    description:
+      Child node describing flash LEDs.
+
   interrupts:
     maxItems: 1
 
@@ -43,6 +59,11 @@ properties:
     description:
       List of child nodes that specify the regulators.
 
+  rgb:
+    $ref: /schemas/leds/samsung,s2mu005-rgb.yaml
+    description:
+      Child node describing RGB LEDs.
+
   samsung,s2mps11-acokb-ground:
     description: |
       Indicates that ACOKB pin of S2MPS11 PMIC is connected to the ground so
@@ -63,7 +84,6 @@ properties:
 required:
   - compatible
   - reg
-  - regulators
 
 additionalProperties: false
 
@@ -78,6 +98,8 @@ allOf:
         regulators:
           $ref: /schemas/regulator/samsung,s2mps11.yaml
         samsung,s2mps11-wrstbi-ground: false
+      required:
+        - regulators
 
   - if:
       properties:
@@ -89,6 +111,8 @@ allOf:
         regulators:
           $ref: /schemas/regulator/samsung,s2mps13.yaml
         samsung,s2mps11-acokb-ground: false
+      required:
+        - regulators
 
   - if:
       properties:
@@ -101,6 +125,8 @@ allOf:
           $ref: /schemas/regulator/samsung,s2mps14.yaml
         samsung,s2mps11-acokb-ground: false
         samsung,s2mps11-wrstbi-ground: false
+      required:
+        - regulators
 
   - if:
       properties:
@@ -113,6 +139,8 @@ allOf:
           $ref: /schemas/regulator/samsung,s2mps15.yaml
         samsung,s2mps11-acokb-ground: false
         samsung,s2mps11-wrstbi-ground: false
+      required:
+        - regulators
 
   - if:
       properties:
@@ -125,6 +153,8 @@ allOf:
           $ref: /schemas/regulator/samsung,s2mpu02.yaml
         samsung,s2mps11-acokb-ground: false
         samsung,s2mps11-wrstbi-ground: false
+      required:
+        - regulators
 
   - if:
       properties:
@@ -137,6 +167,18 @@ allOf:
           $ref: /schemas/regulator/samsung,s2mpu05.yaml
         samsung,s2mps11-acokb-ground: false
         samsung,s2mps11-wrstbi-ground: false
+      required:
+        - regulators
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: samsung,s2mu005-pmic
+    then:
+      properties:
+        samsung,s2mps11-acokb-ground: false
+        samsung,s2mps11-wrstbi-ground: false
 
 examples:
   - |
@@ -278,3 +320,80 @@ examples:
             };
         };
     };
+
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/leds/common.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        pmic@3d {
+            compatible = "samsung,s2mu005-pmic";
+            reg = <0x3d>;
+            interrupt-parent = <&gpa2>;
+            interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+
+            charger {
+                compatible = "samsung,s2mu005-charger";
+                monitored-battery = <&battery>;
+
+                port {
+                    charger_to_muic: endpoint {
+                        remote-endpoint = <&muic_to_charger>;
+                    };
+                };
+            };
+
+            extcon {
+                compatible = "samsung,s2mu005-muic";
+
+                connector {
+                    compatible = "usb-b-connector";
+                    label = "micro-USB";
+                    type = "micro";
+                };
+
+                port {
+                    muic_to_charger: endpoint@0 {
+                        reg = <0>;
+                        remote-endpoint = <&charger_to_muic>;
+                    };
+
+                    muic_to_usb: endpoint@1 {
+                        reg = <1>;
+                        remote-endpoint = <&usb_to_muic>;
+                    };
+                };
+            };
+
+            flash {
+                compatible = "samsung,s2mu005-flash";
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                led@0 {
+                    reg = <0>;
+                    label = "back-cam:white:flash";
+                    color = <LED_COLOR_ID_WHITE>;
+                    function = LED_FUNCTION_FLASH;
+                };
+
+                led@1 {
+                    reg = <1>;
+                    label = "front-cam:white:flash";
+                    color = <LED_COLOR_ID_WHITE>;
+                    function = LED_FUNCTION_FLASH;
+                };
+            };
+
+            rgb {
+                compatible = "samsung,s2mu005-rgb";
+                label = "notification:rgb:indicator";
+                color = <LED_COLOR_ID_RGB>;
+                function = LED_FUNCTION_INDICATOR;
+                linux,default-trigger = "pattern";
+            };
+        };
+    };

-- 
2.53.0


^ permalink raw reply related

* [PATCH v4 06/13] mfd: sec: add support for S2MU005 PMIC
From: Kaustabh Chakraborty @ 2026-04-14  6:32 UTC (permalink / raw)
  To: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, MyungJoo Ham, Chanwoo Choi, Sebastian Reichel,
	Krzysztof Kozlowski, André Draszik, Alexandre Belloni,
	Jonathan Corbet, Shuah Khan, Nam Tran,
	Łukasz Lebiedziński
  Cc: linux-leds, devicetree, linux-kernel, linux-pm, linux-samsung-soc,
	linux-rtc, linux-doc, Kaustabh Chakraborty
In-Reply-To: <20260414-s2mu005-pmic-v4-0-7fe7480577e6@disroot.org>

Samsung's S2MU005 PMIC includes subdevices for a charger, an MUIC (Micro
USB Interface Controller), and flash and RGB LED controllers.

S2MU005's interrupt registers can be properly divided into three regmap
IRQ chips, one each for the charger, flash LEDs, and the MUIC.

Add initial support for S2MU005 in the PMIC driver, along with it's three
interrupt chips.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
 drivers/mfd/sec-common.c            |  16 ++
 drivers/mfd/sec-i2c.c               |  29 ++++
 drivers/mfd/sec-irq.c               |  74 ++++++++
 include/linux/mfd/samsung/core.h    |   1 +
 include/linux/mfd/samsung/irq.h     |  66 ++++++++
 include/linux/mfd/samsung/s2mu005.h | 327 ++++++++++++++++++++++++++++++++++++
 6 files changed, 513 insertions(+)

diff --git a/drivers/mfd/sec-common.c b/drivers/mfd/sec-common.c
index bd8b5f9686892..b3268516bf75e 100644
--- a/drivers/mfd/sec-common.c
+++ b/drivers/mfd/sec-common.c
@@ -105,6 +105,18 @@ static const struct mfd_cell s2mpu05_devs[] = {
 	MFD_CELL_RES("s2mps15-rtc", s2mpu05_rtc_resources),
 };
 
+static const struct resource s2mu005_muic_resources[] = {
+	DEFINE_RES_IRQ_NAMED(S2MU005_IRQ_MUIC_ATTACH, "attach"),
+	DEFINE_RES_IRQ_NAMED(S2MU005_IRQ_MUIC_DETACH, "detach"),
+};
+
+static const struct mfd_cell s2mu005_devs[] = {
+	MFD_CELL_OF("s2mu005-charger", NULL, NULL, 0, 0, "samsung,s2mu005-charger"),
+	MFD_CELL_OF("s2mu005-flash", NULL, NULL, 0, 0, "samsung,s2mu005-flash"),
+	MFD_CELL_OF("s2mu005-muic", s2mu005_muic_resources, NULL, 0, 0, "samsung,s2mu005-muic"),
+	MFD_CELL_OF("s2mu005-rgb", NULL, NULL, 0, 0, "samsung,s2mu005-rgb"),
+};
+
 static void sec_pmic_dump_rev(struct sec_pmic_dev *sec_pmic)
 {
 	unsigned int val;
@@ -250,6 +262,10 @@ int sec_pmic_probe(struct device *dev, int device_type, unsigned int irq,
 		sec_devs = s2mpu05_devs;
 		num_sec_devs = ARRAY_SIZE(s2mpu05_devs);
 		break;
+	case S2MU005:
+		sec_devs = s2mu005_devs;
+		num_sec_devs = ARRAY_SIZE(s2mu005_devs);
+		break;
 	default:
 		return dev_err_probe(sec_pmic->dev, -EINVAL,
 				     "Unsupported device type %d\n",
diff --git a/drivers/mfd/sec-i2c.c b/drivers/mfd/sec-i2c.c
index 3132b849b4bc4..d8609886fcc80 100644
--- a/drivers/mfd/sec-i2c.c
+++ b/drivers/mfd/sec-i2c.c
@@ -17,6 +17,7 @@
 #include <linux/mfd/samsung/s2mps14.h>
 #include <linux/mfd/samsung/s2mps15.h>
 #include <linux/mfd/samsung/s2mpu02.h>
+#include <linux/mfd/samsung/s2mu005.h>
 #include <linux/mfd/samsung/s5m8767.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
@@ -66,6 +67,19 @@ static bool s2mpu02_volatile(struct device *dev, unsigned int reg)
 	}
 }
 
+static bool s2mu005_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case S2MU005_REG_CHGR_INT1M:
+	case S2MU005_REG_FLED_INT1M:
+	case S2MU005_REG_MUIC_INT1M:
+	case S2MU005_REG_MUIC_INT2M:
+		return false;
+	default:
+		return true;
+	}
+}
+
 static const struct regmap_config s2dos05_regmap_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
@@ -130,6 +144,15 @@ static const struct regmap_config s2mpu05_regmap_config = {
 	.val_bits = 8,
 };
 
+static const struct regmap_config s2mu005_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = S2MU005_REG_MUIC_LDOADC_H,
+	.volatile_reg = s2mu005_volatile,
+	.cache_type = REGCACHE_FLAT_S,
+};
+
 static const struct regmap_config s5m8767_regmap_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
@@ -203,6 +226,11 @@ static const struct sec_pmic_i2c_platform_data s2mpu05_data = {
 	.device_type = S2MPU05,
 };
 
+static const struct sec_pmic_i2c_platform_data s2mu005_data = {
+	.regmap_cfg = &s2mu005_regmap_config,
+	.device_type = S2MU005,
+};
+
 static const struct sec_pmic_i2c_platform_data s5m8767_data = {
 	.regmap_cfg = &s5m8767_regmap_config,
 	.device_type = S5M8767X,
@@ -217,6 +245,7 @@ static const struct of_device_id sec_pmic_i2c_of_match[] = {
 	{ .compatible = "samsung,s2mps15-pmic", .data = &s2mps15_data, },
 	{ .compatible = "samsung,s2mpu02-pmic", .data = &s2mpu02_data, },
 	{ .compatible = "samsung,s2mpu05-pmic", .data = &s2mpu05_data, },
+	{ .compatible = "samsung,s2mu005-pmic", .data = &s2mu005_data, },
 	{ .compatible = "samsung,s5m8767-pmic", .data = &s5m8767_data, },
 	{ },
 };
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index 133188391f7c2..91a2922463fb6 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -16,6 +16,7 @@
 #include <linux/mfd/samsung/s2mps14.h>
 #include <linux/mfd/samsung/s2mpu02.h>
 #include <linux/mfd/samsung/s2mpu05.h>
+#include <linux/mfd/samsung/s2mu005.h>
 #include <linux/mfd/samsung/s5m8767.h>
 #include <linux/regmap.h>
 #include "sec-core.h"
@@ -223,6 +224,65 @@ static const struct regmap_irq s2mpu05_irqs[] = {
 	REGMAP_IRQ_REG(S2MPU05_IRQ_TSD, 2, S2MPU05_IRQ_TSD_MASK),
 };
 
+static const struct regmap_irq s2mu005_irqs[] = {
+	REGMAP_IRQ_REG(S2MU005_IRQ_CHGR_DETBAT, 0, S2MU005_IRQ_CHGR_DETBAT_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_CHGR_BAT, 0, S2MU005_IRQ_CHGR_BAT_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_CHGR_IVR, 0, S2MU005_IRQ_CHGR_IVR_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_CHGR_EVENT, 0, S2MU005_IRQ_CHGR_EVENT_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_CHGR_CHG, 0, S2MU005_IRQ_CHGR_CHG_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_CHGR_VMID, 0, S2MU005_IRQ_CHGR_VMID_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_CHGR_WCIN, 0, S2MU005_IRQ_CHGR_WCIN_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_CHGR_VBUS, 0, S2MU005_IRQ_CHGR_VBUS_MASK),
+
+	REGMAP_IRQ_REG(S2MU005_IRQ_FLED_LBPROT, 1, S2MU005_IRQ_FLED_LBPROT_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_FLED_OPENCH2, 1, S2MU005_IRQ_FLED_OPENCH2_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_FLED_OPENCH1, 1, S2MU005_IRQ_FLED_OPENCH1_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_FLED_SHORTCH2, 1, S2MU005_IRQ_FLED_SHORTCH2_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_FLED_SHORTCH1, 1, S2MU005_IRQ_FLED_SHORTCH1_MASK),
+
+	REGMAP_IRQ_REG(S2MU005_IRQ_MUIC_ATTACH, 2, S2MU005_IRQ_MUIC_ATTACH_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_MUIC_DETACH, 2, S2MU005_IRQ_MUIC_DETACH_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_MUIC_KP, 2, S2MU005_IRQ_MUIC_KP_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_MUIC_LKP, 2, S2MU005_IRQ_MUIC_LKP_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_MUIC_LKR, 2, S2MU005_IRQ_MUIC_LKR_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_MUIC_RIDCHG, 2, S2MU005_IRQ_MUIC_RIDCHG_MASK),
+
+	REGMAP_IRQ_REG(S2MU005_IRQ_MUIC_VBUSON, 3, S2MU005_IRQ_MUIC_VBUSON_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_MUIC_RSVD, 3, S2MU005_IRQ_MUIC_RSVD_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_MUIC_ADC, 3, S2MU005_IRQ_MUIC_ADC_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_MUIC_STUCK, 3, S2MU005_IRQ_MUIC_STUCK_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_MUIC_STUCKRCV, 3, S2MU005_IRQ_MUIC_STUCKRCV_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_MUIC_MHDL, 3, S2MU005_IRQ_MUIC_MHDL_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_MUIC_AVCHG, 3, S2MU005_IRQ_MUIC_AVCHG_MASK),
+	REGMAP_IRQ_REG(S2MU005_IRQ_MUIC_VBUSOFF, 3, S2MU005_IRQ_MUIC_VBUSOFF_MASK),
+};
+
+static unsigned int s2mu005_irq_get_reg(struct regmap_irq_chip_data *data,
+					unsigned int base, int index)
+{
+	const unsigned int irqf_regs[] = {
+		S2MU005_REG_CHGR_INT1,
+		S2MU005_REG_FLED_INT1,
+		S2MU005_REG_MUIC_INT1,
+		S2MU005_REG_MUIC_INT2,
+	};
+	const unsigned int mask_regs[] = {
+		S2MU005_REG_CHGR_INT1M,
+		S2MU005_REG_FLED_INT1M,
+		S2MU005_REG_MUIC_INT1M,
+		S2MU005_REG_MUIC_INT2M,
+	};
+
+	switch (base) {
+	case S2MU005_REG_CHGR_INT1:
+		return irqf_regs[index];
+	case S2MU005_REG_CHGR_INT1M:
+		return mask_regs[index];
+	}
+
+	return base;
+}
+
 static const struct regmap_irq s5m8767_irqs[] = {
 	REGMAP_IRQ_REG(S5M8767_IRQ_PWRR, 0, S5M8767_IRQ_PWRR_MASK),
 	REGMAP_IRQ_REG(S5M8767_IRQ_PWRF, 0, S5M8767_IRQ_PWRF_MASK),
@@ -337,6 +397,17 @@ static const struct regmap_irq_chip s2mpu05_irq_chip = {
 	.ack_base = S2MPU05_REG_INT1,
 };
 
+static const struct regmap_irq_chip s2mu005_irq_chip = {
+	.name = "s2mu005",
+	.irqs = s2mu005_irqs,
+	.num_irqs = ARRAY_SIZE(s2mu005_irqs),
+	.num_regs = 4,
+	.status_base = S2MU005_REG_CHGR_INT1,
+	.mask_base = S2MU005_REG_CHGR_INT1M,
+	.ack_base = S2MU005_REG_CHGR_INT1,
+	.get_irq_reg = s2mu005_irq_get_reg,
+};
+
 static const struct regmap_irq_chip s5m8767_irq_chip = {
 	.name = "s5m8767",
 	.irqs = s5m8767_irqs,
@@ -442,6 +513,9 @@ struct regmap_irq_chip_data *sec_irq_init(struct sec_pmic_dev *sec_pmic)
 	case S2MPU05:
 		sec_irq_chip = &s2mpu05_irq_chip;
 		break;
+	case S2MU005:
+		sec_irq_chip = &s2mu005_irq_chip;
+		break;
 	default:
 		return dev_err_ptr_probe(sec_pmic->dev, -EINVAL, "Unsupported device type %d\n",
 					 sec_pmic->device_type);
diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h
index 4480c631110a6..6191f409de945 100644
--- a/include/linux/mfd/samsung/core.h
+++ b/include/linux/mfd/samsung/core.h
@@ -47,6 +47,7 @@ enum sec_device_type {
 	S2MPS15X,
 	S2MPU02,
 	S2MPU05,
+	S2MU005,
 };
 
 /**
diff --git a/include/linux/mfd/samsung/irq.h b/include/linux/mfd/samsung/irq.h
index 6eab95de6fa83..19d0f0e12944f 100644
--- a/include/linux/mfd/samsung/irq.h
+++ b/include/linux/mfd/samsung/irq.h
@@ -408,6 +408,72 @@ enum s2mpu05_irq {
 #define S2MPU05_IRQ_INT140C_MASK	BIT(1)
 #define S2MPU05_IRQ_TSD_MASK		BIT(2)
 
+enum s2mu005_irq {
+	S2MU005_IRQ_CHGR_DETBAT,
+	S2MU005_IRQ_CHGR_BAT,
+	S2MU005_IRQ_CHGR_IVR,
+	S2MU005_IRQ_CHGR_EVENT,
+	S2MU005_IRQ_CHGR_CHG,
+	S2MU005_IRQ_CHGR_VMID,
+	S2MU005_IRQ_CHGR_WCIN,
+	S2MU005_IRQ_CHGR_VBUS,
+
+	S2MU005_IRQ_FLED_LBPROT,
+	S2MU005_IRQ_FLED_OPENCH2,
+	S2MU005_IRQ_FLED_OPENCH1,
+	S2MU005_IRQ_FLED_SHORTCH2,
+	S2MU005_IRQ_FLED_SHORTCH1,
+
+	S2MU005_IRQ_MUIC_ATTACH,
+	S2MU005_IRQ_MUIC_DETACH,
+	S2MU005_IRQ_MUIC_KP,
+	S2MU005_IRQ_MUIC_LKP,
+	S2MU005_IRQ_MUIC_LKR,
+	S2MU005_IRQ_MUIC_RIDCHG,
+
+	S2MU005_IRQ_MUIC_VBUSON,
+	S2MU005_IRQ_MUIC_RSVD,
+	S2MU005_IRQ_MUIC_ADC,
+	S2MU005_IRQ_MUIC_STUCK,
+	S2MU005_IRQ_MUIC_STUCKRCV,
+	S2MU005_IRQ_MUIC_MHDL,
+	S2MU005_IRQ_MUIC_AVCHG,
+	S2MU005_IRQ_MUIC_VBUSOFF,
+
+	S2MU005_IRQ_NR,
+};
+
+#define S2MU005_IRQ_CHGR_DETBAT_MASK	BIT(0)
+#define S2MU005_IRQ_CHGR_BAT_MASK	BIT(1)
+#define S2MU005_IRQ_CHGR_IVR_MASK	BIT(2)
+#define S2MU005_IRQ_CHGR_EVENT_MASK	BIT(3)
+#define S2MU005_IRQ_CHGR_CHG_MASK	BIT(4)
+#define S2MU005_IRQ_CHGR_VMID_MASK	BIT(5)
+#define S2MU005_IRQ_CHGR_WCIN_MASK	BIT(6)
+#define S2MU005_IRQ_CHGR_VBUS_MASK	BIT(7)
+
+#define S2MU005_IRQ_FLED_LBPROT_MASK		BIT(2)
+#define S2MU005_IRQ_FLED_OPENCH2_MASK		BIT(4)
+#define S2MU005_IRQ_FLED_OPENCH1_MASK		BIT(5)
+#define S2MU005_IRQ_FLED_SHORTCH2_MASK		BIT(6)
+#define S2MU005_IRQ_FLED_SHORTCH1_MASK		BIT(7)
+
+#define S2MU005_IRQ_MUIC_ATTACH_MASK		BIT(0)
+#define S2MU005_IRQ_MUIC_DETACH_MASK		BIT(1)
+#define S2MU005_IRQ_MUIC_KP_MASK		BIT(2)
+#define S2MU005_IRQ_MUIC_LKP_MASK		BIT(3)
+#define S2MU005_IRQ_MUIC_LKR_MASK		BIT(4)
+#define S2MU005_IRQ_MUIC_RIDCHG_MASK		BIT(5)
+
+#define S2MU005_IRQ_MUIC_VBUSON_MASK		BIT(0)
+#define S2MU005_IRQ_MUIC_RSVD_MASK		BIT(1)
+#define S2MU005_IRQ_MUIC_ADC_MASK		BIT(2)
+#define S2MU005_IRQ_MUIC_STUCK_MASK		BIT(3)
+#define S2MU005_IRQ_MUIC_STUCKRCV_MASK		BIT(4)
+#define S2MU005_IRQ_MUIC_MHDL_MASK		BIT(5)
+#define S2MU005_IRQ_MUIC_AVCHG_MASK		BIT(6)
+#define S2MU005_IRQ_MUIC_VBUSOFF_MASK		BIT(7)
+
 enum s5m8767_irq {
 	S5M8767_IRQ_PWRR,
 	S5M8767_IRQ_PWRF,
diff --git a/include/linux/mfd/samsung/s2mu005.h b/include/linux/mfd/samsung/s2mu005.h
new file mode 100644
index 0000000000000..07f4ae664950d
--- /dev/null
+++ b/include/linux/mfd/samsung/s2mu005.h
@@ -0,0 +1,327 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd
+ * Copyright (c) 2025 Kaustabh Chakraborty <kauschluss@disroot.org>
+ */
+
+#ifndef __LINUX_MFD_S2MU005_H
+#define __LINUX_MFD_S2MU005_H
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+
+/* S2MU005 registers */
+enum s2mu005_reg {
+	S2MU005_REG_CHGR_INT1,
+	S2MU005_REG_CHGR_INT1M,
+
+	S2MU005_REG_FLED_INT1,
+	S2MU005_REG_FLED_INT1M,
+
+	S2MU005_REG_MUIC_INT1,
+	S2MU005_REG_MUIC_INT2,
+	S2MU005_REG_MUIC_INT1M,
+	S2MU005_REG_MUIC_INT2M,
+
+	S2MU005_REG_CHGR_STATUS0,
+	S2MU005_REG_CHGR_STATUS1,
+	S2MU005_REG_CHGR_STATUS2,
+	S2MU005_REG_CHGR_STATUS3,
+	S2MU005_REG_CHGR_STATUS4,
+	S2MU005_REG_CHGR_STATUS5,
+	S2MU005_REG_CHGR_CTRL0,
+	S2MU005_REG_CHGR_CTRL1,
+	S2MU005_REG_CHGR_CTRL2,
+	S2MU005_REG_CHGR_CTRL3,
+	S2MU005_REG_CHGR_CTRL4,
+	S2MU005_REG_CHGR_CTRL5,
+	S2MU005_REG_CHGR_CTRL6,
+	S2MU005_REG_CHGR_CTRL7,
+	S2MU005_REG_CHGR_CTRL8,
+	S2MU005_REG_CHGR_CTRL9,
+	S2MU005_REG_CHGR_CTRL10,
+	S2MU005_REG_CHGR_CTRL11,
+	S2MU005_REG_CHGR_CTRL12,
+	S2MU005_REG_CHGR_CTRL13,
+	S2MU005_REG_CHGR_CTRL14,
+	S2MU005_REG_CHGR_CTRL15,
+	S2MU005_REG_CHGR_CTRL16,
+	S2MU005_REG_CHGR_CTRL17,
+	S2MU005_REG_CHGR_CTRL18,
+	S2MU005_REG_CHGR_CTRL19,
+	S2MU005_REG_CHGR_TEST0,
+	S2MU005_REG_CHGR_TEST1,
+	S2MU005_REG_CHGR_TEST2,
+	S2MU005_REG_CHGR_TEST3,
+	S2MU005_REG_CHGR_TEST4,
+	S2MU005_REG_CHGR_TEST5,
+	S2MU005_REG_CHGR_TEST6,
+	S2MU005_REG_CHGR_TEST7,
+	S2MU005_REG_CHGR_TEST8,
+	S2MU005_REG_CHGR_TEST9,
+	S2MU005_REG_CHGR_TEST10,
+
+	S2MU005_REG_FLED_STATUS,
+	S2MU005_REG_FLED_CH0_CTRL0,
+	S2MU005_REG_FLED_CH0_CTRL1,
+	S2MU005_REG_FLED_CH0_CTRL2,
+	S2MU005_REG_FLED_CH0_CTRL3,
+	S2MU005_REG_FLED_CH1_CTRL0,
+	S2MU005_REG_FLED_CH1_CTRL1,
+	S2MU005_REG_FLED_CH1_CTRL2,
+	S2MU005_REG_FLED_CH1_CTRL3,
+	S2MU005_REG_FLED_CTRL0,
+	S2MU005_REG_FLED_CTRL1,
+	S2MU005_REG_FLED_CTRL2,
+	S2MU005_REG_FLED_CTRL3,
+	S2MU005_REG_FLED_CTRL4,
+	S2MU005_REG_FLED_CTRL5,
+	S2MU005_REG_FLED_CTRL6,
+
+	S2MU005_REG_RGB_EN,
+	S2MU005_REG_RGB_CH0_CTRL,
+	S2MU005_REG_RGB_CH1_CTRL,
+	S2MU005_REG_RGB_CH2_CTRL,
+	S2MU005_REG_RGB_CH0_RAMP,
+	S2MU005_REG_RGB_CH0_STAY,
+	S2MU005_REG_RGB_CH1_RAMP,
+	S2MU005_REG_RGB_CH1_STAY,
+	S2MU005_REG_RGB_CH2_RAMP,
+	S2MU005_REG_RGB_CH2_STAY,
+	S2MU005_REG_RGB_TEST0,
+	S2MU005_REG_RGB_CTRL0,
+
+	S2MU005_REG_MUIC_ADC,
+	S2MU005_REG_MUIC_DEV1,
+	S2MU005_REG_MUIC_DEV2,
+	S2MU005_REG_MUIC_DEV3,
+	S2MU005_REG_MUIC_BUTTON1,
+	S2MU005_REG_MUIC_BUTTON2,
+	S2MU005_REG_MUIC_RESET,
+	S2MU005_REG_MUIC_CHGTYPE,
+	S2MU005_REG_MUIC_DEVAPPLE,
+	S2MU005_REG_MUIC_BCDRESCAN,
+	S2MU005_REG_MUIC_TEST1,
+	S2MU005_REG_MUIC_TEST2,
+	S2MU005_REG_MUIC_TEST3,
+
+	S2MU005_REG_ID = 0x73,
+
+	S2MU005_REG_MUIC_CTRL1 = 0xb2,
+	S2MU005_REG_MUIC_TIMERSET1,
+	S2MU005_REG_MUIC_TIMERSET2,
+	S2MU005_REG_MUIC_SWCTRL,
+	S2MU005_REG_MUIC_TIMERSET3,
+	S2MU005_REG_MUIC_CTRL2,
+	S2MU005_REG_MUIC_CTRL3,
+
+	S2MU005_REG_MUIC_LDOADC_L = 0xbf,
+	S2MU005_REG_MUIC_LDOADC_H,
+};
+
+#define S2MU005_REG_FLED_CH_CTRL0(x)	(S2MU005_REG_FLED_CH0_CTRL0 + 4 * (x))
+#define S2MU005_REG_FLED_CH_CTRL1(x)	(S2MU005_REG_FLED_CH0_CTRL1 + 4 * (x))
+#define S2MU005_REG_FLED_CH_CTRL2(x)	(S2MU005_REG_FLED_CH0_CTRL2 + 4 * (x))
+#define S2MU005_REG_FLED_CH_CTRL3(x)	(S2MU005_REG_FLED_CH0_CTRL3 + 4 * (x))
+
+#define S2MU005_REG_RGB_CH_CTRL(x)	(S2MU005_REG_RGB_CH0_CTRL + 1 * (x))
+#define S2MU005_REG_RGB_CH_RAMP(x)	(S2MU005_REG_RGB_CH0_RAMP + 2 * (x))
+#define S2MU005_REG_RGB_CH_STAY(x)	(S2MU005_REG_RGB_CH0_STAY + 2 * (x))
+
+/* S2MU005_REG_CHGR_STATUS0 */
+#define S2MU005_CHGR_VBUS		BIT(7)
+#define S2MU005_CHGR_WCIN		BIT(6)
+#define S2MU005_CHGR_VMID		BIT(5)
+#define S2MU005_CHGR_CHG		BIT(4)
+#define S2MU005_CHGR_STAT		GENMASK(3, 0)
+
+#define S2MU005_CHGR_STAT_DONE		8
+#define S2MU005_CHGR_STAT_TOPOFF	7
+#define S2MU005_CHGR_STAT_DONE_FLAG	6
+#define S2MU005_CHGR_STAT_CV		5
+#define S2MU005_CHGR_STAT_CC		4
+#define S2MU005_CHGR_STAT_COOL_CHG	3
+#define S2MU005_CHGR_STAT_PRE_CHG	2
+
+/* S2MU005_REG_CHGR_STATUS1 */
+#define S2MU005_CHGR_DETBAT		BIT(7)
+#define S2MU005_CHGR_VBUS_OVP		GENMASK(6, 4)
+
+#define S2MU005_CHGR_VBUS_OVP_OVERVOLT	2
+
+/* S2MU005_REG_CHGR_STATUS2 */
+#define S2MU005_CHGR_BAT		GENMASK(6, 4)
+
+#define S2MU005_CHGR_BAT_VOLT_DET	7
+#define S2MU005_CHGR_BAT_FAST_CHG_DET	6
+#define S2MU005_CHGR_BAT_COOL_CHG_DET	5
+#define S2MU005_CHGR_BAT_LOW_CHG	2
+#define S2MU005_CHGR_BAT_SELF_DISCHG	1
+#define S2MU005_CHGR_BAT_OVP_DET	0
+
+/* S2MU005_REG_CHGR_STATUS3 */
+#define S2MU005_CHGR_EVT		GENMASK(3, 0)
+
+#define S2MU005_CHGR_EVT_WDT_RST	6
+#define S2MU005_CHGR_EVT_WDT_SUSP	5
+#define S2MU005_CHGR_EVT_VSYS_VUVLO	4
+#define S2MU005_CHGR_EVT_VSYS_VOVP	3
+#define S2MU005_CHGR_EVT_THERM_FOLDBACK	2
+#define S2MU005_CHGR_EVT_THERM_SHUTDOWN	1
+
+/* S2MU005_REG_CHGR_CTRL0 */
+#define S2MU005_CHGR_CHG_EN		BIT(4)
+#define S2MU005_CHGR_OP_MODE		GENMASK(2, 0)
+
+#define S2MU005_CHGR_OP_MODE_OTG	BIT(2)
+#define S2MU005_CHGR_OP_MODE_CHG	BIT(1)
+
+/* S2MU005_REG_CHGR_CTRL1 */
+#define S2MU005_CHGR_VIN_DROP		GENMASK(6, 4)
+
+/* S2MU005_REG_CHGR_CTRL2 */
+#define S2MU005_CHGR_IN_CURR_LIM	GENMASK(5, 0)
+
+/* S2MU005_REG_CHGR_CTRL4 */
+#define S2MU005_CHGR_OTG_OCP_ON		BIT(5)
+#define S2MU005_CHGR_OTG_OCP_OFF	BIT(4)
+#define S2MU005_CHGR_OTG_OCP		GENMASK(3, 2)
+
+/* S2MU005_REG_CHGR_CTRL5 */
+#define S2MU005_CHGR_VMID_BOOST		GENMASK(4, 0)
+
+/* S2MU005_REG_CHGR_CTRL6 */
+#define S2MU005_CHGR_COOL_CHG_CURR	GENMASK(5, 0)
+
+/* S2MU005_REG_CHGR_CTRL7 */
+#define S2MU005_CHGR_FAST_CHG_CURR	GENMASK(5, 0)
+
+/* S2MU005_REG_CHGR_CTRL8 */
+#define S2MU005_CHGR_VF_VBAT		GENMASK(6, 1)
+
+/* S2MU005_REG_CHGR_CTRL10 */
+#define S2MU005_CHGR_TOPOFF_CURR(x)	(GENMASK(3, 0) << 4 * (x))
+
+/* S2MU005_REG_CHGR_CTRL11 */
+#define S2MU005_CHGR_OSC_BOOST		GENMASK(6, 5)
+#define S2MU005_CHGR_OSC_BUCK		GENMASK(4, 3)
+
+/* S2MU005_REG_CHGR_CTRL12 */
+#define S2MU005_CHGR_WDT		GENMASK(2, 0)
+
+#define S2MU005_CHGR_WDT_ON		BIT(2)
+#define S2MU005_CHGR_WDT_OFF		BIT(1)
+
+/* S2MU005_REG_CHGR_CTRL15 */
+#define S2MU005_CHGR_OTG_EN		GENMASK(3, 2)
+
+/* S2MU005_REG_FLED_STATUS */
+#define S2MU005_FLED_FLASH_STATUS(x)	(BIT(7) >> 2 * (x))
+#define S2MU005_FLED_TORCH_STATUS(x)	(BIT(6) >> 2 * (x))
+
+/* S2MU005_REG_FLED_CHx_CTRL0 */
+#define S2MU005_FLED_FLASH_IOUT		GENMASK(3, 0)
+
+/* S2MU005_REG_FLED_CHx_CTRL1 */
+#define S2MU005_FLED_TORCH_IOUT		GENMASK(3, 0)
+
+/* S2MU005_REG_FLED_CHx_CTRL2 */
+#define S2MU005_FLED_TORCH_TIMEOUT	GENMASK(3, 0)
+
+/* S2MU005_REG_FLED_CHx_CTRL3 */
+#define S2MU005_FLED_FLASH_TIMEOUT	GENMASK(3, 0)
+
+/* S2MU005_REG_FLED_CTRL1 */
+#define S2MU005_FLED_CH_EN		BIT(7)
+
+/*
+ * S2MU005_REG_FLED_CTRL4 - Rev. EVT0
+ * S2MU005_REG_FLED_CTRL6 - Rev. EVT1 and later
+ */
+#define S2MU005_FLED_FLASH_EN(x)	(GENMASK(7, 6) >> 4 * (x))
+#define S2MU005_FLED_TORCH_EN(x)	(GENMASK(5, 4) >> 4 * (x))
+
+/* S2MU005_REG_RGB_EN */
+#define S2MU005_RGB_RESET		BIT(6)
+#define S2MU005_RGB_SLOPE		GENMASK(5, 0)
+
+#define S2MU005_RGB_SLOPE_CONST		(BIT(4) | BIT(2) | BIT(0))
+#define S2MU005_RGB_SLOPE_SMOOTH	(BIT(5) | BIT(3) | BIT(1))
+
+/* S2MU005_REG_RGB_CHx_RAMP */
+#define S2MU005_RGB_CH_RAMP_UP		GENMASK(7, 4)
+#define S2MU005_RGB_CH_RAMP_DN		GENMASK(3, 0)
+
+/* S2MU005_REG_RGB_CHx_STAY */
+#define S2MU005_RGB_CH_STAY_HI		GENMASK(7, 4)
+#define S2MU005_RGB_CH_STAY_LO		GENMASK(3, 0)
+
+/* S2MU005_REG_MUIC_DEV1 */
+#define S2MU005_MUIC_OTG		BIT(7)
+#define S2MU005_MUIC_DCP		BIT(6)
+#define S2MU005_MUIC_CDP		BIT(5)
+#define S2MU005_MUIC_T1_T2_CHG		BIT(4)
+#define S2MU005_MUIC_UART		BIT(3)
+#define S2MU005_MUIC_SDP		BIT(2)
+#define S2MU005_MUIC_LANHUB		BIT(1)
+#define S2MU005_MUIC_AUDIO		BIT(0)
+
+/* S2MU005_REG_MUIC_DEV2 */
+#define S2MU005_MUIC_SDP_1P8S		BIT(7)
+#define S2MU005_MUIC_AV			BIT(6)
+#define S2MU005_MUIC_TTY		BIT(5)
+#define S2MU005_MUIC_PPD		BIT(4)
+#define S2MU005_MUIC_JIG_UART_OFF	BIT(3)
+#define S2MU005_MUIC_JIG_UART_ON	BIT(2)
+#define S2MU005_MUIC_JIG_USB_OFF	BIT(1)
+#define S2MU005_MUIC_JIG_USB_ON		BIT(0)
+
+/* S2MU005_REG_MUIC_DEV3 */
+#define S2MU005_MUIC_U200_CHG		BIT(7)
+#define S2MU005_MUIC_VBUS_AV		BIT(4)
+#define S2MU005_MUIC_VBUS_R255		BIT(1)
+#define S2MU005_MUIC_MHL		BIT(0)
+
+/* S2MU005_REG_MUIC_DEVAPPLE */
+#define S2MU005_MUIC_APPLE_CHG_0P5A	BIT(7)
+#define S2MU005_MUIC_APPLE_CHG_1P0A	BIT(6)
+#define S2MU005_MUIC_APPLE_CHG_2P0A	BIT(5)
+#define S2MU005_MUIC_APPLE_CHG_2P4A	BIT(4)
+#define S2MU005_MUIC_SDP_DCD_OUT	BIT(3)
+#define S2MU005_MUIC_RID_WAKEUP		BIT(2)
+#define S2MU005_MUIC_VBUS_WAKEUP	BIT(1)
+#define S2MU005_MUIC_BCV1P2_OR_OPEN	BIT(0)
+
+/* S2MU005_REG_ID */
+#define S2MU005_ID_MASK			GENMASK(3, 0)
+
+/* S2MU005_REG_MUIC_SWCTRL */
+#define S2MU005_MUIC_DM_DP		GENMASK(7, 2)
+#define S2MU005_MUIC_JIG		BIT(0)
+
+#define S2MU005_MUIC_DM_DP_UART		0x12
+#define S2MU005_MUIC_DM_DP_USB		0x09
+
+/* S2MU005_REG_MUIC_CTRL1 */
+#define S2MU005_MUIC_OPEN		BIT(4)
+#define S2MU005_MUIC_RAW_DATA		BIT(3)
+#define S2MU005_MUIC_MAN_SW		BIT(2)
+#define S2MU005_MUIC_WAIT		BIT(1)
+#define S2MU005_MUIC_IRQ		BIT(0)
+
+/* S2MU005_REG_MUIC_CTRL3 */
+#define S2MU005_MUIC_ONESHOT_ADC	BIT(2)
+
+/* S2MU005_REG_MUIC_LDOADC_L and S2MU005_REG_MUIC_LDOADC_H */
+#define S2MU005_MUIC_VSET		GENMASK(4, 0)
+
+#define S2MU005_MUIC_VSET_3P0V		0x1f
+#define S2MU005_MUIC_VSET_2P6V		0x0e
+#define S2MU005_MUIC_VSET_2P4V		0x0c
+#define S2MU005_MUIC_VSET_2P2V		0x0a
+#define S2MU005_MUIC_VSET_2P0V		0x08
+#define S2MU005_MUIC_VSET_1P5V		0x03
+#define S2MU005_MUIC_VSET_1P4V		0x02
+#define S2MU005_MUIC_VSET_1P2V		0x00
+
+#endif /* __LINUX_MFD_S2MU005_H */

-- 
2.53.0


^ permalink raw reply related

* [PATCH v4 07/13] mfd: sec: set DMA coherent mask
From: Kaustabh Chakraborty @ 2026-04-14  6:32 UTC (permalink / raw)
  To: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, MyungJoo Ham, Chanwoo Choi, Sebastian Reichel,
	Krzysztof Kozlowski, André Draszik, Alexandre Belloni,
	Jonathan Corbet, Shuah Khan, Nam Tran,
	Łukasz Lebiedziński
  Cc: linux-leds, devicetree, linux-kernel, linux-pm, linux-samsung-soc,
	linux-rtc, linux-doc, Kaustabh Chakraborty
In-Reply-To: <20260414-s2mu005-pmic-v4-0-7fe7480577e6@disroot.org>

Kernel logs are filled with "DMA mask not set" messages for every
sub-device. The device does not use DMA for communication, so these
messages are useless. Disable the coherent DMA mask for the PMIC device,
which is also propagated to sub-devices.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
 Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml | 3 +++
 drivers/mfd/sec-common.c                                   | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml b/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml
index d3d305b9aa765..849740868d728 100644
--- a/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml
+++ b/Documentation/devicetree/bindings/mfd/samsung,s2mps11.yaml
@@ -356,6 +356,9 @@ examples:
                 };
 
                 port {
+                    #address-cells = <1>;
+                    #size-cells = <0>;
+
                     muic_to_charger: endpoint@0 {
                         reg = <0>;
                         remote-endpoint = <&charger_to_muic>;
diff --git a/drivers/mfd/sec-common.c b/drivers/mfd/sec-common.c
index b3268516bf75e..883e6d0aa3f06 100644
--- a/drivers/mfd/sec-common.c
+++ b/drivers/mfd/sec-common.c
@@ -215,6 +215,9 @@ int sec_pmic_probe(struct device *dev, int device_type, unsigned int irq,
 	if (IS_ERR(irq_data))
 		return PTR_ERR(irq_data);
 
+	dev->coherent_dma_mask = 0;
+	dev->dma_mask = &dev->coherent_dma_mask;
+
 	pm_runtime_set_active(sec_pmic->dev);
 
 	switch (sec_pmic->device_type) {

-- 
2.53.0


^ permalink raw reply related

* [PATCH v4 08/13] mfd: sec: resolve PMIC revision in S2MU005
From: Kaustabh Chakraborty @ 2026-04-14  6:33 UTC (permalink / raw)
  To: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, MyungJoo Ham, Chanwoo Choi, Sebastian Reichel,
	Krzysztof Kozlowski, André Draszik, Alexandre Belloni,
	Jonathan Corbet, Shuah Khan, Nam Tran,
	Łukasz Lebiedziński
  Cc: linux-leds, devicetree, linux-kernel, linux-pm, linux-samsung-soc,
	linux-rtc, linux-doc, Kaustabh Chakraborty
In-Reply-To: <20260414-s2mu005-pmic-v4-0-7fe7480577e6@disroot.org>

In devices other than S2MPG1X, the revision can be retrieved from the
first register of the PMIC regmap. In S2MU005 however, the location is
in offset 0x73. Introduce a switch-case block to allow selecting the
REG_ID register.

S2MU005 also has a field mask for the revision. Apply it using
FIELD_GET() and get the extracted value.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
 drivers/mfd/sec-common.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/mfd/sec-common.c b/drivers/mfd/sec-common.c
index 883e6d0aa3f06..43215605191e4 100644
--- a/drivers/mfd/sec-common.c
+++ b/drivers/mfd/sec-common.c
@@ -16,6 +16,7 @@
 #include <linux/mfd/samsung/irq.h>
 #include <linux/mfd/samsung/s2mps11.h>
 #include <linux/mfd/samsung/s2mps13.h>
+#include <linux/mfd/samsung/s2mu005.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/pm.h>
@@ -119,20 +120,27 @@ static const struct mfd_cell s2mu005_devs[] = {
 
 static void sec_pmic_dump_rev(struct sec_pmic_dev *sec_pmic)
 {
-	unsigned int val;
+	unsigned int reg, mask, val;
 
-	/* For s2mpg1x, the revision is in a different regmap */
 	switch (sec_pmic->device_type) {
 	case S2MPG10:
 	case S2MPG11:
+		/* For s2mpg1x, the revision is in a different regmap */
 		return;
-	default:
+	case S2MU005:
+		reg = S2MU005_REG_ID;
+		mask = S2MU005_ID_MASK;
 		break;
+	default:
+		/* For other device types, REG_ID is always the first register. */
+		reg = S2MPS11_REG_ID;
+		mask = ~0;
 	}
 
-	/* For each device type, the REG_ID is always the first register */
-	if (!regmap_read(sec_pmic->regmap_pmic, S2MPS11_REG_ID, &val))
+	if (!regmap_read(sec_pmic->regmap_pmic, reg, &val)) {
+		val = FIELD_GET(S2MU005_ID_MASK, val);
 		dev_dbg(sec_pmic->dev, "Revision: 0x%x\n", val);
+	}
 }
 
 static void sec_pmic_configure(struct sec_pmic_dev *sec_pmic)

-- 
2.53.0


^ permalink raw reply related

* [PATCH v4 09/13] leds: flash: add support for Samsung S2M series PMIC flash LED device
From: Kaustabh Chakraborty @ 2026-04-14  6:33 UTC (permalink / raw)
  To: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, MyungJoo Ham, Chanwoo Choi, Sebastian Reichel,
	Krzysztof Kozlowski, André Draszik, Alexandre Belloni,
	Jonathan Corbet, Shuah Khan, Nam Tran,
	Łukasz Lebiedziński
  Cc: linux-leds, devicetree, linux-kernel, linux-pm, linux-samsung-soc,
	linux-rtc, linux-doc, Kaustabh Chakraborty
In-Reply-To: <20260414-s2mu005-pmic-v4-0-7fe7480577e6@disroot.org>

Add support for flash LEDs found in certain Samsung S2M series PMICs.
The device has two channels for LEDs, typically for the back and front
cameras in mobile devices. Both channels can be independently
controlled, and can be operated in torch or flash modes.

The driver includes initial support for the S2MU005 PMIC flash LEDs.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
 drivers/leds/flash/Kconfig          |  12 ++
 drivers/leds/flash/Makefile         |   1 +
 drivers/leds/flash/leds-s2m-flash.c | 357 ++++++++++++++++++++++++++++++++++++
 3 files changed, 370 insertions(+)

diff --git a/drivers/leds/flash/Kconfig b/drivers/leds/flash/Kconfig
index 5e08102a67841..be62e05277429 100644
--- a/drivers/leds/flash/Kconfig
+++ b/drivers/leds/flash/Kconfig
@@ -114,6 +114,18 @@ config LEDS_RT8515
 	  To compile this driver as a module, choose M here: the module
 	  will be called leds-rt8515.
 
+config LEDS_S2M_FLASH
+	tristate "Samsung S2M series PMICs flash/torch LED support"
+	depends on LEDS_CLASS
+	depends on MFD_SEC_CORE
+	depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS
+	select REGMAP_IRQ
+	help
+	  This option enables support for the flash/torch LEDs found in
+	  certain Samsung S2M series PMICs, such as the S2MU005. It has
+	  a LED channel dedicated for every physical LED. The LEDs can
+	  be controlled in flash and torch modes.
+
 config LEDS_SGM3140
 	tristate "LED support for the SGM3140"
 	depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS
diff --git a/drivers/leds/flash/Makefile b/drivers/leds/flash/Makefile
index 712fb737a428e..44e6c1b4beb37 100644
--- a/drivers/leds/flash/Makefile
+++ b/drivers/leds/flash/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_LEDS_MAX77693)	+= leds-max77693.o
 obj-$(CONFIG_LEDS_QCOM_FLASH)	+= leds-qcom-flash.o
 obj-$(CONFIG_LEDS_RT4505)	+= leds-rt4505.o
 obj-$(CONFIG_LEDS_RT8515)	+= leds-rt8515.o
+obj-$(CONFIG_LEDS_S2M_FLASH)	+= leds-s2m-flash.o
 obj-$(CONFIG_LEDS_SGM3140)	+= leds-sgm3140.o
 obj-$(CONFIG_LEDS_SY7802)	+= leds-sy7802.o
 obj-$(CONFIG_LEDS_TPS6131X)	+= leds-tps6131x.o
diff --git a/drivers/leds/flash/leds-s2m-flash.c b/drivers/leds/flash/leds-s2m-flash.c
new file mode 100644
index 0000000000000..1ec592417c344
--- /dev/null
+++ b/drivers/leds/flash/leds-s2m-flash.c
@@ -0,0 +1,357 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Flash and Torch LED Driver for Samsung S2M series PMICs.
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd
+ * Copyright (c) 2025 Kaustabh Chakraborty <kauschluss@disroot.org>
+ */
+
+#include <linux/container_of.h>
+#include <linux/led-class-flash.h>
+#include <linux/mfd/samsung/core.h>
+#include <linux/mfd/samsung/s2mu005.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <media/v4l2-flash-led-class.h>
+
+#define MAX_CHANNELS	2
+
+struct s2m_led {
+	struct regmap *regmap;
+	struct led_classdev_flash fled;
+	struct v4l2_flash *v4l2_flash;
+	/*
+	 * The mutex object prevents the concurrent access of flash control
+	 * registers by the LED and V4L2 subsystems.
+	 */
+	struct mutex lock;
+	unsigned int reg_enable;
+	u8 channel;
+	u8 flash_brightness;
+	u8 flash_timeout;
+};
+
+static struct s2m_led *to_s2m_led(struct led_classdev_flash *fled)
+{
+	return container_of(fled, struct s2m_led, fled);
+}
+
+static struct led_classdev_flash *to_s2m_fled(struct led_classdev *cdev)
+{
+	return container_of(cdev, struct led_classdev_flash, led_cdev);
+}
+
+static int s2m_fled_flash_brightness_set(struct led_classdev_flash *fled, u32 brightness)
+{
+	struct s2m_led *led = to_s2m_led(fled);
+	struct led_flash_setting *setting = &fled->brightness;
+
+	led->flash_brightness = (brightness - setting->min) / setting->step;
+
+	return 0;
+}
+
+static int s2m_fled_flash_timeout_set(struct led_classdev_flash *fled, u32 timeout)
+{
+	struct s2m_led *led = to_s2m_led(fled);
+	struct led_flash_setting *setting = &fled->timeout;
+
+	led->flash_timeout = (timeout - setting->min) / setting->step;
+
+	return 0;
+}
+
+#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
+static int s2m_fled_flash_external_strobe_set(struct v4l2_flash *v4l2_flash, bool enable)
+{
+	struct s2m_led *led = to_led(v4l2_flash->fled_cdev);
+
+	mutex_lock(&led->lock);
+
+	led->fled.ops->strobe_set(&led->fled, enable);
+
+	mutex_unlock(&led->lock);
+
+	return 0;
+}
+
+static const struct v4l2_flash_ops s2m_fled_v4l2_flash_ops = {
+	.external_strobe_set = s2m_fled_flash_external_strobe_set,
+};
+#else
+static const struct v4l2_flash_ops s2m_fled_v4l2_flash_ops;
+#endif
+
+static void s2m_fled_v4l2_flash_release(void *v4l2_flash)
+{
+	v4l2_flash_release(v4l2_flash);
+}
+
+static int s2mu005_fled_torch_brightness_set(struct led_classdev *cdev, enum led_brightness value)
+{
+	struct s2m_led *led = to_s2m_led(to_s2m_fled(cdev));
+	int ret;
+
+	mutex_lock(&led->lock);
+
+	if (!value) {
+		ret = regmap_clear_bits(led->regmap, led->reg_enable,
+					S2MU005_FLED_TORCH_EN(led->channel));
+		if (ret < 0)
+			dev_err(cdev->dev, "failed to disable torch LED\n");
+		goto unlock;
+	}
+
+	ret = regmap_update_bits(led->regmap, S2MU005_REG_FLED_CH_CTRL1(led->channel),
+				 S2MU005_FLED_TORCH_IOUT,
+				 FIELD_PREP(S2MU005_FLED_TORCH_IOUT, value - 1));
+	if (ret < 0) {
+		dev_err(cdev->dev, "failed to set torch current\n");
+		goto unlock;
+	}
+
+	ret = regmap_set_bits(led->regmap, led->reg_enable, S2MU005_FLED_TORCH_EN(led->channel));
+	if (ret < 0) {
+		dev_err(cdev->dev, "failed to enable torch LED\n");
+		goto unlock;
+	}
+
+unlock:
+	mutex_unlock(&led->lock);
+
+	return ret;
+}
+
+static int s2mu005_fled_flash_strobe_set(struct led_classdev_flash *fled, bool state)
+{
+	struct s2m_led *led = to_s2m_led(fled);
+	int ret;
+
+	mutex_lock(&led->lock);
+
+	ret = regmap_clear_bits(led->regmap, led->reg_enable, S2MU005_FLED_FLASH_EN(led->channel));
+	if (ret < 0) {
+		dev_err(fled->led_cdev.dev, "failed to disable flash LED\n");
+		goto unlock;
+	}
+
+	if (!state)
+		goto unlock;
+
+	ret = regmap_update_bits(led->regmap, S2MU005_REG_FLED_CH_CTRL0(led->channel),
+				 S2MU005_FLED_FLASH_IOUT,
+				 FIELD_PREP(S2MU005_FLED_FLASH_IOUT, led->flash_brightness));
+	if (ret < 0) {
+		dev_err(fled->led_cdev.dev, "failed to set flash brightness\n");
+		goto unlock;
+	}
+
+	ret = regmap_update_bits(led->regmap, S2MU005_REG_FLED_CH_CTRL3(led->channel),
+				 S2MU005_FLED_FLASH_TIMEOUT,
+				 FIELD_PREP(S2MU005_FLED_FLASH_TIMEOUT, led->flash_timeout));
+	if (ret < 0) {
+		dev_err(fled->led_cdev.dev, "failed to set flash timeout\n");
+		goto unlock;
+	}
+
+	ret = regmap_set_bits(led->regmap, led->reg_enable, S2MU005_FLED_FLASH_EN(led->channel));
+	if (ret < 0) {
+		dev_err(fled->led_cdev.dev, "failed to enable flash LED\n");
+		goto unlock;
+	}
+
+unlock:
+	mutex_unlock(&led->lock);
+
+	return 0;
+}
+
+static int s2mu005_fled_flash_strobe_get(struct led_classdev_flash *fled, bool *state)
+{
+	struct s2m_led *led = to_s2m_led(fled);
+	u32 val;
+	int ret;
+
+	mutex_lock(&led->lock);
+
+	ret = regmap_read(led->regmap, S2MU005_REG_FLED_STATUS, &val);
+	if (ret < 0) {
+		dev_err(fled->led_cdev.dev, "failed to fetch LED status");
+		goto unlock;
+	}
+
+	*state = !!(val & S2MU005_FLED_FLASH_STATUS(led->channel));
+
+unlock:
+	mutex_unlock(&led->lock);
+
+	return ret;
+}
+
+static const struct led_flash_ops s2mu005_fled_flash_ops = {
+	.flash_brightness_set = s2m_fled_flash_brightness_set,
+	.timeout_set = s2m_fled_flash_timeout_set,
+	.strobe_set = s2mu005_fled_flash_strobe_set,
+	.strobe_get = s2mu005_fled_flash_strobe_get,
+};
+
+static int s2mu005_fled_init(struct s2m_led *led, struct device *dev, struct regmap *regmap,
+			     unsigned int nr_channels)
+{
+	unsigned int val;
+	int i, ret;
+
+	/* Enable the LED channels. */
+	ret = regmap_set_bits(regmap, S2MU005_REG_FLED_CTRL1, S2MU005_FLED_CH_EN);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "failed to enable LED channels\n");
+
+	ret = regmap_read(regmap, S2MU005_REG_ID, &val);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "failed to read revision\n");
+
+	for (i = 0; i < nr_channels; i++) {
+		/*
+		 * Read the revision register. Revision EVT0 has the register
+		 * at CTRL4, while EVT1 and higher have it at CTRL6.
+		 */
+		if (FIELD_GET(S2MU005_ID_MASK, val) == 0)
+			led[i].reg_enable = S2MU005_REG_FLED_CTRL4;
+		else
+			led[i].reg_enable = S2MU005_REG_FLED_CTRL6;
+	}
+
+	return 0;
+}
+
+static int s2mu005_fled_init_channel(struct s2m_led *led, struct device *dev,
+				     struct fwnode_handle *fwnp)
+{
+	struct led_classdev *cdev = &led->fled.led_cdev;
+	struct led_init_data init_data = {};
+	struct v4l2_flash_config v4l2_cfg = {};
+	int ret;
+	cdev->max_brightness = 16;
+	cdev->brightness_set_blocking = s2mu005_fled_torch_brightness_set,
+	cdev->flags |= LED_DEV_CAP_FLASH;
+
+	led->fled.timeout.min = 62000;
+	led->fled.timeout.step = 62000;
+	led->fled.timeout.max = 992000;
+	led->fled.timeout.val = 992000;
+
+	led->fled.brightness.min = 25000;
+	led->fled.brightness.step = 25000;
+	led->fled.brightness.max = 375000; /* 400000 causes flickering */
+	led->fled.brightness.val = 375000;
+
+	s2m_fled_flash_timeout_set(&led->fled, led->fled.timeout.val);
+	s2m_fled_flash_brightness_set(&led->fled, led->fled.brightness.val);
+
+	led->fled.ops = &s2mu005_fled_flash_ops;
+
+	init_data.fwnode = fwnp;
+	ret = devm_led_classdev_flash_register_ext(dev, &led->fled, &init_data);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "failed to create LED flash device\n");
+
+	v4l2_cfg.intensity.min = led->fled.timeout.min;
+	v4l2_cfg.intensity.step = led->fled.timeout.step;
+	v4l2_cfg.intensity.max = led->fled.timeout.max;
+	v4l2_cfg.intensity.val = led->fled.timeout.val;
+
+	v4l2_cfg.has_external_strobe = true;
+
+	led->v4l2_flash = v4l2_flash_init(dev, fwnp, &led->fled, &s2m_fled_v4l2_flash_ops,
+					  &v4l2_cfg);
+	if (IS_ERR(led->v4l2_flash)) {
+		v4l2_flash_release(led->v4l2_flash);
+		return dev_err_probe(dev, PTR_ERR(led->v4l2_flash),
+				     "failed to create V4L2 flash device\n");
+	}
+
+	ret = devm_add_action_or_reset(dev, (void *)s2m_fled_v4l2_flash_release, led->v4l2_flash);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "failed to add cleanup action\n");
+
+	return 0;
+}
+
+static int s2m_fled_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct sec_pmic_dev *ddata = dev_get_drvdata(dev->parent);
+	struct s2m_led *led;
+	int ret;
+
+	led = devm_kzalloc(dev, sizeof(*led) * MAX_CHANNELS, GFP_KERNEL);
+	if (!led)
+		return -ENOMEM;
+
+	switch (platform_get_device_id(pdev)->driver_data) {
+	case S2MU005:
+		ret = s2mu005_fled_init(led, dev, ddata->regmap_pmic, MAX_CHANNELS);
+		if (ret)
+			return ret;
+		break;
+	default:
+		return dev_err_probe(dev, -ENODEV, "device type %d is not supported by driver\n",
+				     ddata->device_type);
+	}
+
+	device_for_each_child_node_scoped(dev, child) {
+		u32 reg;
+
+		if (fwnode_property_read_u32(child, "reg", &reg))
+			continue;
+
+		if (led[reg].regmap) {
+			dev_warn(dev, "duplicate node for channel %d\n", reg);
+			continue;
+		}
+
+		led[reg].regmap = ddata->regmap_pmic;
+		led[reg].channel = (u8)reg;
+
+		ret = devm_mutex_init(dev, &led[reg].lock);
+		if (ret)
+			return dev_err_probe(dev, ret, "failed to create mutex\n");
+
+		switch (platform_get_device_id(pdev)->driver_data) {
+		case S2MU005:
+			ret = s2mu005_fled_init_channel(led + reg, dev, child);
+			if (ret < 0)
+				return ret;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static const struct platform_device_id s2m_fled_id_table[] = {
+	{ "s2mu005-flash", S2MU005 },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(platform, s2m_fled_id_table);
+
+static const struct of_device_id s2m_fled_of_match_table[] = {
+	{ .compatible = "samsung,s2mu005-flash", .data = (void *)S2MU005 },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, s2m_fled_of_match_table);
+
+static struct platform_driver s2m_fled_driver = {
+	.driver = {
+		.name = "s2m-flash",
+	},
+	.probe = s2m_fled_probe,
+	.id_table = s2m_fled_id_table,
+};
+module_platform_driver(s2m_fled_driver);
+
+MODULE_DESCRIPTION("Flash/Torch LED Driver For Samsung S2M Series PMICs");
+MODULE_AUTHOR("Kaustabh Chakraborty <kauschluss@disroot.org>");
+MODULE_LICENSE("GPL");

-- 
2.53.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