Linux GPIO subsystem development
 help / color / mirror / Atom feed
* Re: [PATCH] gpio: mvebu: add wake-up interrupt support
From: Bartosz Golaszewski @ 2026-07-01 10:34 UTC (permalink / raw)
  To: linux-gpio, Rosen Penev
  Cc: Bartosz Golaszewski, Linus Walleij, Bartosz Golaszewski,
	linux-kernel
In-Reply-To: <20260628230202.1209991-1-rosenp@gmail.com>


On Sun, 28 Jun 2026 16:02:02 -0700, Rosen Penev wrote:
> Implement wake IRQ support for the mvebu GPIO controller:
> 
> - Replace unused irqbase field with bank_irq[4] to store per-bank
>   IRQ numbers for use in the wake-up callback.
> - Add mvebu_gpio_set_wake_irq() that forwards enable_irq_wake /
>   disable_irq_wake to the correct parent IRQ based on hwirq.
> - Set IRQCHIP_SET_TYPE_MASKED and IRQCHIP_MASK_ON_SUSPEND flags
>   on both level and edge chip types.
> - Set IRQ_GC_INIT_NESTED_LOCK for the nested irq domain.
> - Add missing <linux/interrupt.h> include.
> 
> [...]

Applied, thanks!

[1/1] gpio: mvebu: add wake-up interrupt support
      https://git.kernel.org/brgl/c/b67e64d4eb9765d23010f423e29a627a25f5ac2e

Best regards,
-- 
Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>

^ permalink raw reply

* RE: [PATCH v4 1/4] dt-bindings: gpio: realtek: Add realtek,rtd1625-gpio
From: Yu-Chun Lin [林祐君] @ 2026-07-01 10:31 UTC (permalink / raw)
  To: Linus Walleij
  Cc: brgl@kernel.org, robh@kernel.org, krzk+dt@kernel.org,
	conor+dt@kernel.org, afaerber@suse.com, mwalle@kernel.org,
	andriy.shevchenko@intel.com, TY_Chang[張子逸],
	linux-gpio@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-realtek-soc@lists.infradead.org,
	CY_Huang[黃鉦晏],
	Stanley Chang[昌育德],
	James Tai [戴志峰], Krzysztof Kozlowski
In-Reply-To: <CAD++jL=6pqEA0-vs_J57MnhmLmLwrTj7-syOL8E7PLYW-vUBvg@mail.gmail.com>

Hi Linus,

> Hi Yu-Chun,
> 
> thanks for your patch!
> 
> On Mon, Jun 22, 2026 at 10:33 AM Yu-Chun Lin <eleanor.lin@realtek.com>
> wrote:
> 
> > From: Tzuyi Chang <tychang@realtek.com>
> >
> > Add the device tree bindings for the Realtek DHC (Digital Home Center)
> > RTD1625 GPIO controllers.
> >
> > The RTD1625 GPIO controller features a per-pin register architecture
> > that differs significantly from previous generations. It utilizes
> > separate register blocks for GPIO configuration and interrupt control.
> >
> > Reviewed-by: Krzysztof Kozlowski
> > <krzysztof.kozlowski@oss.qualcomm.com>
> > Signed-off-by: Tzuyi Chang <tychang@realtek.com>
> > Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> (...)
> 
> > +  interrupt-controller: true
> > +
> > +  "#interrupt-cells":
> > +    const: 2
> > +
> > +  gpio-ranges: true
> > +
> > +  gpio-controller: true
> > +
> > +  "#gpio-cells":
> > +    const: 2
> 
> After looking at the driver I must challenge this binding.
> 
> Your driver is full of (offset % 32) and even (offset % 32) *4 to just work around
> the fact that the hardware inherently has 32-pin banks.
> 
> Instead of using twocell GPIO and irqs, just use threecell, interrupt-cells and
> gpio-cells 3.
> 
> First cell is bank, second cell is offset inside each bank.
> 
> For Linux specifically there are helpers for dealing with this in gpiolib, and
> further you will be able to use the GPIO_GENERIC library, while this is beside
> the point for the binding itself.
> 
> Yours,
> Linus Walleij

To clarify the hardware design: this SoC does not use a banked GPIO
architecture.

Each GPIO pin has its own dedicated 32-bit control register that handles
both GPIO configuration and interrupt settings (e.g., edge/level enable).
The only exception is the interrupt status register, which is grouped into
32-bit words.

Since physical GPIO banks do not exist, using a 3-cell <bank offset flags>
format would misrepresent the hardware. Therefore,
keeping #gpio-cells = <2> and #interrupt-cells = <2> is the most accurate
reflection of the actual silicon.

Best Regards,
Yu-Chun

^ permalink raw reply

* Re: [PATCH v3 2/7] gpio: regmap: add gpio_regmap_get_gpiochip() accessor
From: Andy Shevchenko @ 2026-07-01 10:55 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Michael Walle, Linus Walleij, Bartosz Golaszewski,
	robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
	afaerber@suse.com, wbg@kernel.org,
	mathieu.dubois-briand@bootlin.com, lars@metafoo.de,
	Michael.Hennerich@analog.com, jic23@kernel.org,
	nuno.sa@analog.com, andy@kernel.org, dlechner@baylibre.com,
	TY_Chang[張子逸], linux-gpio@vger.kernel.org,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-realtek-soc@lists.infradead.org, linux-iio@vger.kernel.org,
	CY_Huang[黃鉦晏],
	Stanley Chang[昌育德],
	James Tai [戴志峰],
	Yu-Chun Lin [林祐君]
In-Reply-To: <CAHp75VeTp4eYQ4QBoeH2VyVhUivxNn1CaC9jskmeg-1zTAOYLQ@mail.gmail.com>

On Wed, Jul 01, 2026 at 01:01:10PM +0300, Andy Shevchenko wrote:
> On Wed, Jul 1, 2026 at 11:44 AM Michael Walle <mwalle@kernel.org> wrote:
> > On Fri Jun 19, 2026 at 11:08 PM CEST, Linus Walleij wrote:
> > > On Mon, Jun 8, 2026 at 4:41 PM Michael Walle <mwalle@kernel.org> wrote:
> > >
> > >> >>> Without an accessor like gpio_regmap_get_gpiochip(), we cannot retrieve the
> > >> >>> gpio_chip instantiated inside gpio-regmap.c to fulfill these requirements in our
> > >> >>> map() function.
> > >>
> > >> Why is gpiochip_irq_reqres() called in the first place? Isn't that
> > >> only called if the irq handling is set up via gc->irq.chip and not
> > >> via gpiochip_irqchip_add_domain() like in gpio-regmap?
> > >
> > > Not really, the gpiochip_irq_reqres() is called to mark that a
> > > GPIO line is used for IRQ, so the gpiolib cannot turn this
> > > GPIO into an output line, gpiod_direction_out() will fail
> > > on lines used for IRQ. So it's a failsafe.
> > >
> > > You can live without it of course, but then you don't get
> > > this failsafe.
> >
> > Thanks for the explanation! So did I make a mistake years ago by
> > adding the gpiochip_irqchip_add_domain(), see commit 6a45b0e2589f
> > ("gpiolib: Introduce gpiochip_irqchip_add_domain()")
> >
> > As Yu-Chun found, gpiochip_irq_reqres() expect the irq chip data
> > to be a gpio_chip, which isn't the case (in general) for an
> > externally allocated domain, is it?
> 
> So the whole issue comes from the fact that the IRQ chip is not marked
> as immutable. For immutable IRQ chips (which all GPIO provides should
> have) there is no such issue to begin with, id est there is no
> gpiochip_irq_reqres() callback assigned (and respective _relres).

Ah, for immutable chips we put either custom ones or
GPIOCHIP_IRQ_RESOURCE_HELPERS which actually refers to those callbacks.

So, if the domain is external, it should also provide irq_request_resources
and release callbacks. In the custom case we can wrap gpiochip_reqres_irq()
and gpiochip_relres_irq() respectively.

But we need to have a struct gpio_chip pointer for them. And note, the
IRQ chip data can be anything in that case, so it's not a requirement.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* Re: [PATCH v4 1/4] dt-bindings: gpio: realtek: Add realtek,rtd1625-gpio
From: Linus Walleij @ 2026-07-01 11:04 UTC (permalink / raw)
  To: Yu-Chun Lin [林祐君]
  Cc: brgl@kernel.org, robh@kernel.org, krzk+dt@kernel.org,
	conor+dt@kernel.org, afaerber@suse.com, mwalle@kernel.org,
	andriy.shevchenko@intel.com, TY_Chang[張子逸],
	linux-gpio@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-realtek-soc@lists.infradead.org,
	CY_Huang[黃鉦晏],
	Stanley Chang[昌育德],
	James Tai [戴志峰], Krzysztof Kozlowski
In-Reply-To: <56be68cba7d9461d9a1ec66ed1a1417a@realtek.com>

On Wed, Jul 1, 2026 at 12:41 PM Yu-Chun Lin [林祐君]
<eleanor.lin@realtek.com> wrote:

> To clarify the hardware design: this SoC does not use a banked GPIO
> architecture.
>
> Each GPIO pin has its own dedicated 32-bit control register that handles
> both GPIO configuration and interrupt settings (e.g., edge/level enable).
> The only exception is the interrupt status register, which is grouped into
> 32-bit words.

Aha, I get it!

> Since physical GPIO banks do not exist, using a 3-cell <bank offset flags>
> format would misrepresent the hardware. Therefore,
> keeping #gpio-cells = <2> and #interrupt-cells = <2> is the most accurate
> reflection of the actual silicon.

Hmmmm I would argue that the way the interrupts are routed into a
single 32-bit register for 32 GPIOs would be an argument for using
#interrupt-cells = <3> but it would be confusing to use a mixture of
2 and 3 cells for GPIOs and interrupts, so I guess 2 is OK for both.

Yours,
Linus Walleij

^ permalink raw reply

* Re: [PATCH v2 1/4] soc: qcom: rpmh: Allow non-child devices to issue write commands
From: Mark Brown @ 2026-07-01 11:33 UTC (permalink / raw)
  To: Fenglin Wu
  Cc: Konrad Dybcio, Dmitry Baryshkov, linux-arm-msm, Bjorn Andersson,
	Konrad Dybcio, Linus Walleij, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Bartosz Golaszewski, David Collins,
	Subbaraman Narayanamurthy, Kamal Wadhwa, Maulik Shah, kernel,
	linux-kernel, linux-gpio, devicetree
In-Reply-To: <e807f4c1-b489-428d-a29e-186fc64eb542@oss.qualcomm.com>

[-- Attachment #1: Type: text/plain, Size: 2435 bytes --]

On Wed, Jul 01, 2026 at 10:43:01AM +0800, Fenglin Wu wrote:

> Qcom PMH0101 includes bi-directional level-shifter (BIDIR_LVL_SHIFTER)
> modules that act as open-drain voltage translators, mainly to support
> 1.2 to 1.8V voltage translation on the I2C bus between the SoC with 1.2V
> IOs and other I2C clients with 1.8V IOs. Each module shares two physical
> pins with two GPIO modules, and control of the BIDIR_LVL_SHIFTER module
> is centralized on the AOP side with 'XOB' resources so it can be shared
> between different subsystems.

> When a BIDIR_LVL_SHIFTER is enabled, it needs to send RPMh commands to
> enable it and SPMI commands to disable the related two GPIO modules, to
> make sure their circuitry does not interfere with it. For now, the
> suggestion is to write a new driver for BIDIR_LVL_SHIFTER and place it
> as a child of the rpmh_rsc device, and refer to pinstate nodes to
> disable these two GPIO modules. However, we are now facing a difficulty
> in deciding which subsystem the new driver should belong to. We expected
> that the new driver should provide following capabilities:

To the extent any of this is comprehensible (I don't know what things
like AOP, XOB and so on are) nothing about this is screaming regulator.
It sounds like you just want to turn on and off a device to make the bus
you're talking through work?

> 1. Enable and disable the level-shifter at runtime. Consumers, likely
> I2C client devices, will enable it when active and disable it when not,
> mainly to save power.
> 2. Allow sharing the level-shifter between multiple consumers, even
> across different subsystems (currently managed by AOP).

> Following are the approaches that we are considered, and it seems only a
> regulator device could satisfy the requirement the best but we want to
> check with you if you are fine to put it in the regulator framework.

Why would this be a regulator?  It's not providing power to anything
which is a fairly key element of being a regulator, it fits about as
well with clocks (which also provide reference counting which is AFAICT
what you're looking for here).  You'll have a hard time writing DTs for
this that actually refelect the hardware I think.  Possibly it's a power
domain (or a resource controlled by a power domain, I know they manage
clocks and regulators)? 

Possibly work out a DT binding for this and then work back from there.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH v3 2/7] gpio: regmap: add gpio_regmap_get_gpiochip() accessor
From: Andy Shevchenko @ 2026-07-01 11:38 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Michael Walle, Linus Walleij, Bartosz Golaszewski,
	robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
	afaerber@suse.com, wbg@kernel.org,
	mathieu.dubois-briand@bootlin.com, lars@metafoo.de,
	Michael.Hennerich@analog.com, jic23@kernel.org,
	nuno.sa@analog.com, andy@kernel.org, dlechner@baylibre.com,
	TY_Chang[張子逸], linux-gpio@vger.kernel.org,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-realtek-soc@lists.infradead.org, linux-iio@vger.kernel.org,
	CY_Huang[黃鉦晏],
	Stanley Chang[昌育德],
	James Tai [戴志峰],
	Yu-Chun Lin [林祐君]
In-Reply-To: <akTyDzdrt949VnWK@ashevche-desk.local>

On Wed, Jul 01, 2026 at 01:55:11PM +0300, Andy Shevchenko wrote:
> On Wed, Jul 01, 2026 at 01:01:10PM +0300, Andy Shevchenko wrote:
> > On Wed, Jul 1, 2026 at 11:44 AM Michael Walle <mwalle@kernel.org> wrote:
> > > On Fri Jun 19, 2026 at 11:08 PM CEST, Linus Walleij wrote:
> > > > On Mon, Jun 8, 2026 at 4:41 PM Michael Walle <mwalle@kernel.org> wrote:
> > > >
> > > >> >>> Without an accessor like gpio_regmap_get_gpiochip(), we cannot retrieve the
> > > >> >>> gpio_chip instantiated inside gpio-regmap.c to fulfill these requirements in our
> > > >> >>> map() function.
> > > >>
> > > >> Why is gpiochip_irq_reqres() called in the first place? Isn't that
> > > >> only called if the irq handling is set up via gc->irq.chip and not
> > > >> via gpiochip_irqchip_add_domain() like in gpio-regmap?
> > > >
> > > > Not really, the gpiochip_irq_reqres() is called to mark that a
> > > > GPIO line is used for IRQ, so the gpiolib cannot turn this
> > > > GPIO into an output line, gpiod_direction_out() will fail
> > > > on lines used for IRQ. So it's a failsafe.
> > > >
> > > > You can live without it of course, but then you don't get
> > > > this failsafe.
> > >
> > > Thanks for the explanation! So did I make a mistake years ago by
> > > adding the gpiochip_irqchip_add_domain(), see commit 6a45b0e2589f
> > > ("gpiolib: Introduce gpiochip_irqchip_add_domain()")
> > >
> > > As Yu-Chun found, gpiochip_irq_reqres() expect the irq chip data
> > > to be a gpio_chip, which isn't the case (in general) for an
> > > externally allocated domain, is it?
> > 
> > So the whole issue comes from the fact that the IRQ chip is not marked
> > as immutable. For immutable IRQ chips (which all GPIO provides should
> > have) there is no such issue to begin with, id est there is no
> > gpiochip_irq_reqres() callback assigned (and respective _relres).
> 
> Ah, for immutable chips we put either custom ones or
> GPIOCHIP_IRQ_RESOURCE_HELPERS which actually refers to those callbacks.
> 
> So, if the domain is external, it should also provide irq_request_resources
> and release callbacks. In the custom case we can wrap gpiochip_reqres_irq()
> and gpiochip_relres_irq() respectively.
> 
> But we need to have a struct gpio_chip pointer for them. And note, the
> IRQ chip data can be anything in that case, so it's not a requirement.

And looking back for implementation in v3 the whole mistake was to use
GPIOCHIP_IRQ_RESOURCE_HELPERS. It just wanted custom callbacks with
the IRQ chip data assigned to whatever from which we may then deduce
struct gpio_chip. It does *not* require to be struct gpio_chip.
The local driver data structure should keep pointer to struct gpio_regmap.
That one can be used in the respective .irq_request_resources() and
.irq_release_resources(). The default ones for gpio-regmap may also
be provided via a macro, say GPIO_REGMAP_IRQ_RESOURCE_HELPERS.

Hence I don't see the need of having gpio_regmap_get_gpiochip() helper
and driver can be implemented using gpio-regmap and external IRQ domain.

What did I miss?

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* Re: [PATCH v3 2/7] gpio: regmap: add gpio_regmap_get_gpiochip() accessor
From: Michael Walle @ 2026-07-01 11:38 UTC (permalink / raw)
  To: Andy Shevchenko, Andy Shevchenko
  Cc: Linus Walleij, Bartosz Golaszewski, robh@kernel.org,
	krzk+dt@kernel.org, conor+dt@kernel.org, afaerber@suse.com,
	wbg@kernel.org, mathieu.dubois-briand@bootlin.com,
	lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org,
	nuno.sa@analog.com, andy@kernel.org, dlechner@baylibre.com,
	TY_Chang[張子逸], linux-gpio@vger.kernel.org,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-realtek-soc@lists.infradead.org, linux-iio@vger.kernel.org,
	CY_Huang[黃鉦晏],
	Stanley Chang[昌育德],
	James Tai [戴志峰],
	Yu-Chun Lin [林祐君]
In-Reply-To: <akTyDzdrt949VnWK@ashevche-desk.local>

[-- Attachment #1: Type: text/plain, Size: 2792 bytes --]

On Wed Jul 1, 2026 at 12:55 PM CEST, Andy Shevchenko wrote:
> On Wed, Jul 01, 2026 at 01:01:10PM +0300, Andy Shevchenko wrote:
>> On Wed, Jul 1, 2026 at 11:44 AM Michael Walle <mwalle@kernel.org> wrote:
>> > On Fri Jun 19, 2026 at 11:08 PM CEST, Linus Walleij wrote:
>> > > On Mon, Jun 8, 2026 at 4:41 PM Michael Walle <mwalle@kernel.org> wrote:
>> > >
>> > >> >>> Without an accessor like gpio_regmap_get_gpiochip(), we cannot retrieve the
>> > >> >>> gpio_chip instantiated inside gpio-regmap.c to fulfill these requirements in our
>> > >> >>> map() function.
>> > >>
>> > >> Why is gpiochip_irq_reqres() called in the first place? Isn't that
>> > >> only called if the irq handling is set up via gc->irq.chip and not
>> > >> via gpiochip_irqchip_add_domain() like in gpio-regmap?
>> > >
>> > > Not really, the gpiochip_irq_reqres() is called to mark that a
>> > > GPIO line is used for IRQ, so the gpiolib cannot turn this
>> > > GPIO into an output line, gpiod_direction_out() will fail
>> > > on lines used for IRQ. So it's a failsafe.
>> > >
>> > > You can live without it of course, but then you don't get
>> > > this failsafe.
>> >
>> > Thanks for the explanation! So did I make a mistake years ago by
>> > adding the gpiochip_irqchip_add_domain(), see commit 6a45b0e2589f
>> > ("gpiolib: Introduce gpiochip_irqchip_add_domain()")
>> >
>> > As Yu-Chun found, gpiochip_irq_reqres() expect the irq chip data
>> > to be a gpio_chip, which isn't the case (in general) for an
>> > externally allocated domain, is it?
>> 
>> So the whole issue comes from the fact that the IRQ chip is not marked
>> as immutable. For immutable IRQ chips (which all GPIO provides should
>> have) there is no such issue to begin with, id est there is no
>> gpiochip_irq_reqres() callback assigned (and respective _relres).
>
> Ah, for immutable chips we put either custom ones or
> GPIOCHIP_IRQ_RESOURCE_HELPERS which actually refers to those callbacks.
>
> So, if the domain is external, it should also provide irq_request_resources
> and release callbacks. In the custom case we can wrap gpiochip_reqres_irq()
> and gpiochip_relres_irq() respectively.

Exactly. And its seems that this should have been possible with this
series, too.

Apart from that, most drivers use regmap-irq with gpio-regmap. For
this we'd probably have to add something to regmap-irq because that
module owns the irq_chip.

> But we need to have a struct gpio_chip pointer for them. And note, the
> IRQ chip data can be anything in that case, so it's not a requirement.

That's what I've meant. Conceptionally, it should be part of
gpiochip_irqchip_add_domain()/gpiolib, so a user doesn't have to
have that knowledge. But I don't see how this could be achieved.

-michael

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 297 bytes --]

^ permalink raw reply

* Re: [PATCH v3 2/7] gpio: regmap: add gpio_regmap_get_gpiochip() accessor
From: Michael Walle @ 2026-07-01 11:42 UTC (permalink / raw)
  To: Andy Shevchenko, Andy Shevchenko
  Cc: Linus Walleij, Bartosz Golaszewski, robh@kernel.org,
	krzk+dt@kernel.org, conor+dt@kernel.org, afaerber@suse.com,
	wbg@kernel.org, mathieu.dubois-briand@bootlin.com,
	lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org,
	nuno.sa@analog.com, andy@kernel.org, dlechner@baylibre.com,
	TY_Chang[張子逸], linux-gpio@vger.kernel.org,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-realtek-soc@lists.infradead.org, linux-iio@vger.kernel.org,
	CY_Huang[黃鉦晏],
	Stanley Chang[昌育德],
	James Tai [戴志峰],
	Yu-Chun Lin [林祐君]
In-Reply-To: <akT8Niv1ddo-uWmc@ashevche-desk.local>

[-- Attachment #1: Type: text/plain, Size: 3418 bytes --]

On Wed Jul 1, 2026 at 1:38 PM CEST, Andy Shevchenko wrote:
> On Wed, Jul 01, 2026 at 01:55:11PM +0300, Andy Shevchenko wrote:
>> On Wed, Jul 01, 2026 at 01:01:10PM +0300, Andy Shevchenko wrote:
>> > On Wed, Jul 1, 2026 at 11:44 AM Michael Walle <mwalle@kernel.org> wrote:
>> > > On Fri Jun 19, 2026 at 11:08 PM CEST, Linus Walleij wrote:
>> > > > On Mon, Jun 8, 2026 at 4:41 PM Michael Walle <mwalle@kernel.org> wrote:
>> > > >
>> > > >> >>> Without an accessor like gpio_regmap_get_gpiochip(), we cannot retrieve the
>> > > >> >>> gpio_chip instantiated inside gpio-regmap.c to fulfill these requirements in our
>> > > >> >>> map() function.
>> > > >>
>> > > >> Why is gpiochip_irq_reqres() called in the first place? Isn't that
>> > > >> only called if the irq handling is set up via gc->irq.chip and not
>> > > >> via gpiochip_irqchip_add_domain() like in gpio-regmap?
>> > > >
>> > > > Not really, the gpiochip_irq_reqres() is called to mark that a
>> > > > GPIO line is used for IRQ, so the gpiolib cannot turn this
>> > > > GPIO into an output line, gpiod_direction_out() will fail
>> > > > on lines used for IRQ. So it's a failsafe.
>> > > >
>> > > > You can live without it of course, but then you don't get
>> > > > this failsafe.
>> > >
>> > > Thanks for the explanation! So did I make a mistake years ago by
>> > > adding the gpiochip_irqchip_add_domain(), see commit 6a45b0e2589f
>> > > ("gpiolib: Introduce gpiochip_irqchip_add_domain()")
>> > >
>> > > As Yu-Chun found, gpiochip_irq_reqres() expect the irq chip data
>> > > to be a gpio_chip, which isn't the case (in general) for an
>> > > externally allocated domain, is it?
>> > 
>> > So the whole issue comes from the fact that the IRQ chip is not marked
>> > as immutable. For immutable IRQ chips (which all GPIO provides should
>> > have) there is no such issue to begin with, id est there is no
>> > gpiochip_irq_reqres() callback assigned (and respective _relres).
>> 
>> Ah, for immutable chips we put either custom ones or
>> GPIOCHIP_IRQ_RESOURCE_HELPERS which actually refers to those callbacks.
>> 
>> So, if the domain is external, it should also provide irq_request_resources
>> and release callbacks. In the custom case we can wrap gpiochip_reqres_irq()
>> and gpiochip_relres_irq() respectively.
>> 
>> But we need to have a struct gpio_chip pointer for them. And note, the
>> IRQ chip data can be anything in that case, so it's not a requirement.
>
> And looking back for implementation in v3 the whole mistake was to use
> GPIOCHIP_IRQ_RESOURCE_HELPERS. It just wanted custom callbacks with
> the IRQ chip data assigned to whatever from which we may then deduce
> struct gpio_chip. It does *not* require to be struct gpio_chip.
> The local driver data structure should keep pointer to struct gpio_regmap.
> That one can be used in the respective .irq_request_resources() and
> .irq_release_resources(). The default ones for gpio-regmap may also
> be provided via a macro, say GPIO_REGMAP_IRQ_RESOURCE_HELPERS.
>
> Hence I don't see the need of having gpio_regmap_get_gpiochip() helper
> and driver can be implemented using gpio-regmap and external IRQ domain.
>
> What did I miss?

IMHO nothing, that's exactly my understanding, too. Except for the
GPIO_REGMAP_IRQ_RESOURCE_HELPERS. See my previous mail. Because that
would have to be set by regmap-irq.

-michael


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 297 bytes --]

^ permalink raw reply

* Re: [PATCH v3 2/7] gpio: regmap: add gpio_regmap_get_gpiochip() accessor
From: Andy Shevchenko @ 2026-07-01 12:03 UTC (permalink / raw)
  To: Michael Walle
  Cc: Andy Shevchenko, Linus Walleij, Bartosz Golaszewski,
	robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
	afaerber@suse.com, wbg@kernel.org,
	mathieu.dubois-briand@bootlin.com, lars@metafoo.de,
	Michael.Hennerich@analog.com, jic23@kernel.org,
	nuno.sa@analog.com, andy@kernel.org, dlechner@baylibre.com,
	TY_Chang[張子逸], linux-gpio@vger.kernel.org,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-realtek-soc@lists.infradead.org, linux-iio@vger.kernel.org,
	CY_Huang[黃鉦晏],
	Stanley Chang[昌育德],
	James Tai [戴志峰],
	Yu-Chun Lin [林祐君]
In-Reply-To: <DJN7HPMWJLXG.157YRMNW34NJQ@kernel.org>

On Wed, Jul 01, 2026 at 01:42:55PM +0200, Michael Walle wrote:
> On Wed Jul 1, 2026 at 1:38 PM CEST, Andy Shevchenko wrote:
> > On Wed, Jul 01, 2026 at 01:55:11PM +0300, Andy Shevchenko wrote:
> >> On Wed, Jul 01, 2026 at 01:01:10PM +0300, Andy Shevchenko wrote:
> >> > On Wed, Jul 1, 2026 at 11:44 AM Michael Walle <mwalle@kernel.org> wrote:
> >> > > On Fri Jun 19, 2026 at 11:08 PM CEST, Linus Walleij wrote:
> >> > > > On Mon, Jun 8, 2026 at 4:41 PM Michael Walle <mwalle@kernel.org> wrote:
> >> > > >
> >> > > >> >>> Without an accessor like gpio_regmap_get_gpiochip(), we cannot retrieve the
> >> > > >> >>> gpio_chip instantiated inside gpio-regmap.c to fulfill these requirements in our
> >> > > >> >>> map() function.
> >> > > >>
> >> > > >> Why is gpiochip_irq_reqres() called in the first place? Isn't that
> >> > > >> only called if the irq handling is set up via gc->irq.chip and not
> >> > > >> via gpiochip_irqchip_add_domain() like in gpio-regmap?
> >> > > >
> >> > > > Not really, the gpiochip_irq_reqres() is called to mark that a
> >> > > > GPIO line is used for IRQ, so the gpiolib cannot turn this
> >> > > > GPIO into an output line, gpiod_direction_out() will fail
> >> > > > on lines used for IRQ. So it's a failsafe.
> >> > > >
> >> > > > You can live without it of course, but then you don't get
> >> > > > this failsafe.
> >> > >
> >> > > Thanks for the explanation! So did I make a mistake years ago by
> >> > > adding the gpiochip_irqchip_add_domain(), see commit 6a45b0e2589f
> >> > > ("gpiolib: Introduce gpiochip_irqchip_add_domain()")
> >> > >
> >> > > As Yu-Chun found, gpiochip_irq_reqres() expect the irq chip data
> >> > > to be a gpio_chip, which isn't the case (in general) for an
> >> > > externally allocated domain, is it?
> >> > 
> >> > So the whole issue comes from the fact that the IRQ chip is not marked
> >> > as immutable. For immutable IRQ chips (which all GPIO provides should
> >> > have) there is no such issue to begin with, id est there is no
> >> > gpiochip_irq_reqres() callback assigned (and respective _relres).
> >> 
> >> Ah, for immutable chips we put either custom ones or
> >> GPIOCHIP_IRQ_RESOURCE_HELPERS which actually refers to those callbacks.
> >> 
> >> So, if the domain is external, it should also provide irq_request_resources
> >> and release callbacks. In the custom case we can wrap gpiochip_reqres_irq()
> >> and gpiochip_relres_irq() respectively.
> >> 
> >> But we need to have a struct gpio_chip pointer for them. And note, the
> >> IRQ chip data can be anything in that case, so it's not a requirement.
> >
> > And looking back for implementation in v3 the whole mistake was to use
> > GPIOCHIP_IRQ_RESOURCE_HELPERS. It just wanted custom callbacks with
> > the IRQ chip data assigned to whatever from which we may then deduce
> > struct gpio_chip. It does *not* require to be struct gpio_chip.
> > The local driver data structure should keep pointer to struct gpio_regmap.
> > That one can be used in the respective .irq_request_resources() and
> > .irq_release_resources(). The default ones for gpio-regmap may also
> > be provided via a macro, say GPIO_REGMAP_IRQ_RESOURCE_HELPERS.
> >
> > Hence I don't see the need of having gpio_regmap_get_gpiochip() helper
> > and driver can be implemented using gpio-regmap and external IRQ domain.
> >
> > What did I miss?
> 
> IMHO nothing, that's exactly my understanding, too. Except for the
> GPIO_REGMAP_IRQ_RESOURCE_HELPERS. See my previous mail. Because that
> would have to be set by regmap-irq.

There are two cases:
- easy, when the chip is provided by the user
(in this case we just missing a couple of callbacks in gpio-regmap)

- hard, when chip is created by regmap-irq
(in this case regmap-irq missing to setup the callbacks)

So, effectively all GPIO drivers that use regmap-irq facility are
now missing the functionality of tracking "GPIO locked as IRQ".

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* Re: [PATCH v3 2/7] gpio: regmap: add gpio_regmap_get_gpiochip() accessor
From: Andy Shevchenko @ 2026-07-01 12:08 UTC (permalink / raw)
  To: Michael Walle
  Cc: Andy Shevchenko, Linus Walleij, Bartosz Golaszewski,
	robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
	afaerber@suse.com, wbg@kernel.org,
	mathieu.dubois-briand@bootlin.com, lars@metafoo.de,
	Michael.Hennerich@analog.com, jic23@kernel.org,
	nuno.sa@analog.com, andy@kernel.org, dlechner@baylibre.com,
	TY_Chang[張子逸], linux-gpio@vger.kernel.org,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-realtek-soc@lists.infradead.org, linux-iio@vger.kernel.org,
	CY_Huang[黃鉦晏],
	Stanley Chang[昌育德],
	James Tai [戴志峰],
	Yu-Chun Lin [林祐君]
In-Reply-To: <DJN7EN61AJGW.2TV8JLMVRFTJ@kernel.org>

On Wed, Jul 01, 2026 at 01:38:54PM +0200, Michael Walle wrote:
> On Wed Jul 1, 2026 at 12:55 PM CEST, Andy Shevchenko wrote:
> > On Wed, Jul 01, 2026 at 01:01:10PM +0300, Andy Shevchenko wrote:
> >> On Wed, Jul 1, 2026 at 11:44 AM Michael Walle <mwalle@kernel.org> wrote:
> >> > On Fri Jun 19, 2026 at 11:08 PM CEST, Linus Walleij wrote:
> >> > > On Mon, Jun 8, 2026 at 4:41 PM Michael Walle <mwalle@kernel.org> wrote:
> >> > >
> >> > >> >>> Without an accessor like gpio_regmap_get_gpiochip(), we cannot retrieve the
> >> > >> >>> gpio_chip instantiated inside gpio-regmap.c to fulfill these requirements in our
> >> > >> >>> map() function.
> >> > >>
> >> > >> Why is gpiochip_irq_reqres() called in the first place? Isn't that
> >> > >> only called if the irq handling is set up via gc->irq.chip and not
> >> > >> via gpiochip_irqchip_add_domain() like in gpio-regmap?
> >> > >
> >> > > Not really, the gpiochip_irq_reqres() is called to mark that a
> >> > > GPIO line is used for IRQ, so the gpiolib cannot turn this
> >> > > GPIO into an output line, gpiod_direction_out() will fail
> >> > > on lines used for IRQ. So it's a failsafe.
> >> > >
> >> > > You can live without it of course, but then you don't get
> >> > > this failsafe.
> >> >
> >> > Thanks for the explanation! So did I make a mistake years ago by
> >> > adding the gpiochip_irqchip_add_domain(), see commit 6a45b0e2589f
> >> > ("gpiolib: Introduce gpiochip_irqchip_add_domain()")
> >> >
> >> > As Yu-Chun found, gpiochip_irq_reqres() expect the irq chip data
> >> > to be a gpio_chip, which isn't the case (in general) for an
> >> > externally allocated domain, is it?
> >> 
> >> So the whole issue comes from the fact that the IRQ chip is not marked
> >> as immutable. For immutable IRQ chips (which all GPIO provides should
> >> have) there is no such issue to begin with, id est there is no
> >> gpiochip_irq_reqres() callback assigned (and respective _relres).
> >
> > Ah, for immutable chips we put either custom ones or
> > GPIOCHIP_IRQ_RESOURCE_HELPERS which actually refers to those callbacks.
> >
> > So, if the domain is external, it should also provide irq_request_resources
> > and release callbacks. In the custom case we can wrap gpiochip_reqres_irq()
> > and gpiochip_relres_irq() respectively.
> 
> Exactly. And its seems that this should have been possible with this
> series, too.
> 
> Apart from that, most drivers use regmap-irq with gpio-regmap. For
> this we'd probably have to add something to regmap-irq because that
> module owns the irq_chip.
> 
> > But we need to have a struct gpio_chip pointer for them. And note, the
> > IRQ chip data can be anything in that case, so it's not a requirement.
> 
> That's what I've meant. Conceptionally, it should be part of
> gpiochip_irqchip_add_domain()/gpiolib, so a user doesn't have to
> have that knowledge. But I don't see how this could be achieved.

But it can be hidden in gpio-regmap + regmap-irq.

So, what we need is:
- patch regmap-irq to be able to customize irq_request_resources and release
- provide default callbacks in gpio-regmap (and export for external domains)
- use those callbacks by default when gpio-regmap creates an IRQ chip

The leftovers are the drivers that use gpio-regmap + their own call to
regmap-irq. I haven't looked into them closely, they usually have custom
xlate and something else. OTOH, they will be able to customize the resource
handling as well.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* [PATCH 0/8] Support ROHM BD73800
From: Matti Vaittinen @ 2026-07-01 12:40 UTC (permalink / raw)
  To: Matti Vaittinen, Matti Vaittinen, Matti Vaittinen
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Liam Girdwood, Mark Brown, Matti Vaittinen, Michael Turquette,
	Stephen Boyd, Brian Masney, Linus Walleij, Bartosz Golaszewski,
	Alexandre Belloni, devicetree, linux-kernel, linux-clk,
	linux-gpio, linux-rtc

[-- Attachment #1: Type: text/plain, Size: 2571 bytes --]

Add support for the ROHM BD73800 PMIC and compatibles.

The ROHM BD73800 is a power management IC which integrates 8 BUCKs and 4
LDOs. There is also an ADC and operation amplifier intended for current
/ temperature measurement and accumulation. RTC and 32.768 kHz clock
gate are also included. The PMIC can be customized via OTP and it has
options for operating as a main PMIC in multi-PMIC installation. Some
of the pins can also be used for GPO or GPI (including interrupt support).

There are also ROHM BD71851 and BD71885 PMICs out there. These are, from
the SW-perspective, similar to the BD73800. There is only some different
default values and OTP settings. The driver should be able to handle them
just fine.

Oh, finally - there is absolutely no rush reviewing this. I am likely to
be (mostly) offline for (at least) 3 weeks. So please, take your time, I
probably will spin the next version only somewhere at August.

---

Matti Vaittinen (8):
  dt-bindings: regulator: ROHM BD73800 regulators
  dt-bindings: mfd: ROHM BD73800 PMIC
  mfd: Support for ROHM BD73800 PMIC core
  rtc: bd70528: Support RTC on ROHM BD73800
  regulator: bd71828: Support ROHM BD73800
  clk: bd718x7: Support ROHM BD73800
  gpio: bd73800: Support ROHM BD73800 PMIC GPIOs
  MAINTAINERS: Add ROHM BD73800 PMIC files

 .../bindings/mfd/rohm,bd73800-pmic.yaml       | 229 ++++++++
 .../regulator/rohm,bd73800-regulator.yaml     | 119 ++++
 MAINTAINERS                                   |   2 +
 drivers/clk/clk-bd718x7.c                     |   8 +
 drivers/gpio/Kconfig                          |  11 +
 drivers/gpio/Makefile                         |   1 +
 drivers/gpio/gpio-bd73800.c                   | 234 ++++++++
 drivers/mfd/Kconfig                           |  15 +-
 drivers/mfd/rohm-bd71828.c                    | 145 ++++-
 drivers/regulator/Kconfig                     |   4 +-
 drivers/regulator/bd71828-regulator.c         | 555 +++++++++++++++++-
 drivers/rtc/rtc-bd70528.c                     |   8 +
 include/linux/mfd/rohm-bd73800.h              | 307 ++++++++++
 include/linux/mfd/rohm-generic.h              |   1 +
 14 files changed, 1629 insertions(+), 10 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/rohm,bd73800-pmic.yaml
 create mode 100644 Documentation/devicetree/bindings/regulator/rohm,bd73800-regulator.yaml
 create mode 100644 drivers/gpio/gpio-bd73800.c
 create mode 100644 include/linux/mfd/rohm-bd73800.h


base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
-- 
2.54.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* [PATCH 1/8] dt-bindings: regulator: ROHM BD73800 regulators
From: Matti Vaittinen @ 2026-07-01 12:41 UTC (permalink / raw)
  To: Matti Vaittinen, Matti Vaittinen, Matti Vaittinen
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Liam Girdwood, Mark Brown, Matti Vaittinen, Michael Turquette,
	Stephen Boyd, Brian Masney, Linus Walleij, Bartosz Golaszewski,
	Alexandre Belloni, devicetree, linux-kernel, linux-clk,
	linux-gpio, linux-rtc
In-Reply-To: <cover.1782909323.git.mazziesaccount@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 4827 bytes --]

From: Matti Vaittinen <mazziesaccount@gmail.com>

Add bindings for the BUCKs and LDOs on ROHM BD73800. The PMIC state
specific voltages can be set in same fashion as with a few other ROHM
PMICs (for example with BD718[15,28,37,47,50,79]). Same properties are
recycled :)

The LDOs 1 and 4 can use different voltage ranges depending on the OTP
configuration.

Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
---
 .../regulator/rohm,bd73800-regulator.yaml     | 119 ++++++++++++++++++
 1 file changed, 119 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/regulator/rohm,bd73800-regulator.yaml

diff --git a/Documentation/devicetree/bindings/regulator/rohm,bd73800-regulator.yaml b/Documentation/devicetree/bindings/regulator/rohm,bd73800-regulator.yaml
new file mode 100644
index 000000000000..c427a04098ec
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/rohm,bd73800-regulator.yaml
@@ -0,0 +1,119 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/rohm,bd73800-regulator.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ROHM BD73800 Power Management Integrated Circuit regulators
+
+maintainers:
+  - Matti Vaittinen <mazziesaccount@gmail.com>
+
+description: |
+  This module is part of the ROHM BD73800 MFD device. For more details
+  see Documentation/devicetree/bindings/mfd/rohm,bd73800-pmic.yaml.
+
+  The regulator controller is represented as a sub-node of the PMIC node
+  on the device tree.
+
+  Regulator nodes should be named to buck<number> and ldo<number>.
+  The valid names for BD73800 regulator nodes are
+  buck1, buck2, buck3, buck4, buck5, buck6, buck7, buck8
+  ldo1, ldo2, ldo3, ldo4
+
+patternProperties:
+  "^buck[1-8]$":
+    type: object
+    description:
+      Properties for a single BUCK regulator.
+    $ref: regulator.yaml#
+
+    properties:
+      regulator-name:
+        pattern: "^buck[1-8]$"
+        description:
+          should be "buck1", ..., "buck8"
+
+      rohm,dvs-run-voltage:
+        description:
+          PMIC default "RUN" state voltage in uV. 0 means disabled. See the
+          explanation below for regulator specific details.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 3500000
+
+      rohm,dvs-idle-voltage:
+        description:
+          PMIC default "IDLE" state voltage in uV. 0 means disabled. See the
+          explanation below for regulator specific details.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 3500000
+
+      rohm,dvs-suspend-voltage:
+        description:
+          PMIC default "SUSPEND" state voltage in uV. 0 means disabled. See the
+          explanation below for regulator specific details.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 3500000
+
+        # BUCKs 1,2,3,4 and 8 support voltages 0.5 - 1.3V
+        # BUCK 5 supports voltages 0.3 - 1.3V
+        # BUCKs 6 and 7 support voltages 1.5 - 3.5V
+
+    required:
+      - regulator-name
+
+    unevaluatedProperties: false
+
+  "^ldo[1-4]$":
+    type: object
+    description:
+      Properties for single LDO regulator.
+    $ref: regulator.yaml#
+
+    properties:
+      regulator-name:
+        pattern: "^ldo[1-4]$"
+        description:
+          should be "ldo1", ..., "ldo4"
+
+      rohm,dvs-run-voltage:
+        description:
+          Set the default output state at PMIC's "RUN" state.
+          0 is disabled, 1 is enabled.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 1
+
+      rohm,dvs-idle-voltage:
+        description:
+          Set the default output state at PMIC's "IDLE" state.
+          0 is disabled, 1 is enabled.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 1
+
+      rohm,dvs-suspend-voltage:
+        description:
+          Set the default output state at PMIC's "SUSPEND" state.
+          0 is disabled, 1 is enabled.
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 1
+
+      rohm,ldo-range-high:
+        type: boolean
+        description:
+          LDO1 and LDO3 voltage ranges can be "high" or "low" depending on
+          OTP. Indicate that the "high" range is used. See comment below
+          for voltages.
+
+        # LDOs 2 and 4 support voltages 0.75 - 3.3V
+        # LDOs 1 and 3 may support different ranges depending on OTP.
+        # either 0.6 - 1.8V or 0.75 - 3.3V.
+
+    unevaluatedProperties: false
+
+additionalProperties: false
-- 
2.54.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply related

* [PATCH 2/8] dt-bindings: mfd: ROHM BD73800 PMIC
From: Matti Vaittinen @ 2026-07-01 12:41 UTC (permalink / raw)
  To: Matti Vaittinen, Matti Vaittinen, Matti Vaittinen
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Liam Girdwood, Mark Brown, Matti Vaittinen, Michael Turquette,
	Stephen Boyd, Brian Masney, Linus Walleij, Bartosz Golaszewski,
	Alexandre Belloni, devicetree, linux-kernel, linux-clk,
	linux-gpio, linux-rtc
In-Reply-To: <cover.1782909323.git.mazziesaccount@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 9418 bytes --]

From: Matti Vaittinen <mazziesaccount@gmail.com>

The ROHM BD73800 is a power management IC which integrates 8 BUCKs and 4
LDOs. There is also an ADC and operation amplifier intended for current
/ temperature measurement and accumulation. RTC and 32.768 kHz clock
gate are also included. The PMIC can be customized via OTP and it has
options for operating as a main PMIC in multi-PMIC installation. Some
of the pins can also be used for GPO or GPI (including interrupt support).

There are also ROHM BD71851 and BD71885 PMICs out there. These are, from
the SW-perspective, similar to the BD73800. There is only some different
default values and OTP settings. The driver should be able to handle them
just fine.

Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
---
 .../bindings/mfd/rohm,bd73800-pmic.yaml       | 229 ++++++++++++++++++
 1 file changed, 229 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/rohm,bd73800-pmic.yaml

diff --git a/Documentation/devicetree/bindings/mfd/rohm,bd73800-pmic.yaml b/Documentation/devicetree/bindings/mfd/rohm,bd73800-pmic.yaml
new file mode 100644
index 000000000000..6371de08b865
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/rohm,bd73800-pmic.yaml
@@ -0,0 +1,229 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/rohm,bd73800-pmic.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ROHM BD73800 Power Management Integrated Circuit
+
+maintainers:
+  - Matti Vaittinen <mazziesaccount@gmail.com>
+
+description:
+  BD73800GW is a single-chip power management IC for battery-powered
+  portable devices. It integrates 8 buck converters, 4 LDOs and a current
+  sense amplifier with ADC. Also included is a Real Time Clock (RTC) and a
+  32.768 kHz clock gate. Depending on the OTP configuration the BD73800
+  may also have interrupt controller and GPIOs.
+
+  There are also different variants called BD71851 and BD71885 which are
+  almost identical from the software point of view.
+
+properties:
+  compatible:
+    oneOf:
+      - const: rohm,bd73800
+
+      - items:
+          - const: rohm,bd71851
+          - const: rohm,bd73800
+
+      - items:
+          - const: rohm,bd71885
+          - const: rohm,bd73800
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  # The GPIO1, CLKOUT (GPIO2), FAULT_B and EXTEN_OUT pins can be
+  # configured to interrupt pins by OTP.
+  interrupt-controller: true
+
+  "#interrupt-cells":
+    const: 1
+    description:
+      The IRQ number. 0 is GPIO1, 1 CLKOUT (GPIO2), 2 FAULT_B and 3 EXTEN_OUT.
+      NOTE, A pin can operate as IRQ source only when the OTP
+      configuration for it has been set to GPI.
+
+  gpio-controller: true
+
+  "#gpio-cells":
+    const: 2
+
+# The GPIO1, CLKOUT, FAULT_B and EXTEN_OUT pins may be configured for a
+# specific purpose (like ADC input, 32.768 clk output, fault indicator or
+# delivering power sequence to a companion PMIC when multiple PMICs are
+# used) - but also to be either a GPO or GPI. (When used as a GPI the pin
+# can also be used as an IRQ source). The pin purpose is determined by
+# OTP (One Time Programmable memory), typically during device manufacturing.
+# The OTP can't be read at runtime so device-tree should describe the pins.
+  rohm,pin-gpio1:
+    $ref: /schemas/types.yaml#/definitions/string
+    description:
+      Indicate if the GPIO1 pin has been set to GPI or GPO at manufacturing.
+    enum: [gpi, gpo]
+
+  rohm,pin-clkout:
+    $ref: /schemas/types.yaml#/definitions/string
+    description:
+      Indicate if the CLKOUT pin has been set to GPI or GPO at manufacturing.
+    enum: [gpi, gpo]
+
+  rohm,pin-fault-b:
+    $ref: /schemas/types.yaml#/definitions/string
+    description:
+      Indicate if the FAULT_B pin has been set to GPI or GPO at manufacturing.
+    enum: [gpi, gpo]
+
+  rohm,pin-exten:
+    $ref: /schemas/types.yaml#/definitions/string
+    description:
+      Indicate if the EXTEN_OUT pin has been set to GPI or GPO at
+      manufacturing.
+    enum: [gpi, gpo]
+
+  # The CLKOUT pin may have its purpose overridden by OTP configuration. It is
+  # possible the BD73800 does not output a clock signal. Hence the optional clk
+  # properties.
+  clocks:
+    maxItems: 1
+
+  "#clock-cells":
+    const: 0
+
+  clock-output-names:
+    const: bd73800-32k-out
+
+  rohm,clkout-open-drain:
+    description: clk32kout mode. Set to 1 for "open-drain" or 0 for "cmos".
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 0
+    maximum: 1
+
+  regulators:
+    $ref: /schemas/regulator/rohm,bd73800-regulator.yaml
+    description:
+      List of child nodes that specify the regulators.
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - regulators
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/leds/common.h>
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        pmic: pmic@4b {
+            compatible = "rohm,bd73800";
+            reg = <0x4b>;
+
+            interrupt-parent = <&gpio1>;
+            interrupts = <29 IRQ_TYPE_LEVEL_LOW>;
+
+            clocks = <&osc 0>;
+            #clock-cells = <0>;
+            clock-output-names = "bd73800-32k-out";
+
+            gpio-controller;
+            #gpio-cells = <2>;
+
+            rohm,pin-gpio1 = "gpo";
+            rohm,pin-exten = "gpi";
+
+            regulators {
+                buck1: buck1 {
+                    regulator-name = "buck1";
+                    regulator-min-microvolt = <800000>;
+                    regulator-max-microvolt = <2000000>;
+                    regulator-always-on;
+                    regulator-ramp-delay = <1250>;
+                    rohm,dvs-run-voltage = <1150000>;
+                    rohm,dvs-suspend-voltage = <950000>;
+                };
+                buck2: buck2 {
+                    regulator-name = "buck2";
+                    regulator-min-microvolt = <800000>;
+                    regulator-max-microvolt = <2000000>;
+                    regulator-always-on;
+                    regulator-ramp-delay = <1250>;
+                    rohm,dvs-run-voltage = <1150000>;
+                    rohm,dvs-suspend-voltage = <950000>;
+                };
+                buck3: buck3 {
+                    regulator-name = "buck3";
+                    regulator-min-microvolt = <1200000>;
+                    regulator-max-microvolt = <2700000>;
+                    rohm,dvs-run-voltage = <1150000>;
+                    rohm,dvs-idle-voltage = <1100000>;
+                    rohm,dvs-suspend-voltage = <950000>;
+                    regulator-always-on;
+                };
+                buck4: buck4 {
+                    regulator-name = "buck4";
+                    regulator-min-microvolt = <1100000>;
+                    regulator-max-microvolt = <1850000>;
+                    regulator-always-on;
+                };
+                buck5: buck5 {
+                    regulator-name = "buck5";
+                    regulator-min-microvolt = <1800000>;
+                    regulator-max-microvolt = <3300000>;
+                    regulator-always-on;
+                };
+                buck6: buck6 {
+                    regulator-name = "buck6";
+                    regulator-min-microvolt = <1800000>;
+                    regulator-max-microvolt = <3300000>;
+                    regulator-always-on;
+                };
+                buck7: buck7 {
+                    regulator-name = "buck7";
+                    regulator-min-microvolt = <1800000>;
+                    regulator-max-microvolt = <3300000>;
+                    regulator-always-on;
+                };
+                buck8: buck8 {
+                    regulator-name = "buck8";
+                    regulator-min-microvolt = <500000>;
+                    regulator-max-microvolt = <1300000>;
+                    regulator-always-on;
+                };
+                ldo1: ldo1 {
+                    regulator-name = "ldo1";
+                    rohm,ldo-range-high;
+                    regulator-min-microvolt = <800000>;
+                    regulator-max-microvolt = <3300000>;
+                    regulator-always-on;
+                };
+                ldo2: ldo2 {
+                    regulator-name = "ldo2";
+                    regulator-min-microvolt = <800000>;
+                    regulator-max-microvolt = <3300000>;
+                    regulator-always-on;
+                };
+                ldo3: ldo3 {
+                    regulator-name = "ldo3";
+                    regulator-min-microvolt = <800000>;
+                    regulator-max-microvolt = <3300000>;
+                    regulator-always-on;
+                };
+                ldo4: ldo4 {
+                    regulator-name = "ldo4";
+                    regulator-min-microvolt = <650000>;
+                    regulator-max-microvolt = <1750000>;
+                    regulator-always-on;
+                };
+            };
+        };
+    };
-- 
2.54.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply related

* [PATCH 3/8] mfd: Support for ROHM BD73800 PMIC core
From: Matti Vaittinen @ 2026-07-01 12:41 UTC (permalink / raw)
  To: Matti Vaittinen, Matti Vaittinen, Matti Vaittinen
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Liam Girdwood, Mark Brown, Matti Vaittinen, Michael Turquette,
	Stephen Boyd, Brian Masney, Linus Walleij, Bartosz Golaszewski,
	Alexandre Belloni, devicetree, linux-kernel, linux-clk,
	linux-gpio, linux-rtc
In-Reply-To: <cover.1782909323.git.mazziesaccount@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 21493 bytes --]

From: Matti Vaittinen <mazziesaccount@gmail.com>

The BD73800 integrates regulators, ADC (intended for accumulating current /
voltage / power values), a real-time clock (RTC), clock gate and GPIOs.

Add core support for ROHM BD73800 Power Management IC.

Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
---
 drivers/mfd/Kconfig              |  15 +-
 drivers/mfd/rohm-bd71828.c       | 145 ++++++++++++++-
 include/linux/mfd/rohm-bd73800.h | 307 +++++++++++++++++++++++++++++++
 include/linux/mfd/rohm-generic.h |   1 +
 4 files changed, 461 insertions(+), 7 deletions(-)
 create mode 100644 include/linux/mfd/rohm-bd73800.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 763ce6a34782..c5e9032eb9de 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -2222,7 +2222,7 @@ config MFD_ROHM_BD718XX
 	  and emergency shut down as well as 32,768KHz clock output.
 
 config MFD_ROHM_BD71828
-	tristate "ROHM BD718[15/28/79], BD72720 and BD73900 PMICs"
+	tristate "ROHM BD718[15/28/79], BD72720 and BD73[8/9]00 PMICs"
 	depends on I2C=y
 	depends on OF
 	select REGMAP_I2C
@@ -2230,14 +2230,17 @@ config MFD_ROHM_BD71828
 	select MFD_CORE
 	help
 	  Select this option to get support for the ROHM BD71815, BD71828,
-	  BD71879, BD72720 and BD73900 Power Management ICs (PMICs). These are
-	  single-chip Power Management ICs (PMIC), mainly for battery-powered
-	  portable devices.
+	  BD71879, BD72720, BD73800 and BD73900 Power Management ICs (PMICs).
+	  These are single-chip Power Management ICs (PMIC), mainly for
+	  battery-powered portable devices.
 	  The BD71815 has 5 bucks, 7 LDOs, and a boost for driving LEDs.
 	  The BD718[28/79] have 7 buck converters and 7 LDOs.
 	  The BD72720 and the BD73900 have 10 bucks and 11 LDOs.
-	  All ICs provide a single-cell linear charger, a Coulomb counter,
-	  a Real-Time Clock (RTC), GPIOs and a 32.768 kHz clock gate.
+	  All the above ICs provide a single-cell linear charger, and a Coulomb
+	  counter.
+	  The BD73800 has 8 bucks, 4 LDOs and ADC for power/current
+	  accumulation but no charging logic. All these PMICs integrate also a
+	  Real-Time Clock (RTC), GPIOs and a 32.768 kHz clock gate.
 
 config MFD_ROHM_BD957XMUF
 	tristate "ROHM BD9576MUF and BD9573MUF Power Management ICs"
diff --git a/drivers/mfd/rohm-bd71828.c b/drivers/mfd/rohm-bd71828.c
index a79f354bf5cb..31637777b627 100644
--- a/drivers/mfd/rohm-bd71828.c
+++ b/drivers/mfd/rohm-bd71828.c
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2019 ROHM Semiconductors
  *
- * ROHM BD718[15/28/79] and BD72720 PMIC driver
+ * ROHM BD718[15/28/79], BD72720 and BD73[8/9]00 PMIC driver
  */
 
 #include <linux/gpio_keys.h>
@@ -15,6 +15,7 @@
 #include <linux/mfd/rohm-bd71815.h>
 #include <linux/mfd/rohm-bd71828.h>
 #include <linux/mfd/rohm-bd72720.h>
+#include <linux/mfd/rohm-bd73800.h>
 #include <linux/mfd/rohm-generic.h>
 #include <linux/module.h>
 #include <linux/of.h>
@@ -68,6 +69,12 @@ static const struct resource bd72720_rtc_irqs[] = {
 	DEFINE_RES_IRQ_NAMED(BD72720_INT_RTC2, "bd70528-rtc-alm-2"),
 };
 
+static const struct resource bd73800_rtc_irqs[] = {
+	DEFINE_RES_IRQ_NAMED(BD73800_INT_RTC0, "bd70528-rtc-alm-0"),
+	DEFINE_RES_IRQ_NAMED(BD73800_INT_RTC1, "bd70528-rtc-alm-1"),
+	DEFINE_RES_IRQ_NAMED(BD73800_INT_RTC2, "bd70528-rtc-alm-2"),
+};
+
 static const struct resource bd71815_power_irqs[] = {
 	DEFINE_RES_IRQ_NAMED(BD71815_INT_DCIN_RMV, "bd71815-dcin-rmv"),
 	DEFINE_RES_IRQ_NAMED(BD71815_INT_CLPS_OUT, "bd71815-dcin-clps-out"),
@@ -249,6 +256,17 @@ static const struct mfd_cell bd72720_mfd_cells[] = {
 	},
 };
 
+static const struct mfd_cell bd73800_mfd_cells[] = {
+	{ .name = "bd73800-pmic", },
+	{ .name = "bd73800-clk", },
+	{ .name = "bd73800-gpio", },
+	{
+		.name = "bd73800-rtc",
+		.num_resources = ARRAY_SIZE(bd73800_rtc_irqs),
+		.resources = &bd73800_rtc_irqs[0],
+	},
+};
+
 static const struct regmap_range bd71815_volatile_ranges[] = {
 	regmap_reg_range(BD71815_REG_SEC, BD71815_REG_YEAR),
 	regmap_reg_range(BD71815_REG_CONF, BD71815_REG_BAT_TEMP),
@@ -358,6 +376,17 @@ static const struct regmap_range bd72720_volatile_ranges_4c[] = {
 	BD72720_UNWRAP_REG_RANGE(BD72720_REG_IMPCHK_CTRL, BD72720_REG_IMPCHK_CTRL),
 };
 
+static const struct regmap_range bd73800_volatile_ranges[] = {
+	regmap_reg_range(BD73800_REG_POR_REASON, BD73800_REG_POW_STATE),
+	regmap_reg_range(BD73800_REG_PS_CTRL_1, BD73800_REG_PS_CTRL_2),
+	regmap_reg_range(BD73800_REG_RCVNUM, BD73800_REG_RCVNUM),
+	regmap_reg_range(BD73800_REG_RTC_SEC, BD73800_REG_RTC_YEAR),
+	regmap_reg_range(BD73800_REG_RTC_CONF, BD73800_REG_RTC_CONF),
+	regmap_reg_range(BD73800_REG_ADC_ACCUM_KICK, BD73800_REG_ADC_TEMP_VAL0),
+	regmap_reg_range(BD73800_REG_INT_MAIN_STAT, BD73800_REG_INT_5_STAT),
+	regmap_reg_range(BD73800_REG_INT_MAIN_SRC, BD73800_REG_INT_5_SRC),
+};
+
 static const struct regmap_access_table bd71815_volatile_regs = {
 	.yes_ranges = &bd71815_volatile_ranges[0],
 	.n_yes_ranges = ARRAY_SIZE(bd71815_volatile_ranges),
@@ -383,6 +412,24 @@ static const struct regmap_access_table bd72720_volatile_regs_4c = {
 	.n_yes_ranges = ARRAY_SIZE(bd72720_volatile_ranges_4c),
 };
 
+static const struct regmap_access_table bd73800_volatile_regs = {
+	.yes_ranges = &bd73800_volatile_ranges[0],
+	.n_yes_ranges = ARRAY_SIZE(bd73800_volatile_ranges),
+};
+
+static const struct regmap_range bd73800_read_only_ranges[] = {
+	regmap_reg_range(BD73800_REG_PRODUCT_ID, BD73800_REG_NVMVERSION),
+	regmap_reg_range(BD73800_REG_POW_STATE, BD73800_REG_POW_STATE),
+	regmap_reg_range(BD73800_REG_ADC_ACCUM_CNT2, BD73800_REG_ADC_TEMP_VAL0),
+	regmap_reg_range(BD73800_REG_INT_MAIN_STAT, BD73800_REG_INT_MAIN_STAT),
+	regmap_reg_range(BD73800_REG_INT_MAIN_SRC, BD73800_REG_INT_5_SRC),
+};
+
+static const struct regmap_access_table bd73800_ro_regs = {
+	.no_ranges = &bd73800_read_only_ranges[0],
+	.n_no_ranges = ARRAY_SIZE(bd73800_read_only_ranges),
+};
+
 static const struct regmap_config bd71815_regmap = {
 	.reg_bits = 8,
 	.val_bits = 8,
@@ -467,6 +514,15 @@ static const struct regmap_config bd72720_regmap_4c = {
 	.cache_type = REGCACHE_MAPLE,
 };
 
+static const struct regmap_config bd73800_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.wr_table = &bd73800_ro_regs,
+	.volatile_table = &bd73800_volatile_regs,
+	.max_register = BD73800_MAX_REGISTER - 1,
+	.cache_type = REGCACHE_MAPLE,
+};
+
 /*
  * Mapping of main IRQ register bits to sub-IRQ register offsets so that we can
  * access corect sub-IRQ registers based on bits that are set in main IRQ
@@ -798,6 +854,60 @@ static int bd72720_set_type_config(unsigned int **buf, unsigned int type,
 	return regmap_irq_set_type_config_simple(buf, type, irq_data, idx, irq_drv_data);
 }
 
+static const struct regmap_irq bd73800_irqs[] = {
+	/* INT_STAT_1 register IRQs, ADC and RTC */
+	REGMAP_IRQ_REG(BD73800_INT_ADC_ACCUM_DONE, 0, BD73800_INT_ADC_ACCUM_DONE_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_ADC_ACCUM_OVF, 0, BD73800_INT_ADC_ACCUM_OVF_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_ADC_ACCUM_VAL, 0, BD73800_INT_ADC_ACCUM_VAL_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_ADC_ACCUM_TW, 0, BD73800_INT_ADC_ACCUM_TW_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_ADC_POW_VAL, 0, BD73800_INT_ADC_POW_VAL_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_RTC0, 0, BD73800_INT_RTC0_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_RTC1, 0, BD73800_INT_RTC1_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_RTC2, 0, BD73800_INT_RTC2_MASK),
+
+	/* BUCK reg interrupts */
+	/* INT_STAT_2 IRQs */
+	REGMAP_IRQ_REG(BD73800_INT_BUCK1_DVS_DONE, 1, BD73800_INT_BUCK1_DVS_DONE_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_BUCK2_DVS_DONE, 1, BD73800_INT_BUCK2_DVS_DONE_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_BUCK3_DVS_DONE, 1, BD73800_INT_BUCK3_DVS_DONE_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_BUCK4_DVS_DONE, 1, BD73800_INT_BUCK4_DVS_DONE_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_BUCK5_DVS_DONE, 1, BD73800_INT_BUCK5_DVS_DONE_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_BUCK6_DVS_DONE, 1, BD73800_INT_BUCK6_DVS_DONE_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_BUCK7_DVS_DONE, 1, BD73800_INT_BUCK7_DVS_DONE_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_BUCK8_DVS_DONE, 1, BD73800_INT_BUCK8_DVS_DONE_MASK),
+	/* INT_STAT_3 IRQs */
+	REGMAP_IRQ_REG(BD73800_INT_BUCK1_OCP, 2, BD73800_INT_BUCK1_OCP_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_BUCK2_OCP, 2, BD73800_INT_BUCK2_OCP_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_BUCK3_OCP, 2, BD73800_INT_BUCK3_OCP_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_BUCK4_OCP, 2, BD73800_INT_BUCK4_OCP_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_BUCK5_OCP, 2, BD73800_INT_BUCK5_OCP_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_BUCK6_OCP, 2, BD73800_INT_BUCK6_OCP_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_BUCK7_OCP, 2, BD73800_INT_BUCK7_OCP_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_BUCK8_OCP, 2, BD73800_INT_BUCK8_OCP_MASK),
+
+	/* INT_STAT_4 IRQs, power-button, WDG and reset */
+	REGMAP_IRQ_REG(BD73800_INT_PBTN_LONG_PRESS, 3, BD73800_INT_PBTN_LONG_PRESS_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_PBTN_MID_PRESS, 3, BD73800_INT_PBTN_MID_PRESS_MASK),
+	/*
+	 * The SHORT_PUSH is generated when button is first pressed (longer
+	 * than configured time limit), and then released before the MID_PRESS
+	 * time limit. The SHORT_PRESS is generated immediately when button is
+	 * pressed for longer than configured limit, whether it is released or
+	 * not.
+	 */
+	REGMAP_IRQ_REG(BD73800_INT_PBTN_SHORT_PUSH, 3, BD73800_INT_PBTN_SHORT_PUSH_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_PBTN_SHORT_PRESS, 3, BD73800_INT_PBTN_SHORT_PRESS_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_WDG, 3, BD73800_INT_WDG_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_SWRESET, 3, BD73800_INT_SWRESET_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_SEQ_DONE, 3, BD73800_INT_SEQ_DONE_MASK),
+
+	/* INT_STAT_5 IRQs, GPIO */
+	REGMAP_IRQ_REG(BD73800_INT_GPIO1, 4, BD73800_INT_GPIO1_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_GPIO2, 4, BD73800_INT_GPIO2_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_GPIO3, 4, BD73800_INT_GPIO3_MASK),
+	REGMAP_IRQ_REG(BD73800_INT_GPIO4, 4, BD73800_INT_GPIO4_MASK),
+};
+
 static const struct regmap_irq_chip bd71828_irq_chip = {
 	.name = "bd71828_irq",
 	.main_status = BD71828_REG_INT_MAIN,
@@ -852,6 +962,25 @@ static const struct regmap_irq_chip bd72720_irq_chip = {
 	.irq_reg_stride = 1,
 };
 
+static const struct regmap_irq_chip bd73800_irq_chip = {
+	.name = "bd73800_irq",
+	.main_status = BD73800_REG_INT_MAIN_STAT,
+	.irqs = &bd73800_irqs[0],
+	.num_irqs = ARRAY_SIZE(bd73800_irqs),
+	.status_base = BD73800_REG_INT_1_STAT,
+	.unmask_base = BD73800_REG_INT_1_EN,
+	.ack_base = BD73800_REG_INT_1_STAT,
+	.init_ack_masked = true,
+	.num_regs = 5,
+	.num_main_regs = 1,
+	/*
+	 * Ignore mirrored bits [7:5]. They are handled as part of normal INT_4
+	 * handling.
+	 */
+	.num_main_status_bits = 5,
+	.irq_reg_stride = 1,
+};
+
 static int set_clk_mode(struct device *dev, struct regmap *regmap,
 			int clkmode_reg)
 {
@@ -987,6 +1116,17 @@ static int bd71828_i2c_probe(struct i2c_client *i2c)
 		main_lvl_val = BD72720_MASK_LVL1_EN_ALL;
 		break;
 	}
+	case ROHM_CHIP_TYPE_BD73800:
+		mfd = bd73800_mfd_cells;
+		cells = ARRAY_SIZE(bd73800_mfd_cells);
+		regmap_config = &bd73800_regmap;
+		irqchip = &bd73800_irq_chip;
+		clkmode_reg = BD73800_REG_OUT32K;
+		button_irq = BD73800_INT_PBTN_SHORT_PUSH;
+		main_lvl_mask_reg = BD73800_REG_INT_MAIN_EN;
+		main_lvl_val = BD73800_INT_MAIN_EN_ALL;
+		break;
+
 	default:
 		dev_err(&i2c->dev, "Unknown device type");
 		return -EINVAL;
@@ -1066,6 +1206,9 @@ static const struct of_device_id bd71828_of_match[] = {
 	}, {
 		.compatible = "rohm,bd72720",
 		.data = (void *)ROHM_CHIP_TYPE_BD72720,
+	}, {
+		.compatible = "rohm,bd73800",
+		.data = (void *)ROHM_CHIP_TYPE_BD73800,
 	 },
 	{ },
 };
diff --git a/include/linux/mfd/rohm-bd73800.h b/include/linux/mfd/rohm-bd73800.h
new file mode 100644
index 000000000000..4bceb20ac6b1
--- /dev/null
+++ b/include/linux/mfd/rohm-bd73800.h
@@ -0,0 +1,307 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright 2024 ROHM Semiconductors.
+ *
+ * Author: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
+ */
+
+#ifndef _MFD_BD73800_H
+#define _MFD_BD73800_H
+
+#include <linux/regmap.h>
+
+enum {
+	BD73800_BUCK1	=	0,
+	BD73800_BUCK2,
+	BD73800_BUCK3,
+	BD73800_BUCK4,
+	BD73800_BUCK5,
+	BD73800_BUCK6,
+	BD73800_BUCK7,
+	BD73800_BUCK8,
+	BD73800_LDO1,
+	BD73800_LDO2,
+	BD73800_LDO3,
+	BD73800_LDO4,
+};
+
+/*
+ * All regulators except BUCK 5 have full 8-bit register of valid voltage
+ * values, including 0.
+ */
+#define BD73800_NUM_VOLTS	(0xff + 1)
+/*
+ * BUCK 5 has two sets of voltage ranges, both having valid voltage selectors
+ * from 0x0 to 0x7f
+ */
+#define BD73800_BUCK5_VOLTS	(0x80 + 0x80)
+
+/* BD73800 interrupts */
+enum {
+	/* INT_STAT_1 register IRQs, ADC and RTC */
+	BD73800_INT_ADC_ACCUM_DONE,
+	BD73800_INT_ADC_ACCUM_OVF,
+	BD73800_INT_ADC_ACCUM_VAL,
+	BD73800_INT_ADC_ACCUM_TW,
+	BD73800_INT_ADC_POW_VAL,
+	BD73800_INT_RTC0,
+	BD73800_INT_RTC1,
+	BD73800_INT_RTC2,
+
+	/* BUCK reg interrupts */
+	/* INT_STAT_2 IRQs */
+	BD73800_INT_BUCK1_DVS_DONE,
+	BD73800_INT_BUCK2_DVS_DONE,
+	BD73800_INT_BUCK3_DVS_DONE,
+	BD73800_INT_BUCK4_DVS_DONE,
+	BD73800_INT_BUCK5_DVS_DONE,
+	BD73800_INT_BUCK6_DVS_DONE,
+	BD73800_INT_BUCK7_DVS_DONE,
+	BD73800_INT_BUCK8_DVS_DONE,
+	/* INT_STAT_3 IRQs */
+	BD73800_INT_BUCK1_OCP,
+	BD73800_INT_BUCK2_OCP,
+	BD73800_INT_BUCK3_OCP,
+	BD73800_INT_BUCK4_OCP,
+	BD73800_INT_BUCK5_OCP,
+	BD73800_INT_BUCK6_OCP,
+	BD73800_INT_BUCK7_OCP,
+	BD73800_INT_BUCK8_OCP,
+
+	/* INT_STAT_4 IRQs, power-button, WDG and reset */
+	BD73800_INT_PBTN_LONG_PRESS,
+	BD73800_INT_PBTN_MID_PRESS,
+	/*
+	 * The SHORT_PUSH is generated when button is first pressed (longer
+	 * than configured time limit), and then released before the MID_PRESS
+	 * time limit. The SHORT_PRESS is generated immediately when button is
+	 * pressed for longer than configured limit, whether it is released or
+	 * not.
+	 */
+	BD73800_INT_PBTN_SHORT_PUSH,
+	BD73800_INT_PBTN_SHORT_PRESS,
+	BD73800_INT_WDG,
+	BD73800_INT_SWRESET,
+	BD73800_INT_SEQ_DONE,
+
+	/* INT_STAT_5 IRQs, GPIO */
+	BD73800_INT_GPIO1,
+	BD73800_INT_GPIO2,
+	BD73800_INT_GPIO3,
+	BD73800_INT_GPIO4,
+};
+
+#define BD73800_MASK_RUN_EN		BIT(2)
+#define BD73800_MASK_SUSP_EN		BIT(1)
+#define BD73800_MASK_IDLE_EN		BIT(0)
+#define BD73800_MASK_VOLT		GENMASK(7, 0)
+#define BD73800_MASK_BUCK5_VOLT		GENMASK(6, 0)
+#define BD73800_MASK_RAMP_DELAY		GENMASK(2, 1)
+#define BD73800_BUCK5_RANGE_MASK	BIT(7)
+
+/* BD73800 registers */
+enum {
+	BD73800_REG_PRODUCT_ID	= 0x0,
+	BD73800_REG_MANUFACTURER_ID,
+	BD73800_REG_REVISION,
+	BD73800_REG_NVMVERSION,
+	BD73800_REG_POR_REASON,
+	BD73800_REG_RESET_REASON1,
+	BD73800_REG_RESET_REASON2,
+	BD73800_REG_RESET_REASON3,
+	BD73800_REG_POW_STATE,
+	BD73800_REG_WRST_SEL,
+	BD73800_REG_PS_CTRL_1,
+	BD73800_REG_PS_CTRL_2,
+	BD73800_REG_RCVCFG,
+	BD73800_REG_RCVNUM,
+	BD73800_REG_CRDCFG, /* 0x0f, followed by undocumented reg */
+
+	BD73800_REG_BUCK1_ON = 0x11,
+	BD73800_REG_BUCK1_MODE,
+	BD73800_REG_BUCK1_VOLT_RUN,
+	BD73800_REG_BUCK1_VOLT_IDLE,
+	BD73800_REG_BUCK1_VOLT_SUSP, /* 0x15, followed by undocumented reg */
+
+	BD73800_REG_BUCK2_ON = 0x17,
+	BD73800_REG_BUCK2_MODE,
+	BD73800_REG_BUCK2_VOLT_RUN,
+	BD73800_REG_BUCK2_VOLT_IDLE,
+	BD73800_REG_BUCK2_VOLT_SUSP, /* 0x1b */
+
+	BD73800_REG_BUCK3_ON = 0x1d,
+	BD73800_REG_BUCK3_MODE,
+	BD73800_REG_BUCK3_VOLT_RUN,
+	BD73800_REG_BUCK3_VOLT_IDLE,
+	BD73800_REG_BUCK3_VOLT_SUSP, /* 0x21 */
+
+	BD73800_REG_BUCK4_ON = 0x23,
+	BD73800_REG_BUCK4_MODE,
+	BD73800_REG_BUCK4_VOLT_RUN,
+	BD73800_REG_BUCK4_VOLT_IDLE,
+	BD73800_REG_BUCK4_VOLT_SUSP, /* 0x27 */
+
+	BD73800_REG_BUCK5_ON = 0x29,
+	BD73800_REG_BUCK5_MODE,
+	BD73800_REG_BUCK5_VOLT_RUN,
+	BD73800_REG_BUCK5_VOLT_IDLE,
+	BD73800_REG_BUCK5_VOLT_SUSP, /* 0x2d */
+
+	BD73800_REG_BUCK6_ON = 0x2f,
+	BD73800_REG_BUCK6_MODE,
+	BD73800_REG_BUCK6_VOLT_RUN,
+	BD73800_REG_BUCK6_VOLT_IDLE,
+	BD73800_REG_BUCK6_VOLT_SUSP, /* 0x33 */
+
+	BD73800_REG_BUCK7_ON = 0x35,
+	BD73800_REG_BUCK7_MODE,
+	BD73800_REG_BUCK7_VOLT_RUN,
+	BD73800_REG_BUCK7_VOLT_IDLE,
+	BD73800_REG_BUCK7_VOLT_SUSP, /* 0x39 */
+
+	BD73800_REG_BUCK8_ON = 0x3b,
+	BD73800_REG_BUCK8_MODE,
+	BD73800_REG_BUCK8_VOLT_RUN,
+	BD73800_REG_BUCK8_VOLT_IDLE,
+	BD73800_REG_BUCK8_VOLT_SUSP, /* 0x3f */
+
+	BD73800_REG_LDO1_ON = 0x41,
+	BD73800_REG_LDO1_VOLT,
+	BD73800_REG_LDO1_MODE,
+	BD73800_REG_LDO2_ON,
+	BD73800_REG_LDO2_VOLT,
+	BD73800_REG_LDO2_MODE,
+	BD73800_REG_LDO3_ON,
+	BD73800_REG_LDO3_VOLT,
+	BD73800_REG_LDO3_MODE,
+	BD73800_REG_LDO4_ON,
+	BD73800_REG_LDO4_VOLT,
+	BD73800_REG_LDO4_MODE, /* 0x4c */
+
+	BD73800_REG_GPO_OUT = 0x4e,
+	BD73800_REG_OUT32K = 0x50,
+	BD73800_REG_RTC_SEC,
+	BD73800_REG_RTC_MIN,
+	BD73800_REG_RTC_HOUR,
+	BD73800_REG_RTC_WEEK,
+	BD73800_REG_RTC_DAY,
+	BD73800_REG_RTC_MONTH,
+	BD73800_REG_RTC_YEAR,
+	BD73800_REG_RTC_ALM0_SEC,
+	BD73800_REG_RTC_ALM0_MIN,
+	BD73800_REG_RTC_ALM0_HOUR,
+	BD73800_REG_RTC_ALM0_WEEK,
+	BD73800_REG_RTC_ALM0_DAY,
+	BD73800_REG_RTC_ALM0_MONTH,
+	BD73800_REG_RTC_ALM0_YEAR,
+	BD73800_REG_RTC_ALM1_SEC,
+	BD73800_REG_RTC_ALM1_MIN,
+	BD73800_REG_RTC_ALM1_HOUR,
+	BD73800_REG_RTC_ALM1_WEEK,
+	BD73800_REG_RTC_ALM1_DAY,
+	BD73800_REG_RTC_ALM1_MONTH,
+	BD73800_REG_RTC_ALM1_YEAR,
+	BD73800_REG_RTC_ALM2,
+	BD73800_REG_RTC_CONF, /* 0x69 */
+
+	BD73800_REG_ADC_CTRL_1 = 0x6b,
+	BD73800_REG_ADC_CTRL_2,
+	BD73800_REG_ADC_ACCUM_NUM2,
+	BD73800_REG_ADC_ACCUM_NUM1,
+	BD73800_REG_ADC_ACCUM_NUM0,
+	BD73800_REG_ADC_ACCUM_KICK,
+	BD73800_REG_ADC_ACCUM_CNT2,
+	BD73800_REG_ADC_ACCUM_CNT1,
+	BD73800_REG_ADC_ACCUM_CNT0,
+	BD73800_REG_ADC_ACCUM_VAL2,
+	BD73800_REG_ADC_ACCUM_VAL1,
+	BD73800_REG_ADC_ACCUM_VAL0,
+	BD73800_REG_ADC_VOL_VAL1,
+	BD73800_REG_ADC_VOL_VAL0,
+	BD73800_REG_ADC_CUR_VAL1,
+	BD73800_REG_ADC_CUR_VAL0,
+	BD73800_REG_ADC_POW_VAL1,
+	BD73800_REG_ADC_POW_VAL0,
+	BD73800_REG_ADC_TEMP_VAL1,
+	BD73800_REG_ADC_TEMP_VAL0,
+	BD73800_REG_ADC_ACCUM_VAL_INT_TH4,
+	BD73800_REG_ADC_ACCUM_VAL_INT_TH3,
+	BD73800_REG_ADC_ACCUM_VAL_INT_TH2,
+	BD73800_REG_ADC_ACCUM_VAL_INT_TH1,
+	BD73800_REG_ADC_ACCUM_VAL_INT_TH0,
+	BD73800_REG_ADC_WARN_TEMP_INT_TH1,
+	BD73800_REG_ADC_WARN_TEMP_INT_TH0,
+	BD73800_REG_ADC_POW_VAL_INT_TH1,
+	BD73800_REG_ADC_POW_VAL_INT_TH0, /* 0x89 */
+
+	BD73800_REG_PBTN_CONF = 0x8b,
+
+	BD73800_REG_INT_MAIN_EN = 0x8f,
+	BD73800_REG_INT_1_EN,
+	BD73800_REG_INT_2_EN,
+	BD73800_REG_INT_3_EN,
+	BD73800_REG_INT_4_EN,
+	BD73800_REG_INT_5_EN, /* 0x94 */
+
+	BD73800_REG_INT_MAIN_STAT = 0x96,
+	BD73800_REG_INT_1_STAT,
+	BD73800_REG_INT_2_STAT,
+	BD73800_REG_INT_3_STAT,
+	BD73800_REG_INT_4_STAT,
+	BD73800_REG_INT_5_STAT, /* 0x9b */
+
+	BD73800_REG_INT_MAIN_SRC = 0x9d,
+	BD73800_REG_INT_1_SRC,
+	BD73800_REG_INT_2_SRC,
+	BD73800_REG_INT_3_SRC,
+	BD73800_REG_INT_4_SRC,
+	BD73800_REG_INT_5_SRC, /* 0xa2 */
+
+	BD73800_REG_RST_MASK = 0xaf,
+	BD73800_MAX_REGISTER,
+};
+
+#define BD73800_REG_RTC_START			BD73800_REG_RTC_SEC
+#define BD73800_REG_RTC_ALM_START		BD73800_REG_RTC_ALM0_SEC
+
+/* BD73800 IRQ register masks */
+
+#define BD73800_INT_MAIN_EN_ALL			GENMASK(4, 0)
+#define BD73800_INT_ADC_ACCUM_DONE_MASK		BIT(0)
+#define BD73800_INT_ADC_ACCUM_OVF_MASK		BIT(1)
+#define BD73800_INT_ADC_ACCUM_VAL_MASK		BIT(2)
+#define BD73800_INT_ADC_ACCUM_TW_MASK		BIT(3)
+#define BD73800_INT_ADC_POW_VAL_MASK		BIT(4)
+#define BD73800_INT_RTC0_MASK			BIT(5)
+#define BD73800_INT_RTC1_MASK			BIT(6)
+#define BD73800_INT_RTC2_MASK			BIT(7)
+#define BD73800_INT_BUCK1_DVS_DONE_MASK		BIT(0)
+#define BD73800_INT_BUCK2_DVS_DONE_MASK		BIT(1)
+#define BD73800_INT_BUCK3_DVS_DONE_MASK		BIT(2)
+#define BD73800_INT_BUCK4_DVS_DONE_MASK		BIT(3)
+#define BD73800_INT_BUCK5_DVS_DONE_MASK		BIT(4)
+#define BD73800_INT_BUCK6_DVS_DONE_MASK		BIT(5)
+#define BD73800_INT_BUCK7_DVS_DONE_MASK		BIT(6)
+#define BD73800_INT_BUCK8_DVS_DONE_MASK		BIT(7)
+#define BD73800_INT_BUCK1_OCP_MASK		BIT(0)
+#define BD73800_INT_BUCK2_OCP_MASK		BIT(1)
+#define BD73800_INT_BUCK3_OCP_MASK		BIT(2)
+#define BD73800_INT_BUCK4_OCP_MASK		BIT(3)
+#define BD73800_INT_BUCK5_OCP_MASK		BIT(4)
+#define BD73800_INT_BUCK6_OCP_MASK		BIT(5)
+#define BD73800_INT_BUCK7_OCP_MASK		BIT(6)
+#define BD73800_INT_BUCK8_OCP_MASK		BIT(7)
+#define BD73800_INT_PBTN_LONG_PRESS_MASK	BIT(0)
+#define BD73800_INT_PBTN_MID_PRESS_MASK		BIT(1)
+#define BD73800_INT_PBTN_SHORT_PUSH_MASK	BIT(2)
+#define BD73800_INT_PBTN_SHORT_PRESS_MASK	BIT(3)
+#define BD73800_INT_WDG_MASK			BIT(4)
+#define BD73800_INT_SWRESET_MASK		BIT(5)
+#define BD73800_INT_SEQ_DONE_MASK		BIT(6)
+#define BD73800_INT_GPIO1_MASK			BIT(0)
+#define BD73800_INT_GPIO2_MASK			BIT(1)
+#define BD73800_INT_GPIO3_MASK			BIT(2)
+#define BD73800_INT_GPIO4_MASK			BIT(3)
+
+#endif /* _MFD_BD73800_H */
+
diff --git a/include/linux/mfd/rohm-generic.h b/include/linux/mfd/rohm-generic.h
index 0a284919a6c3..3ec87428ee97 100644
--- a/include/linux/mfd/rohm-generic.h
+++ b/include/linux/mfd/rohm-generic.h
@@ -17,6 +17,7 @@ enum rohm_chip_type {
 	ROHM_CHIP_TYPE_BD71837,
 	ROHM_CHIP_TYPE_BD71847,
 	ROHM_CHIP_TYPE_BD72720,
+	ROHM_CHIP_TYPE_BD73800,
 	ROHM_CHIP_TYPE_BD96801,
 	ROHM_CHIP_TYPE_BD96802,
 	ROHM_CHIP_TYPE_BD96805,
-- 
2.54.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply related

* [PATCH 4/8] rtc: bd70528: Support RTC on ROHM BD73800
From: Matti Vaittinen @ 2026-07-01 12:42 UTC (permalink / raw)
  To: Matti Vaittinen, Matti Vaittinen, Matti Vaittinen
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Liam Girdwood, Mark Brown, Matti Vaittinen, Michael Turquette,
	Stephen Boyd, Brian Masney, Linus Walleij, Bartosz Golaszewski,
	Alexandre Belloni, devicetree, linux-kernel, linux-clk,
	linux-gpio, linux-rtc
In-Reply-To: <cover.1782909323.git.mazziesaccount@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1676 bytes --]

From: Matti Vaittinen <mazziesaccount@gmail.com>

BD73800 contains similar RTC block as BD71828 and BD71815. Only the address
offsets seem different. Support also BD73800 RTC using the rtc-bd70528.

Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
---
 drivers/rtc/rtc-bd70528.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/rtc/rtc-bd70528.c b/drivers/rtc/rtc-bd70528.c
index 482810b61495..fd415e327ea6 100644
--- a/drivers/rtc/rtc-bd70528.c
+++ b/drivers/rtc/rtc-bd70528.c
@@ -8,6 +8,7 @@
 #include <linux/mfd/rohm-bd71815.h>
 #include <linux/mfd/rohm-bd71828.h>
 #include <linux/mfd/rohm-bd72720.h>
+#include <linux/mfd/rohm-bd73800.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
@@ -284,6 +285,12 @@ static int bd70528_probe(struct platform_device *pdev)
 		bd_rtc->bd718xx_alm_block_start = BD72720_REG_RTC_ALM_START;
 		hour_reg = BD72720_REG_RTC_HOUR;
 		break;
+	case ROHM_CHIP_TYPE_BD73800:
+		bd_rtc->reg_time_start = BD73800_REG_RTC_START;
+		bd_rtc->bd718xx_alm_block_start = BD73800_REG_RTC_ALM_START;
+		hour_reg = BD73800_REG_RTC_HOUR;
+		break;
+
 	default:
 		dev_err(&pdev->dev, "Unknown chip\n");
 		return -ENOENT;
@@ -344,6 +351,7 @@ static const struct platform_device_id bd718x7_rtc_id[] = {
 	{ .name = "bd71828-rtc", .driver_data = ROHM_CHIP_TYPE_BD71828 },
 	{ .name = "bd71815-rtc", .driver_data = ROHM_CHIP_TYPE_BD71815 },
 	{ .name = "bd72720-rtc", .driver_data = ROHM_CHIP_TYPE_BD72720 },
+	{ .name = "bd73800-rtc", .driver_data = ROHM_CHIP_TYPE_BD73800 },
 	{ }
 };
 MODULE_DEVICE_TABLE(platform, bd718x7_rtc_id);
-- 
2.54.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply related

* [PATCH 5/8] regulator: bd71828: Support ROHM BD73800
From: Matti Vaittinen @ 2026-07-01 12:42 UTC (permalink / raw)
  To: Matti Vaittinen, Matti Vaittinen, Matti Vaittinen
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Liam Girdwood, Mark Brown, Matti Vaittinen, Michael Turquette,
	Stephen Boyd, Brian Masney, Linus Walleij, Bartosz Golaszewski,
	Alexandre Belloni, devicetree, linux-kernel, linux-clk,
	linux-gpio, linux-rtc
In-Reply-To: <cover.1782909323.git.mazziesaccount@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 23837 bytes --]

From: Matti Vaittinen <mazziesaccount@gmail.com>

The ROHM BD73800 is a power management IC which integrates 8 BUCKs and 4
LDOs. The PMIC has internal state-machine and it can support transitions
to RUN, SUSPEND and IDLE states. The LDOs 1 and 3 have two different
voltage range configurations that can be set at the manufacturing phase
by OTP. By default driver assumes low voltage ranges to be used because
the data-sheet indicates the higher voltage ranges to be an 'OTP option'.
The high voltage range can be indicated via device-tree property.

Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
---
 drivers/regulator/Kconfig             |   4 +-
 drivers/regulator/bd71828-regulator.c | 555 +++++++++++++++++++++++++-
 2 files changed, 556 insertions(+), 3 deletions(-)

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index a54a549196fe..0e5a3994f49d 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -241,12 +241,12 @@ config REGULATOR_BD71815
 	  will be called bd71815-regulator.
 
 config REGULATOR_BD71828
-	tristate "ROHM BD71828, BD72720 and BD73900 Power Regulators"
+	tristate "ROHM BD71828, BD72720 and BD73[8/9]00 Power Regulators"
 	depends on MFD_ROHM_BD71828
 	select REGULATOR_ROHM
 	help
 	  This driver supports voltage regulators on ROHM BD71828,
-	  BD71879, BD72720 and BD73900 PMICs. This will enable
+	  BD71879, BD72720 and BD73[8/9]00 PMICs. This will enable
 	  support for the software controllable buck and LDO regulators.
 
 	  This driver can also be built as a module. If so, the module
diff --git a/drivers/regulator/bd71828-regulator.c b/drivers/regulator/bd71828-regulator.c
index bd61caa8284a..89738953f8b5 100644
--- a/drivers/regulator/bd71828-regulator.c
+++ b/drivers/regulator/bd71828-regulator.c
@@ -1,7 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // Copyright (C) 2019 ROHM Semiconductors
 // bd71828-regulator.c ROHM BD71828GW-DS1 regulator driver
-//
 
 #include <linux/cleanup.h>
 #include <linux/delay.h>
@@ -10,6 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/mfd/rohm-bd71828.h>
 #include <linux/mfd/rohm-bd72720.h>
+#include <linux/mfd/rohm-bd73800.h>
 #include <linux/module.h>
 #include <linux/mod_devicetable.h>
 #include <linux/of.h>
@@ -32,6 +32,13 @@ struct bd71828_regulator_data {
 	int reg_init_amnt;
 };
 
+/*
+ * LDO1 and LDO3 node names are used also in the driver to find OTP setting for
+ * the used voltage range.
+ */
+#define LDO1_NODE_NAME "ldo1"
+#define LDO3_NODE_NAME "ldo3"
+
 static const struct reg_init bd71828_buck1_inits[] = {
 	/*
 	 * DVS Buck voltages can be changed by register values or via GPIO.
@@ -173,6 +180,54 @@ static const struct linear_range bd72720_ldo6_volts[] = {
 	REGULATOR_LINEAR_RANGE(1800000, 0x79, 0x7f, 0),
 };
 
+static const struct linear_range bd73800_buck12348_volts[] = {
+	REGULATOR_LINEAR_RANGE(500000, 0x00, 0x50, 10000),
+	REGULATOR_LINEAR_RANGE(1300000, 0x51, 0xff, 0),
+};
+
+static const unsigned int bd73800_buck5_volt_range_sel[] = {
+	0x0, 0x0, 0x1, 0x1,
+};
+
+static const struct linear_range bd73800_buck5_volts[] = {
+	/* range selector 0 */
+	REGULATOR_LINEAR_RANGE(500000, 0x00, 0x50, 10000),
+	REGULATOR_LINEAR_RANGE(1300000, 0x51, 0x7f, 0),
+	/* range selector 1 */
+	REGULATOR_LINEAR_RANGE(300000, 0x00, 0x46, 10000),
+	REGULATOR_LINEAR_RANGE(1000000, 0x47, 0x7f, 0),
+};
+/*
+ * iBUCK5 has two different pickable ranges, each having voltages matching
+ * selectors 0x0 to 0x7f. This gives 0x7f + 1 different voltages for each of
+ * the ranges.
+ */
+#define BD73800_NUM_BUCK5_VOLTS ((0x7f + 1) * 2)
+
+static const struct linear_range bd73800_buck67_volts[] = {
+	REGULATOR_LINEAR_RANGE(1500000, 0x00, 0xc8, 10000),
+	REGULATOR_LINEAR_RANGE(3500000, 0xc9, 0xff, 0),
+};
+
+/*
+ * On the BD73800 the LDO1 and LDO3 support two different voltage areas.
+ * Whether to use 'high' or 'low' ranges is configured by OTP. There seems
+ * to be no register to read the configured area so it must be given via
+ * device-tree properties.
+ */
+static const struct linear_range bd73800_ldo13_low_volts[] = {
+	REGULATOR_LINEAR_RANGE(600000, 0x00, 0x78, 10000),
+	REGULATOR_LINEAR_RANGE(1800000, 0x79, 0xff, 0),
+};
+
+static const struct linear_range bd73800_ldo13_high_volts[] = {
+	REGULATOR_LINEAR_RANGE(750000, 0x00, 0xff, 10000),
+};
+
+static const struct linear_range bd73800_ldo24_volts[] = {
+	REGULATOR_LINEAR_RANGE(750000, 0x00, 0xff, 10000),
+};
+
 static const unsigned int bd71828_ramp_delay[] = { 2500, 5000, 10000, 20000 };
 
 /*
@@ -226,6 +281,36 @@ static int bd71828_ldo6_parse_dt(struct device_node *np,
 	return 0;
 }
 
+/* Operations for all other BUCKs but BUCK 5 */
+static const struct regulator_ops bd73800_buck_ops = {
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = regulator_is_enabled_regmap,
+	.list_voltage = regulator_list_voltage_linear_range,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_ramp_delay = regulator_set_ramp_delay_regmap,
+};
+
+static const struct regulator_ops bd73800_buck5_ops = {
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = regulator_is_enabled_regmap,
+	.list_voltage = regulator_list_voltage_pickable_linear_range,
+	.set_voltage_sel = regulator_set_voltage_sel_pickable_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
+	.set_ramp_delay = regulator_set_ramp_delay_regmap,
+};
+
+static const struct regulator_ops bd73800_ldo_ops = {
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = regulator_is_enabled_regmap,
+	.list_voltage = regulator_list_voltage_linear_range,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+};
+
 static const struct regulator_ops bd71828_buck_ops = {
 	.enable = regulator_enable_regmap,
 	.disable = regulator_disable_regmap,
@@ -1566,6 +1651,412 @@ static const struct bd71828_regulator_data bd72720_rdata[] = {
 	},
 };
 
+static const struct bd71828_regulator_data bd73800_rdata[] = {
+	{
+		.desc = {
+			.name = "buck1",
+			.of_match = of_match_ptr("buck1"),
+			.regulators_node = of_match_ptr("regulators"),
+			.id = BD73800_BUCK1,
+			.ops = &bd73800_buck_ops,
+			.type = REGULATOR_VOLTAGE,
+			.linear_ranges = bd73800_buck12348_volts,
+			.n_linear_ranges = ARRAY_SIZE(bd73800_buck12348_volts),
+			.n_voltages = BD73800_NUM_VOLTS,
+			.enable_reg = BD73800_REG_BUCK1_ON,
+			.enable_mask = BD73800_MASK_RUN_EN,
+			.vsel_reg = BD73800_REG_BUCK1_VOLT_RUN,
+			.vsel_mask = BD73800_MASK_VOLT,
+			.ramp_delay_table = bd71828_ramp_delay,
+			.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
+			.ramp_reg = BD73800_REG_BUCK1_MODE,
+			.ramp_mask = BD73800_MASK_RAMP_DELAY,
+			.owner = THIS_MODULE,
+			.of_parse_cb = buck_set_hw_dvs_levels,
+		},
+		.dvs = {
+			.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+				     ROHM_DVS_LEVEL_SUSPEND,
+			.run_reg = BD73800_REG_BUCK1_VOLT_RUN,
+			.run_mask = BD73800_MASK_VOLT,
+			.idle_reg = BD73800_REG_BUCK1_VOLT_IDLE,
+			.idle_mask = BD73800_MASK_VOLT,
+			.idle_on_mask = BD73800_MASK_IDLE_EN,
+			.suspend_reg = BD73800_REG_BUCK1_VOLT_SUSP,
+			.suspend_mask = BD73800_MASK_VOLT,
+			.suspend_on_mask = BD73800_MASK_SUSP_EN,
+		},
+	}, {
+		.desc = {
+			.name = "buck2",
+			.of_match = of_match_ptr("buck2"),
+			.regulators_node = of_match_ptr("regulators"),
+			.id = BD73800_BUCK2,
+			.ops = &bd73800_buck_ops,
+			.type = REGULATOR_VOLTAGE,
+			.linear_ranges = bd73800_buck12348_volts,
+			.n_linear_ranges = ARRAY_SIZE(bd73800_buck12348_volts),
+			.n_voltages = BD73800_NUM_VOLTS,
+			.enable_reg = BD73800_REG_BUCK2_ON,
+			.enable_mask = BD73800_MASK_RUN_EN,
+			.vsel_reg = BD73800_REG_BUCK2_VOLT_RUN,
+			.vsel_mask = BD73800_MASK_VOLT,
+			.ramp_delay_table = bd71828_ramp_delay,
+			.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
+			.ramp_reg = BD73800_REG_BUCK2_MODE,
+			.ramp_mask = BD73800_MASK_RAMP_DELAY,
+			.owner = THIS_MODULE,
+			.of_parse_cb = buck_set_hw_dvs_levels,
+		},
+		.dvs = {
+			.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+				     ROHM_DVS_LEVEL_SUSPEND,
+			.run_reg = BD73800_REG_BUCK2_VOLT_RUN,
+			.run_mask = BD73800_MASK_VOLT,
+			.idle_reg = BD73800_REG_BUCK2_VOLT_IDLE,
+			.idle_mask = BD73800_MASK_VOLT,
+			.idle_on_mask = BD73800_MASK_IDLE_EN,
+			.suspend_reg = BD73800_REG_BUCK2_VOLT_SUSP,
+			.suspend_mask = BD73800_MASK_VOLT,
+			.suspend_on_mask = BD73800_MASK_SUSP_EN,
+		},
+	}, {
+		.desc = {
+			.name = "buck3",
+			.of_match = of_match_ptr("buck3"),
+			.regulators_node = of_match_ptr("regulators"),
+			.id = BD73800_BUCK3,
+			.ops = &bd73800_buck_ops,
+			.type = REGULATOR_VOLTAGE,
+			.linear_ranges = bd73800_buck12348_volts,
+			.n_linear_ranges = ARRAY_SIZE(bd73800_buck12348_volts),
+			.n_voltages = BD73800_NUM_VOLTS,
+			.enable_reg = BD73800_REG_BUCK3_ON,
+			.enable_mask = BD73800_MASK_RUN_EN,
+			.vsel_reg = BD73800_REG_BUCK3_VOLT_RUN,
+			.vsel_mask = BD73800_MASK_VOLT,
+			.ramp_delay_table = bd71828_ramp_delay,
+			.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
+			.ramp_reg = BD73800_REG_BUCK3_MODE,
+			.ramp_mask = BD73800_MASK_RAMP_DELAY,
+			.owner = THIS_MODULE,
+			.of_parse_cb = buck_set_hw_dvs_levels,
+		},
+		.dvs = {
+			.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+				     ROHM_DVS_LEVEL_SUSPEND,
+			.run_reg = BD73800_REG_BUCK3_VOLT_RUN,
+			.run_mask = BD73800_MASK_VOLT,
+			.idle_reg = BD73800_REG_BUCK3_VOLT_IDLE,
+			.idle_mask = BD73800_MASK_VOLT,
+			.idle_on_mask = BD73800_MASK_IDLE_EN,
+			.suspend_reg = BD73800_REG_BUCK3_VOLT_SUSP,
+			.suspend_mask = BD73800_MASK_VOLT,
+			.suspend_on_mask = BD73800_MASK_SUSP_EN,
+		},
+
+	}, {
+		.desc = {
+			.name = "buck4",
+			.of_match = of_match_ptr("buck4"),
+			.regulators_node = of_match_ptr("regulators"),
+			.id = BD73800_BUCK4,
+			.ops = &bd73800_buck_ops,
+			.type = REGULATOR_VOLTAGE,
+			.linear_ranges = bd73800_buck12348_volts,
+			.n_linear_ranges = ARRAY_SIZE(bd73800_buck12348_volts),
+			.n_voltages = BD73800_NUM_VOLTS,
+			.enable_reg = BD73800_REG_BUCK4_ON,
+			.enable_mask = BD73800_MASK_RUN_EN,
+			.vsel_reg = BD73800_REG_BUCK4_VOLT_RUN,
+			.vsel_mask = BD73800_MASK_VOLT,
+			.ramp_delay_table = bd71828_ramp_delay,
+			.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
+			.ramp_reg = BD73800_REG_BUCK4_MODE,
+			.ramp_mask = BD73800_MASK_RAMP_DELAY,
+			.owner = THIS_MODULE,
+			.of_parse_cb = buck_set_hw_dvs_levels,
+		},
+		.dvs = {
+			.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+				     ROHM_DVS_LEVEL_SUSPEND,
+			.run_reg = BD73800_REG_BUCK4_VOLT_RUN,
+			.run_mask = BD73800_MASK_VOLT,
+			.idle_reg = BD73800_REG_BUCK4_VOLT_IDLE,
+			.idle_mask = BD73800_MASK_VOLT,
+			.idle_on_mask = BD73800_MASK_IDLE_EN,
+			.suspend_reg = BD73800_REG_BUCK4_VOLT_SUSP,
+			.suspend_mask = BD73800_MASK_VOLT,
+			.suspend_on_mask = BD73800_MASK_SUSP_EN,
+		},
+	}, {
+		.desc = {
+			.name = "buck5",
+			.of_match = of_match_ptr("buck5"),
+			.regulators_node = of_match_ptr("regulators"),
+			.id = BD73800_BUCK5,
+			.ops = &bd73800_buck5_ops,
+			.type = REGULATOR_VOLTAGE,
+			.linear_ranges = bd73800_buck5_volts,
+			.n_linear_ranges = ARRAY_SIZE(bd73800_buck5_volts),
+			.linear_range_selectors_bitfield =
+						bd73800_buck5_volt_range_sel,
+			.n_voltages = BD73800_NUM_BUCK5_VOLTS,
+			.enable_reg = BD73800_REG_BUCK5_ON,
+			.enable_mask = BD73800_MASK_RUN_EN,
+			.vsel_reg = BD73800_REG_BUCK5_VOLT_RUN,
+			.vsel_mask = BD73800_MASK_VOLT,
+			.vsel_range_reg = BD73800_REG_BUCK5_MODE,
+			.vsel_range_mask = BD73800_BUCK5_RANGE_MASK,
+			.range_applied_by_vsel = true,
+			.ramp_delay_table = bd71828_ramp_delay,
+			.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
+			.ramp_reg = BD73800_REG_BUCK5_MODE,
+			.ramp_mask = BD73800_MASK_RAMP_DELAY,
+			.owner = THIS_MODULE,
+		},
+		.dvs = {
+			/*
+			 * We don't support setting the IDLE / SUSPEND voltages
+			 * for the BUCK 5 for now. Reason is that the pickable
+			 * range selector bit is common for all states (RUN,
+			 * SUSPEND and IDLE), and toggling it for one impacts
+			 * also others.
+			 * Furthermore, writing the BD73800 range selector does
+			 * not impact the RUN voltage until a new voltage value
+			 * is also written to the vsel register. Hence the
+			 * voltage change can be done without any 'intermediate
+			 * voltages', even when the range is changed when the
+			 * BUCK is enabled.
+			 * It, however, is not documented how the IDLE / SUSPEND
+			 * states work in this regard. I expect the full
+			 * combination of the range selector and vsel is taken
+			 * into account at the state change, no matter when they
+			 * have been written to.
+			 */
+			.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+				     ROHM_DVS_LEVEL_SUSPEND,
+			.run_reg = BD73800_REG_BUCK5_VOLT_RUN,
+			.run_mask = BD73800_MASK_VOLT,
+			.idle_on_mask = BD73800_MASK_IDLE_EN,
+			.suspend_on_mask = BD73800_MASK_SUSP_EN,
+		},
+
+	}, {
+		.desc = {
+			.name = "buck6",
+			.of_match = of_match_ptr("buck6"),
+			.regulators_node = of_match_ptr("regulators"),
+			.id = BD73800_BUCK6,
+			.ops = &bd73800_buck_ops,
+			.type = REGULATOR_VOLTAGE,
+			.linear_ranges = bd73800_buck67_volts,
+			.n_linear_ranges = ARRAY_SIZE(bd73800_buck67_volts),
+			.n_voltages = BD73800_NUM_VOLTS,
+			.enable_reg = BD73800_REG_BUCK6_ON,
+			.enable_mask = BD73800_MASK_RUN_EN,
+			.vsel_reg = BD73800_REG_BUCK6_VOLT_RUN,
+			.vsel_mask = BD73800_MASK_VOLT,
+			.ramp_delay_table = bd71828_ramp_delay,
+			.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
+			.ramp_reg = BD73800_REG_BUCK6_MODE,
+			.ramp_mask = BD73800_MASK_RAMP_DELAY,
+			.owner = THIS_MODULE,
+			.of_parse_cb = buck_set_hw_dvs_levels,
+		},
+		.dvs = {
+			.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+				     ROHM_DVS_LEVEL_SUSPEND,
+			.run_reg = BD73800_REG_BUCK6_VOLT_RUN,
+			.run_mask = BD73800_MASK_VOLT,
+			.idle_reg = BD73800_REG_BUCK6_VOLT_IDLE,
+			.idle_mask = BD73800_MASK_VOLT,
+			.idle_on_mask = BD73800_MASK_IDLE_EN,
+			.suspend_reg = BD73800_REG_BUCK6_VOLT_SUSP,
+			.suspend_mask = BD73800_MASK_VOLT,
+			.suspend_on_mask = BD73800_MASK_SUSP_EN,
+		},
+	}, {
+		.desc = {
+			.name = "buck7",
+			.of_match = of_match_ptr("buck7"),
+			.regulators_node = of_match_ptr("regulators"),
+			.id = BD73800_BUCK7,
+			.ops = &bd73800_buck_ops,
+			.type = REGULATOR_VOLTAGE,
+			.linear_ranges = bd73800_buck67_volts,
+			.n_linear_ranges = ARRAY_SIZE(bd73800_buck67_volts),
+			.n_voltages = BD73800_NUM_VOLTS,
+			.enable_reg = BD73800_REG_BUCK7_ON,
+			.enable_mask = BD73800_MASK_RUN_EN,
+			.vsel_reg = BD73800_REG_BUCK7_VOLT_RUN,
+			.vsel_mask = BD73800_MASK_VOLT,
+			.ramp_delay_table = bd71828_ramp_delay,
+			.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
+			.ramp_reg = BD73800_REG_BUCK7_MODE,
+			.ramp_mask = BD73800_MASK_RAMP_DELAY,
+			.owner = THIS_MODULE,
+			.of_parse_cb = buck_set_hw_dvs_levels,
+		},
+		.dvs = {
+			.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+				     ROHM_DVS_LEVEL_SUSPEND,
+			.run_reg = BD73800_REG_BUCK7_VOLT_RUN,
+			.run_mask = BD73800_MASK_VOLT,
+			.idle_reg = BD73800_REG_BUCK7_VOLT_IDLE,
+			.idle_mask = BD73800_MASK_VOLT,
+			.idle_on_mask = BD73800_MASK_IDLE_EN,
+			.suspend_reg = BD73800_REG_BUCK7_VOLT_SUSP,
+			.suspend_mask = BD73800_MASK_VOLT,
+			.suspend_on_mask = BD73800_MASK_SUSP_EN,
+		},
+	}, {
+		.desc = {
+			.name = "buck8",
+			.of_match = of_match_ptr("buck8"),
+			.regulators_node = of_match_ptr("regulators"),
+			.id = BD73800_BUCK8,
+			.ops = &bd73800_buck_ops,
+			.type = REGULATOR_VOLTAGE,
+			.linear_ranges = bd73800_buck12348_volts,
+			.n_linear_ranges = ARRAY_SIZE(bd73800_buck12348_volts),
+			.n_voltages = BD73800_NUM_VOLTS,
+			.enable_reg = BD73800_REG_BUCK8_ON,
+			.enable_mask = BD73800_MASK_RUN_EN,
+			.vsel_reg = BD73800_REG_BUCK8_VOLT_RUN,
+			.vsel_mask = BD73800_MASK_VOLT,
+			.ramp_delay_table = bd71828_ramp_delay,
+			.n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay),
+			.ramp_reg = BD73800_REG_BUCK8_MODE,
+			.ramp_mask = BD73800_MASK_RAMP_DELAY,
+			.owner = THIS_MODULE,
+			.of_parse_cb = buck_set_hw_dvs_levels,
+		},
+		.dvs = {
+			.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+				     ROHM_DVS_LEVEL_SUSPEND,
+			.run_reg = BD73800_REG_BUCK8_VOLT_RUN,
+			.run_mask = BD73800_MASK_VOLT,
+			.idle_reg = BD73800_REG_BUCK8_VOLT_IDLE,
+			.idle_mask = BD73800_MASK_VOLT,
+			.idle_on_mask = BD73800_MASK_IDLE_EN,
+			.suspend_reg = BD73800_REG_BUCK8_VOLT_SUSP,
+			.suspend_mask = BD73800_MASK_VOLT,
+			.suspend_on_mask = BD73800_MASK_SUSP_EN,
+		},
+	}, {
+		.desc = {
+			.name = "ldo1",
+			.of_match = of_match_ptr(LDO1_NODE_NAME),
+			.regulators_node = of_match_ptr("regulators"),
+			.id = BD73800_LDO1,
+			.ops = &bd73800_ldo_ops,
+			.type = REGULATOR_VOLTAGE,
+			.linear_ranges = bd73800_ldo13_low_volts,
+			.n_linear_ranges = ARRAY_SIZE(bd73800_ldo13_low_volts),
+			.n_voltages = BD73800_NUM_VOLTS,
+			.enable_reg = BD73800_REG_LDO1_ON,
+			.enable_mask = BD73800_MASK_RUN_EN,
+			.vsel_reg = BD73800_REG_LDO1_VOLT,
+			.vsel_mask = BD73800_MASK_VOLT,
+			.owner = THIS_MODULE,
+			.of_parse_cb = buck_set_hw_dvs_levels,
+		},
+		.dvs = {
+			/*
+			 * LDOs support only single voltage for all states.
+			 * Voltage can be individually enabled for each state
+			 * though. Allow setting enable/disable config by
+			 * setting the <state>_on_mask for all supported states.
+			 */
+			.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+				     ROHM_DVS_LEVEL_SUSPEND,
+			.run_reg = BD73800_REG_LDO1_VOLT,
+			.run_mask = BD73800_MASK_VOLT,
+			.idle_on_mask = BD73800_MASK_IDLE_EN,
+			.suspend_on_mask = BD73800_MASK_SUSP_EN,
+		},
+	}, {
+		.desc = {
+			.name = "ldo2",
+			.of_match = of_match_ptr("ldo2"),
+			.regulators_node = of_match_ptr("regulators"),
+			.id = BD73800_LDO2,
+			.ops = &bd73800_ldo_ops,
+			.type = REGULATOR_VOLTAGE,
+			.linear_ranges = bd73800_ldo24_volts,
+			.n_linear_ranges = ARRAY_SIZE(bd73800_ldo24_volts),
+			.n_voltages = BD73800_NUM_VOLTS,
+			.enable_reg = BD73800_REG_LDO2_ON,
+			.enable_mask = BD73800_MASK_RUN_EN,
+			.vsel_reg = BD73800_REG_LDO2_VOLT,
+			.vsel_mask = BD73800_MASK_VOLT,
+			.owner = THIS_MODULE,
+			.of_parse_cb = buck_set_hw_dvs_levels,
+		},
+		.dvs = {
+			.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+				     ROHM_DVS_LEVEL_SUSPEND,
+			.run_reg = BD73800_REG_LDO2_VOLT,
+			.run_mask = BD73800_MASK_VOLT,
+			.idle_on_mask = BD73800_MASK_IDLE_EN,
+			.suspend_on_mask = BD73800_MASK_SUSP_EN,
+		},
+	}, {
+		.desc = {
+			.name = "ldo3",
+			.of_match = of_match_ptr(LDO3_NODE_NAME),
+			.regulators_node = of_match_ptr("regulators"),
+			.id = BD73800_LDO3,
+			.ops = &bd73800_ldo_ops,
+			.type = REGULATOR_VOLTAGE,
+			.linear_ranges = bd73800_ldo13_low_volts,
+			.n_linear_ranges = ARRAY_SIZE(bd73800_ldo13_low_volts),
+			.n_voltages = BD73800_NUM_VOLTS,
+			.enable_reg = BD73800_REG_LDO3_ON,
+			.enable_mask = BD73800_MASK_RUN_EN,
+			.vsel_reg = BD73800_REG_LDO3_VOLT,
+			.vsel_mask = BD73800_MASK_VOLT,
+			.owner = THIS_MODULE,
+			.of_parse_cb = buck_set_hw_dvs_levels,
+		},
+		.dvs = {
+			.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+				     ROHM_DVS_LEVEL_SUSPEND,
+			.run_reg = BD73800_REG_LDO3_VOLT,
+			.run_mask = BD73800_MASK_VOLT,
+			.idle_on_mask = BD73800_MASK_IDLE_EN,
+			.suspend_on_mask = BD73800_MASK_SUSP_EN,
+		},
+	}, {
+		.desc = {
+			.name = "ldo4",
+			.of_match = of_match_ptr("ldo4"),
+			.regulators_node = of_match_ptr("regulators"),
+			.id = BD73800_LDO4,
+			.ops = &bd73800_ldo_ops,
+			.type = REGULATOR_VOLTAGE,
+			.linear_ranges = bd73800_ldo24_volts,
+			.n_linear_ranges = ARRAY_SIZE(bd73800_ldo24_volts),
+			.n_voltages = BD73800_NUM_VOLTS,
+			.enable_reg = BD73800_REG_LDO4_ON,
+			.enable_mask = BD73800_MASK_RUN_EN,
+			.vsel_reg = BD73800_REG_LDO4_VOLT,
+			.vsel_mask = BD73800_MASK_VOLT,
+			.owner = THIS_MODULE,
+			.of_parse_cb = buck_set_hw_dvs_levels,
+		},
+		.dvs = {
+			.level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE |
+				     ROHM_DVS_LEVEL_SUSPEND,
+			.run_reg = BD73800_REG_LDO4_VOLT,
+			.run_mask = BD73800_MASK_VOLT,
+			.idle_on_mask = BD73800_MASK_IDLE_EN,
+			.suspend_on_mask = BD73800_MASK_SUSP_EN,
+		},
+	},
+};
+
 static int bd72720_buck10_ldon_head_mode(struct device *dev,
 					 struct device_node *npreg,
 					 struct regmap *regmap,
@@ -1620,6 +2111,50 @@ static int bd72720_dt_parse(struct device *dev,
 	return bd72720_buck10_ldon_head_mode(dev, nproot, regmap, buck10_desc);
 }
 
+static int bd73800_check_ldo_otp_options(struct device *dev,
+					 struct bd71828_regulator_data *d,
+					 unsigned int num_reg_data)
+{
+	bool ldo1_use_high_range = false, ldo3_use_high_range = false;
+	struct device_node *nproot = dev->parent->of_node;
+	struct device_node *np;
+
+	/*
+	 * The code assumes regulator IDs to start from 0 and to match the
+	 * indexing of regulator data arrays. WARN if someone changes this.
+	 */
+	WARN_ON(d[BD73800_LDO1].desc.id != BD73800_LDO1);
+	WARN_ON(d[BD73800_LDO3].desc.id != BD73800_LDO3);
+
+	nproot = of_get_child_by_name(nproot, "regulators");
+	if (!nproot) {
+		dev_err(dev, "failed to find regulators node\n");
+		return -ENODEV;
+	}
+	for_each_child_of_node(nproot, np) {
+		if (of_node_name_eq(np, LDO1_NODE_NAME))
+			ldo1_use_high_range = of_property_read_bool(np,
+							"rohm,ldo-range-high");
+		if (of_node_name_eq(np, LDO3_NODE_NAME))
+			ldo3_use_high_range = of_property_read_bool(np,
+							"rohm,ldo-range-high");
+	}
+	of_node_put(nproot);
+
+	if (ldo1_use_high_range) {
+		d[BD73800_LDO1].desc.linear_ranges = bd73800_ldo13_high_volts;
+		d[BD73800_LDO1].desc.n_linear_ranges =
+					ARRAY_SIZE(bd73800_ldo13_high_volts);
+	}
+	if (ldo3_use_high_range) {
+		d[BD73800_LDO3].desc.linear_ranges = bd73800_ldo13_high_volts;
+		d[BD73800_LDO3].desc.n_linear_ranges =
+					ARRAY_SIZE(bd73800_ldo13_high_volts);
+	}
+
+	return 0;
+}
+
 static int bd71828_probe(struct platform_device *pdev)
 {
 	int i, j, ret, num_regulators;
@@ -1657,6 +2192,23 @@ static int bd71828_probe(struct platform_device *pdev)
 		num_regulators = ARRAY_SIZE(bd71828_rdata);
 
 		break;
+
+	case ROHM_CHIP_TYPE_BD73800:
+	{
+		rdata = devm_kmemdup(&pdev->dev, bd73800_rdata, sizeof(bd73800_rdata),
+			     GFP_KERNEL);
+		if (!rdata)
+			return -ENOMEM;
+
+		num_regulators = ARRAY_SIZE(bd73800_rdata);
+
+		ret = bd73800_check_ldo_otp_options(&pdev->dev, rdata,
+						    num_regulators);
+		if (ret)
+			return ret;
+
+		break;
+	}
 	default:
 		return dev_err_probe(&pdev->dev, -EINVAL,
 				     "Unsupported device\n");
@@ -1693,6 +2245,7 @@ static int bd71828_probe(struct platform_device *pdev)
 static const struct platform_device_id bd71828_pmic_id[] = {
 	{ .name = "bd71828-pmic", .driver_data = ROHM_CHIP_TYPE_BD71828 },
 	{ .name = "bd72720-pmic", .driver_data = ROHM_CHIP_TYPE_BD72720 },
+	{ .name = "bd73800-pmic", .driver_data = ROHM_CHIP_TYPE_BD73800 },
 	{ }
 };
 MODULE_DEVICE_TABLE(platform, bd71828_pmic_id);
-- 
2.54.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply related

* [PATCH 6/8] clk: bd718x7: Support ROHM BD73800
From: Matti Vaittinen @ 2026-07-01 12:43 UTC (permalink / raw)
  To: Matti Vaittinen, Matti Vaittinen, Matti Vaittinen
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Liam Girdwood, Mark Brown, Matti Vaittinen, Michael Turquette,
	Stephen Boyd, Brian Masney, Linus Walleij, Bartosz Golaszewski,
	Alexandre Belloni, devicetree, linux-kernel, linux-clk,
	linux-gpio, linux-rtc
In-Reply-To: <cover.1782909323.git.mazziesaccount@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1515 bytes --]

From: Matti Vaittinen <mazziesaccount@gmail.com>

The ROHM BD73800 PMIC has a 32.768 kHz clock gate. Add support for
controlling this clock.

NOTE: The CLKOUT pin can be muxed by an OTP option. On some OTP
configurations the CLKOUT is not outputting the clk signal.

Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
---
 drivers/clk/clk-bd718x7.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/clk/clk-bd718x7.c b/drivers/clk/clk-bd718x7.c
index 1cae974e6d1d..2dc6b8e46f18 100644
--- a/drivers/clk/clk-bd718x7.c
+++ b/drivers/clk/clk-bd718x7.c
@@ -21,6 +21,9 @@
 #define BD718XX_REG_OUT32K	0x2E
 /* BD72720 */
 #define BD72720_REG_OUT32K	0x9a
+/* BD73800 */
+#define BD73800_REG_OUT32K	0x50
+
 /*
  * BD71837, BD71847, and BD71828 all use bit [0] to clk output control
  */
@@ -123,6 +126,10 @@ static int bd71837_clk_probe(struct platform_device *pdev)
 		c->reg = BD72720_REG_OUT32K;
 		c->mask = CLK_OUT_EN_MASK;
 		break;
+	case ROHM_CHIP_TYPE_BD73800:
+		c->reg = BD73800_REG_OUT32K;
+		c->mask = CLK_OUT_EN_MASK;
+		break;
 	default:
 		dev_err(&pdev->dev, "Unknown clk chip\n");
 		return -EINVAL;
@@ -152,6 +159,7 @@ static const struct platform_device_id bd718x7_clk_id[] = {
 	{ "bd71828-clk", ROHM_CHIP_TYPE_BD71828 },
 	{ "bd71815-clk", ROHM_CHIP_TYPE_BD71815 },
 	{ "bd72720-clk", ROHM_CHIP_TYPE_BD72720 },
+	{ "bd73800-clk", ROHM_CHIP_TYPE_BD73800 },
 	{ },
 };
 MODULE_DEVICE_TABLE(platform, bd718x7_clk_id);
-- 
2.54.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply related

* [PATCH 7/8] gpio: bd73800: Support ROHM BD73800 PMIC GPIOs
From: Matti Vaittinen @ 2026-07-01 12:43 UTC (permalink / raw)
  To: Matti Vaittinen, Matti Vaittinen, Matti Vaittinen
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Liam Girdwood, Mark Brown, Matti Vaittinen, Michael Turquette,
	Stephen Boyd, Brian Masney, Linus Walleij, Bartosz Golaszewski,
	Alexandre Belloni, devicetree, linux-kernel, linux-clk,
	linux-gpio, linux-rtc
In-Reply-To: <cover.1782909323.git.mazziesaccount@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 10185 bytes --]

From: Matti Vaittinen <mazziesaccount@gmail.com>

The ROHM BD73800 PMIC has 4 pins (named GPIO1, CLKOUT, FAULT_B and
EXTEN_OUT) which might have been set to operate as a GPI or GPO when OTP
(One Time Programmable memory) is written at device manufacturing.
Support the GPI/GPO use-case via GPIO framework.

The default OTP for these pins is to not use any of them as GPI or GPO.
(The GPIO1 defaults as an ADC input regardless the naming). Hence the
driver assumes none of these pins is a GPI/GPO unless explicitly pointed
as GPI or GPO via device tree.

Furthermore, pin's direction can't be changed after OTP configuration is
done. Also the default drive type for a GPO (CMOS / Open Drain) is set
by the OTP configuration. The BD73800 has a set of undocumented test
registers which should allow changing the drive type. Access to the test
register area or the test registers aren't documented and so this driver
does not support configuring the drive type even though it might be
doable.

Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
---
 drivers/gpio/Kconfig        |  11 ++
 drivers/gpio/Makefile       |   1 +
 drivers/gpio/gpio-bd73800.c | 234 ++++++++++++++++++++++++++++++++++++
 3 files changed, 246 insertions(+)
 create mode 100644 drivers/gpio/gpio-bd73800.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 28cf6d2e83c2..09d87c3b756f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1363,6 +1363,17 @@ config GPIO_BD72720
 	  be configured to GPO on the ROHM PMIC. The pin configuration is done
 	  on OTP at manufacturing.
 
+config GPIO_BD73800
+	tristate "ROHM BD73800 GPIO support"
+	depends on MFD_ROHM_BD71828
+	help
+	  Support for GPIOs on ROHM BD73800 PMIC. There can be up to 4
+	  GPI or GPO pins available on the PMIC in total. The purpose of
+	  the pins is decided at the device manufacturing by OTP
+	  configuration and can't be reconfigured later. Enable this
+	  if your PMIC has pins set as GPIs or GPOs and if you wish to
+	  control the pins via the GPIO framework.
+
 config GPIO_BD9571MWV
 	tristate "ROHM BD9571 GPIO support"
 	depends on MFD_BD9571MWV
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 4d0e900402fc..3041c06aa933 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_GPIO_BCM_XGS_IPROC)	+= gpio-xgs-iproc.o
 obj-$(CONFIG_GPIO_BD71815)		+= gpio-bd71815.o
 obj-$(CONFIG_GPIO_BD71828)		+= gpio-bd71828.o
 obj-$(CONFIG_GPIO_BD72720)		+= gpio-bd72720.o
+obj-$(CONFIG_GPIO_BD73800)		+= gpio-bd73800.o
 obj-$(CONFIG_GPIO_BD9571MWV)		+= gpio-bd9571mwv.o
 obj-$(CONFIG_GPIO_BLZP1600)		+= gpio-blzp1600.o
 obj-$(CONFIG_GPIO_BRCMSTB)		+= gpio-brcmstb.o
diff --git a/drivers/gpio/gpio-bd73800.c b/drivers/gpio/gpio-bd73800.c
new file mode 100644
index 000000000000..3fe4b7f167b8
--- /dev/null
+++ b/drivers/gpio/gpio-bd73800.c
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Support to GPIOs on ROHM BD73800
+ * Copyright 2024 ROHM Semiconductors.
+ * Author: Matti Vaittinen <mazziesaccount@gmail.com>
+ */
+
+#include <linux/gpio/driver.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/rohm-bd73800.h>
+
+#define BD73800_GPIO_MAX_PINS 4
+/*
+ * The BD73800 has several "one time programmable" (OTP) configurations which
+ * can be set at manufacturing phase. Some of these options allow using
+ * individual pins as GPI or GPO (not both at the same time). The OTP
+ * configuration can't be read at run-time, so drivers rely on device-tree to
+ * advertise the OTP programmed in manufacturing.
+ *
+ * The pins which can be used as GPIO are:
+ * GPIO1, CLKOUT (GPIO2), FAULT_B, EXTEN_OUT.
+ *
+ * The OTP options 2 and 3 state for all the pins:
+ *  - OTP2: GPI (also IRQ source)
+ *  - OTP3: GPO (NOTE: This is actually 2 different OTP options. Either a
+ *    register controllable output or a power-sequence controlled output.
+ *    The "gpo" referred here means only the register controllable output.
+ *    The datasheet refers to this as: "<pin> output is controlled by
+ *    GPIO<N>_OUT or power on/off sequencer to control external VRs. ON/OFF
+ *    sequence timing is configurable."
+ *
+ * The data-sheet further says that the GPI/GPO is not a default OTP
+ * configuration for any of the pins. Hence the GPIO driver defaults to a pin
+ * not being a GPI or GPO, but requires the pin to be explicitly marked as a
+ * GPI or GPO in the device-tree.
+ *
+ * DT properties:
+ * "rohm,pin-gpio1", "rohm,pin-clkout", "rohm,pin-fault-b", "rohm,pin-exten"
+ * can be set to one of the values "gpi" or "gpo" to enable them to be used as
+ * GPIO.
+ */
+
+enum bd73800_gpio_state {
+	BD73800_PIN_UNKNOWN,
+	BD73800_PIN_GPI,
+	BD73800_PIN_GPO,
+};
+
+struct bd73800_gpio_pin_cfg {
+	enum bd73800_gpio_state state;
+	int mask; /* GPIO_OUT and INT_SRC have same bit offsets for GPIO */
+};
+
+struct bd73800_gpio {
+	/* chip.parent points the MFD which provides DT node and regmap */
+	struct gpio_chip chip;
+	struct bd73800_gpio_pin_cfg pin[BD73800_GPIO_MAX_PINS];
+	int num_pins;
+	/* dev points to the platform device for devm and prints */
+	struct device *dev;
+	struct regmap *regmap;
+};
+
+static int bd73800_gpio_get_pins(struct bd73800_gpio *g)
+{
+	static const char * const properties[] = {"rohm,pin-gpio1",
+		"rohm,pin-clkout", "rohm,pin-fault-b", "rohm,pin-exten"};
+	const char *val;
+	int i, ret;
+
+	for (i = 0; i < ARRAY_SIZE(properties); i++) {
+		ret = fwnode_property_read_string(dev_fwnode(g->dev->parent),
+						  properties[i], &val);
+
+		if (ret) {
+			if (ret == -EINVAL)
+				continue;
+
+			return dev_err_probe(g->dev, ret,
+					"pin %d (%s), bad configuration\n", i,
+					properties[i]);
+		}
+
+		if (strcmp(val, "gpi") == 0) {
+			g->pin[g->num_pins].state = BD73800_PIN_GPI;
+			g->pin[g->num_pins].mask = BIT(i);
+			g->num_pins++;
+		} else if (strcmp(val, "gpo") == 0) {
+			g->pin[g->num_pins].state = BD73800_PIN_GPO;
+			g->pin[g->num_pins].mask = BIT(i);
+			g->num_pins++;
+		}
+	}
+
+	return 0;
+}
+
+static int bd73800gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+	struct bd73800_gpio *bdgpio = gpiochip_get_data(chip);
+	struct bd73800_gpio_pin_cfg *pin = &bdgpio->pin[offset];
+	int ret, val;
+
+	/* Only pins configured as GPI via OTP can have their status read */
+	if (pin->state != BD73800_PIN_GPI) {
+		dev_dbg(bdgpio->dev, "pin %d (%x) not input. State %d\n",
+			offset, pin->mask, pin->state);
+		return -EINVAL;
+	}
+
+	ret = regmap_read(bdgpio->regmap, BD73800_REG_INT_5_SRC, &val);
+	if (ret)
+		return ret;
+
+	return val & pin->mask;
+}
+
+static int bd73800gpo_set(struct gpio_chip *chip, unsigned int offset,
+			  int value)
+{
+	struct bd73800_gpio *bdgpio = gpiochip_get_data(chip);
+	struct bd73800_gpio_pin_cfg *pin = &bdgpio->pin[offset];
+
+	if (pin->state != BD73800_PIN_GPO) {
+		dev_dbg(bdgpio->dev, "pin %d (%d) not output. State %d\n",
+			offset, pin->mask, pin->state);
+
+		return -EINVAL;
+	}
+
+	if (value)
+		return regmap_set_bits(bdgpio->regmap, BD73800_REG_GPO_OUT,
+				       pin->mask);
+
+	return regmap_clear_bits(bdgpio->regmap, BD73800_REG_GPO_OUT, pin->mask);
+}
+
+static int bd73800gpio_direction_get(struct gpio_chip *chip,
+				    unsigned int offset)
+{
+	struct bd73800_gpio *bdgpio = gpiochip_get_data(chip);
+
+	if (bdgpio->pin[offset].state == BD73800_PIN_GPO)
+		return GPIO_LINE_DIRECTION_OUT;
+
+	return GPIO_LINE_DIRECTION_IN;
+}
+
+/*
+ * Template for GPIO chip. The BD73800 GPO supports both CMOS and open drain
+ * configurations. The default however depends on the OTP. The runtime config
+ * can be done via undocumented test registers - but at the moment there is no
+ * support for this.
+ *
+ * NOTE: When the BD73800 GPIO pins are used as IRQ source, the users are
+ * expected to request them directly from the regmap_irq IRQ-chip (implemented
+ * in the MFD driver). This way we don't need to populate another IRQ-chip
+ * here.
+ */
+static const struct gpio_chip bd73800gpio_chip = {
+	.label			= "bd73800",
+	.owner			= THIS_MODULE,
+	.get			= bd73800gpio_get,
+	.get_direction		= bd73800gpio_direction_get,
+	.set			= bd73800gpo_set,
+	.can_sleep		= true,
+};
+
+static int gpo_bd73800_probe(struct platform_device *pdev)
+{
+	struct bd73800_gpio *g;
+	struct device *parent, *dev;
+	int ret;
+
+	/*
+	 * Bind devm lifetime to this platform device => use dev for devm.
+	 * also the prints should originate from this device.
+	 */
+	dev = &pdev->dev;
+	/* The device-tree and regmap come from MFD => use parent for that */
+	parent = dev->parent;
+
+	g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL);
+	if (!g)
+		return -ENOMEM;
+
+	g->chip = bd73800gpio_chip;
+	g->chip.base = -1;
+	g->chip.parent = parent;
+	g->regmap = dev_get_regmap(parent, NULL);
+	g->dev = dev;
+
+	ret = bd73800_gpio_get_pins(g);
+	if (ret)
+		return ret;
+
+	if (!g->num_pins) {
+		/*
+		 * The BD73800 may or may not have pins allocated for GPIO
+		 * depending on the OTP used at manufacturing. Free the memory
+		 * and go out if there is no pins as then we have nothing to do
+		 */
+		dev_dbg(dev, "no GPIO pins\n");
+		devm_kfree(dev, g);
+		return 0;
+	}
+	g->chip.ngpio = g->num_pins;
+
+	return devm_gpiochip_add_data(dev, &g->chip, g);
+}
+
+static const struct platform_device_id bd73800_gpio_id[] = {
+	{ "bd73800-gpio" },
+	{ },
+};
+MODULE_DEVICE_TABLE(platform, bd73800_gpio_id);
+
+static struct platform_driver gpo_bd73800_driver = {
+	.driver = {
+		.name = "bd73800-gpio",
+		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
+	},
+	.probe = gpo_bd73800_probe,
+	.id_table = bd73800_gpio_id,
+};
+module_platform_driver(gpo_bd73800_driver);
+
+MODULE_AUTHOR("Matti Vaittinen <mazziesaccount@gmail.com>");
+MODULE_DESCRIPTION("GPIO interface for BD73800");
+MODULE_LICENSE("GPL");
-- 
2.54.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply related

* [PATCH 8/8] MAINTAINERS: Add ROHM BD73800 PMIC files
From: Matti Vaittinen @ 2026-07-01 12:43 UTC (permalink / raw)
  To: Matti Vaittinen, Matti Vaittinen, Matti Vaittinen
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Liam Girdwood, Mark Brown, Matti Vaittinen, Michael Turquette,
	Stephen Boyd, Brian Masney, Linus Walleij, Bartosz Golaszewski,
	Alexandre Belloni, devicetree, linux-kernel, linux-clk,
	linux-gpio, linux-rtc
In-Reply-To: <cover.1782909323.git.mazziesaccount@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 995 bytes --]

From: Matti Vaittinen <mazziesaccount@gmail.com>

Add the undersigned as a maintainer for the ROHM BD73800 PMIC related
files.

Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
---
 MAINTAINERS | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 15011f5752a9..92795b08bc52 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -23539,6 +23539,7 @@ F:	drivers/clk/clk-bd718x7.c
 F:	drivers/gpio/gpio-bd71815.c
 F:	drivers/gpio/gpio-bd71828.c
 F:	drivers/gpio/gpio-bd72720.c
+F:	drivers/gpio/gpio-bd73800.c
 F:	drivers/mfd/rohm-bd71828.c
 F:	drivers/mfd/rohm-bd718x7.c
 F:	drivers/mfd/rohm-bd9576.c
@@ -23556,6 +23557,7 @@ F:	include/linux/mfd/rohm-bd71815.h
 F:	include/linux/mfd/rohm-bd71828.h
 F:	include/linux/mfd/rohm-bd718x7.h
 F:	include/linux/mfd/rohm-bd72720.h
+F:	include/linux/mfd/rohm-bd73800.h
 F:	include/linux/mfd/rohm-bd957x.h
 F:	include/linux/mfd/rohm-bd96801.h
 F:	include/linux/mfd/rohm-bd96802.h
-- 
2.54.0


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply related

* Re: [PATCH 4/8] rtc: bd70528: Support RTC on ROHM BD73800
From: Alexandre Belloni @ 2026-07-01 12:55 UTC (permalink / raw)
  To: Matti Vaittinen
  Cc: Matti Vaittinen, Matti Vaittinen, Lee Jones, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Liam Girdwood, Mark Brown,
	Michael Turquette, Stephen Boyd, Brian Masney, Linus Walleij,
	Bartosz Golaszewski, devicetree, linux-kernel, linux-clk,
	linux-gpio, linux-rtc
In-Reply-To: <d9f5b1c6b165699627c7cf127a7ec64d28e15cca.1782909323.git.mazziesaccount@gmail.com>

On 01/07/2026 15:42:20+0300, Matti Vaittinen wrote:
> From: Matti Vaittinen <mazziesaccount@gmail.com>
> 
> BD73800 contains similar RTC block as BD71828 and BD71815. Only the address
> offsets seem different. Support also BD73800 RTC using the rtc-bd70528.
> 
> Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com>

> ---
>  drivers/rtc/rtc-bd70528.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/rtc/rtc-bd70528.c b/drivers/rtc/rtc-bd70528.c
> index 482810b61495..fd415e327ea6 100644
> --- a/drivers/rtc/rtc-bd70528.c
> +++ b/drivers/rtc/rtc-bd70528.c
> @@ -8,6 +8,7 @@
>  #include <linux/mfd/rohm-bd71815.h>
>  #include <linux/mfd/rohm-bd71828.h>
>  #include <linux/mfd/rohm-bd72720.h>
> +#include <linux/mfd/rohm-bd73800.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
>  #include <linux/platform_device.h>
> @@ -284,6 +285,12 @@ static int bd70528_probe(struct platform_device *pdev)
>  		bd_rtc->bd718xx_alm_block_start = BD72720_REG_RTC_ALM_START;
>  		hour_reg = BD72720_REG_RTC_HOUR;
>  		break;
> +	case ROHM_CHIP_TYPE_BD73800:
> +		bd_rtc->reg_time_start = BD73800_REG_RTC_START;
> +		bd_rtc->bd718xx_alm_block_start = BD73800_REG_RTC_ALM_START;
> +		hour_reg = BD73800_REG_RTC_HOUR;
> +		break;
> +
>  	default:
>  		dev_err(&pdev->dev, "Unknown chip\n");
>  		return -ENOENT;
> @@ -344,6 +351,7 @@ static const struct platform_device_id bd718x7_rtc_id[] = {
>  	{ .name = "bd71828-rtc", .driver_data = ROHM_CHIP_TYPE_BD71828 },
>  	{ .name = "bd71815-rtc", .driver_data = ROHM_CHIP_TYPE_BD71815 },
>  	{ .name = "bd72720-rtc", .driver_data = ROHM_CHIP_TYPE_BD72720 },
> +	{ .name = "bd73800-rtc", .driver_data = ROHM_CHIP_TYPE_BD73800 },
>  	{ }
>  };
>  MODULE_DEVICE_TABLE(platform, bd718x7_rtc_id);
> -- 
> 2.54.0
> 



-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply

* Re: [PATCH 5/8] regulator: bd71828: Support ROHM BD73800
From: Mark Brown @ 2026-07-01 13:01 UTC (permalink / raw)
  To: Matti Vaittinen
  Cc: Matti Vaittinen, Matti Vaittinen, Lee Jones, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Liam Girdwood,
	Michael Turquette, Stephen Boyd, Brian Masney, Linus Walleij,
	Bartosz Golaszewski, Alexandre Belloni, devicetree, linux-kernel,
	linux-clk, linux-gpio, linux-rtc
In-Reply-To: <1d00359236272fd1fab0dfbcb9119d2f91aa0d23.1782909323.git.mazziesaccount@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1138 bytes --]

On Wed, Jul 01, 2026 at 03:42:35PM +0300, Matti Vaittinen wrote:
> From: Matti Vaittinen <mazziesaccount@gmail.com>

> +	nproot = of_get_child_by_name(nproot, "regulators");
> +	if (!nproot) {
> +		dev_err(dev, "failed to find regulators node\n");
> +		return -ENODEV;
> +	}
> +	for_each_child_of_node(nproot, np) {
> +		if (of_node_name_eq(np, LDO1_NODE_NAME))
> +			ldo1_use_high_range = of_property_read_bool(np,
> +							"rohm,ldo-range-high");
> +		if (of_node_name_eq(np, LDO3_NODE_NAME))
> +			ldo3_use_high_range = of_property_read_bool(np,
> +							"rohm,ldo-range-high");
> +	}

Why do we iterate over all nodes rather than doing additional
of_get_child_by_name()s?

> +	if (ldo1_use_high_range) {
> +		d[BD73800_LDO1].desc.linear_ranges = bd73800_ldo13_high_volts;
> +		d[BD73800_LDO1].desc.n_linear_ranges =
> +					ARRAY_SIZE(bd73800_ldo13_high_volts);
> +	}
> +	if (ldo3_use_high_range) {
> +		d[BD73800_LDO3].desc.linear_ranges = bd73800_ldo13_high_volts;
> +		d[BD73800_LDO3].desc.n_linear_ranges =
> +					ARRAY_SIZE(bd73800_ldo13_high_volts);
> +	}

You could just do these updates without the intermediate variables.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH v2 4/9] MIPS: TXX9: rbtx4927: Use GPIO lookup table for TXx9 LEDs
From: Philippe Mathieu-Daudé @ 2026-07-01 14:27 UTC (permalink / raw)
  To: Geert Uytterhoeven, Thomas Bogendoerfer, Linus Walleij,
	Bartosz Golaszewski, Arnd Bergmann
  Cc: linux-mips, linux-gpio, linux-kernel, Bartosz Golaszewski
In-Reply-To: <92613064355ad1228b0f43031fc6c5d781e7d4f6.1782900491.git.geert@linux-m68k.org>

On 1/7/26 12:11, Geert Uytterhoeven wrote:
> Convert TXx9 LED description from legacy GPIO numbers to GPIO
> descriptors using a GPIO lookup table.
> 
> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
> Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> Reviewed-by: Linus Walleij <linusw@kernel.org>
> ---
> v2:
>    - Add Reviewed-by,
>    - Return early on platform_device_add() failure.
> ---
>   arch/mips/txx9/rbtx4927/setup.c | 19 ++++++++++++++++---
>   1 file changed, 16 insertions(+), 3 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>

^ permalink raw reply

* Re: [PATCH v2 6/9] MIPS: TXX9: Use GPIO lookup table for iocled LEDs
From: Philippe Mathieu-Daudé @ 2026-07-01 14:29 UTC (permalink / raw)
  To: Geert Uytterhoeven, Thomas Bogendoerfer, Linus Walleij,
	Bartosz Golaszewski, Arnd Bergmann
  Cc: linux-mips, linux-gpio, linux-kernel, Bartosz Golaszewski
In-Reply-To: <68c915761e5234ad64cd62024fbac39ab097494d.1782900491.git.geert@linux-m68k.org>

On 1/7/26 12:11, Geert Uytterhoeven wrote:
> Convert iocled LED description from legacy GPIO numbers to GPIO
> descriptors using a GPIO lookup table.
> 
> For now, just ignore the "lowactive" parameter, and force
> GPIO_ACTIVE_LOW, as that is what the sole caller wants.
> 
> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
> Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> Reviewed-by: Linus Walleij <linusw@kernel.org>
> ---
> v2:
>    - Add Reviewed-by.
> ---
>   arch/mips/txx9/generic/setup.c | 14 ++++++++++++--
>   1 file changed, 12 insertions(+), 2 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>

^ permalink raw reply

* Re: [PATCH 1/8] dt-bindings: regulator: ROHM BD73800 regulators
From: Rob Herring (Arm) @ 2026-07-01 15:39 UTC (permalink / raw)
  To: Matti Vaittinen
  Cc: devicetree, linux-kernel, Mark Brown, Brian Masney,
	Michael Turquette, linux-clk, Stephen Boyd, Bartosz Golaszewski,
	Conor Dooley, Linus Walleij, linux-rtc, Krzysztof Kozlowski,
	Alexandre Belloni, Matti Vaittinen, linux-gpio, Matti Vaittinen,
	Lee Jones, Liam Girdwood
In-Reply-To: <67b42b5363533f11c22a6421417c3345f9872aec.1782909323.git.mazziesaccount@gmail.com>


On Wed, 01 Jul 2026 15:41:11 +0300, Matti Vaittinen wrote:
> From: Matti Vaittinen <mazziesaccount@gmail.com>
> 
> Add bindings for the BUCKs and LDOs on ROHM BD73800. The PMIC state
> specific voltages can be set in same fashion as with a few other ROHM
> PMICs (for example with BD718[15,28,37,47,50,79]). Same properties are
> recycled :)
> 
> The LDOs 1 and 4 can use different voltage ranges depending on the OTP
> configuration.
> 
> Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
> ---
>  .../regulator/rohm,bd73800-regulator.yaml     | 119 ++++++++++++++++++
>  1 file changed, 119 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/regulator/rohm,bd73800-regulator.yaml
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:


doc reference errors (make refcheckdocs):
Warning: Documentation/devicetree/bindings/regulator/rohm,bd73800-regulator.yaml references a file that doesn't exist: Documentation/devicetree/bindings/mfd/rohm,bd73800-pmic.yaml
Documentation/devicetree/bindings/regulator/rohm,bd73800-regulator.yaml: Documentation/devicetree/bindings/mfd/rohm,bd73800-pmic.yaml

See https://patchwork.kernel.org/project/devicetree/patch/67b42b5363533f11c22a6421417c3345f9872aec.1782909323.git.mazziesaccount@gmail.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.


^ permalink raw reply

* [PATCH 0/5] gpio: nomadik: silence boot log
From: Théo Lebrun @ 2026-07-01 16:56 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski, Philipp Zabel
  Cc: Vladimir Kondratiev, Gregory CLEMENT, Benoît Monin,
	Tawfik Bayouk, Thomas Petazzoni, linux-arm-kernel, linux-gpio,
	linux-kernel, Théo Lebrun

Currently, on EyeQ5, we might get those error logs:

[    0.544230] nomadik-gpio 1400000.gpio: failed getting reset control: -EPROBE_DEFER
[    0.544274] nomadik-gpio 1400000.gpio: could not populate nmk chip struct

Then on successful probe we get:

[    0.976838] nomadik-gpio 1400000.gpio: chip registered

First line is because we don't use the appropriate dev_err_probe()
helper. Second line is redundant to populate chip dev_err() calls and
shall be dropped. Third line should be dropped.

That's done in patches 3+4+5. Patches 1+2 prepare the terrain.

Have a nice day,
Théo

Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
---
Théo Lebrun (5):
      gpio: nomadik: convert nmk_gpio_populate_chip() to goto cleanup
      gpio: nomadik: add missing dev_err() call on chip populate failure
      gpio: nomadik: drop duplicate probe error line
      gpio: nomadik: use dev_err_probe()
      gpio: nomadik: drop "chip registered" log on probe success

 drivers/gpio/gpio-nomadik.c | 64 ++++++++++++++++++++++-----------------------
 1 file changed, 32 insertions(+), 32 deletions(-)
---
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
change-id: 20260701-gpio-nomadik-silent-678abaee1e3e

Best regards,
--  
Théo Lebrun <theo.lebrun@bootlin.com>


^ permalink raw reply


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