* [PATCH 0/7] mailbox: Improve the mbox core then introduce the goog-mba driver @ 2026-07-14 22:21 Douglas Anderson 2026-07-14 22:21 ` [PATCH 6/7] dt-bindings: mailbox: goog-mba: Add goog-mba mailbox bindings Douglas Anderson 2026-07-14 22:21 ` [PATCH 7/7] mailbox: goog-mba: Introduce the goog-mba mailbox driver Douglas Anderson 0 siblings, 2 replies; 10+ messages in thread From: Douglas Anderson @ 2026-07-14 22:21 UTC (permalink / raw) To: Jassi Brar Cc: Joonwon Kang, Subhash Jadavani, Tudor Ambarus, Lucas Wei, Brian Norris, Peter Griffin, André Draszik, Douglas Anderson, Conor Dooley, Krzysztof Kozlowski, Rob Herring, devicetree, linux-arm-kernel, linux-kernel, linux-samsung-soc The goal of this series is to land support for the goog-mba (MailBox Array) IP block that's present in Pixel 10 phones. As can be seen in the device-tree bindings for the goog-mba IP block, the mailbox IP block in Pixel 10 phones is fairly sophisticated. Notably: * It has hardware features that support queuing, meaning that more than one mailbox message can be pending at a time. * The "channels" in a given mailbox array aren't homogeneous. Each "channel" in the mailbox array can have a different amount of memory for messages. Really, the "channels" in a mailbox are considered to be full single-channel mailboxes and a grouping of mailboxes is considered a "mailbox array" (hence the IP block being named "mba") In order to cleanly support some of the sophisticated goog-mba features, improvements are made to the mailbox core. Specifically, support for mailbox controllers that can queue is added and also support for mailbox drivers that have more than one sub-node is added. This is a fairly big rewrite from the downstream MBA driver shipping on Pixel 10 phones, which awkwardly makes due without the improvements to the mailbox core. It has been lightly tested both by porting it to an experimental downstream tree based on 7.1 and also by running it directly upstream against a stripped down Pixel 10 device tree. Douglas Anderson (7): dt-bindings: mailbox: Don't require #mbox-cells to be 1 mailbox: Allow #mbox-cells = <0> without specifying a custom xlate mailbox: Find a matching mailbox by fwnode rather than device mailbox: Simplify circular queue math with mod arithmetic mailbox: Add support for mailbox controllers that can queue dt-bindings: mailbox: goog-mba: Add goog-mba mailbox bindings mailbox: goog-mba: Introduce the goog-mba mailbox driver .../bindings/mailbox/google,mba.yaml | 216 +++++++ .../devicetree/bindings/mailbox/mailbox.txt | 6 +- MAINTAINERS | 8 + drivers/mailbox/Kconfig | 8 + drivers/mailbox/Makefile | 2 + drivers/mailbox/goog-mba-priv.h | 108 ++++ drivers/mailbox/goog-mba-trace.h | 183 ++++++ drivers/mailbox/goog-mba.c | 567 ++++++++++++++++++ drivers/mailbox/mailbox.c | 84 ++- include/linux/mailbox/goog-mba-message.h | 38 ++ include/linux/mailbox_controller.h | 15 +- 11 files changed, 1209 insertions(+), 26 deletions(-) create mode 100644 Documentation/devicetree/bindings/mailbox/google,mba.yaml create mode 100644 drivers/mailbox/goog-mba-priv.h create mode 100644 drivers/mailbox/goog-mba-trace.h create mode 100644 drivers/mailbox/goog-mba.c create mode 100644 include/linux/mailbox/goog-mba-message.h -- 2.55.0.141.g00534a21ce-goog ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 6/7] dt-bindings: mailbox: goog-mba: Add goog-mba mailbox bindings 2026-07-14 22:21 [PATCH 0/7] mailbox: Improve the mbox core then introduce the goog-mba driver Douglas Anderson @ 2026-07-14 22:21 ` Douglas Anderson 2026-07-15 4:51 ` Krzysztof Kozlowski 2026-07-14 22:21 ` [PATCH 7/7] mailbox: goog-mba: Introduce the goog-mba mailbox driver Douglas Anderson 1 sibling, 1 reply; 10+ messages in thread From: Douglas Anderson @ 2026-07-14 22:21 UTC (permalink / raw) To: Jassi Brar Cc: Joonwon Kang, Subhash Jadavani, Tudor Ambarus, Lucas Wei, Brian Norris, Peter Griffin, André Draszik, Douglas Anderson, Conor Dooley, Krzysztof Kozlowski, Rob Herring, devicetree, linux-arm-kernel, linux-kernel, linux-samsung-soc Introduce bindings for the MailBox Array IP block present in Laguna SoCs (AKA "lga", AKA "Google Tensor G5"). Signed-off-by: Douglas Anderson <dianders@chromium.org> --- .../bindings/mailbox/google,mba.yaml | 216 ++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 Documentation/devicetree/bindings/mailbox/google,mba.yaml diff --git a/Documentation/devicetree/bindings/mailbox/google,mba.yaml b/Documentation/devicetree/bindings/mailbox/google,mba.yaml new file mode 100644 index 000000000000..6c4505a369e2 --- /dev/null +++ b/Documentation/devicetree/bindings/mailbox/google,mba.yaml @@ -0,0 +1,216 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright 2025 Google LLC +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mailbox/google,mba.yaml# +$schema: http://devicetree.org/meta-schemas/base.yaml# + +title: Google MailBox Array + +maintainers: + - Douglas Anderson <dianders@chromium.org> + +description: | + The Google MailBox Array (MBA) is an IP block in Google-designed SoCs + starting in Laguna (AKA "lga", AKA Google Tensor G5). In a typical SoC + that includes this IP block, there are a number of instances of the MBA + controller with each instance having slightly different hardware + parameters and intended for communication with a different remote + processor. + + An MBA instance has a "host" that is defined as the processor "providing" + a "service". This is typically not the main Application Processor (AP) but + is instead some specialized co-processor in the SoC like the Central Power + Manager (CPM). A processor (like the AP) talking to the "host" of the MBA + is a "client" of the MBA. A given MBA instance only ever has one host, but + it may have several clients. For instance, the CPM (an MBA "host") may need + to send/receive mailbox messages not just from the AP but from other + processors in the SoC and each of these other processors can be "clients" + of the same MBA. + + The "host" of an MBA instance has full access to everything in the MBA + instance. It can access its own private set of "host" MBA registers, the + "global" MBA registers (if they exist), and all of the "client" MBA + registers. + + A "client" of an MBA instance has access to the "global" MBA registers (if + they exist) and one or more sets of "client" MBA registers. + + These bindings are focused on describing the MBA from the point of view of + a single client. + + As per above, a client may have access to several sets of MBA "client" + registers. Each set of "client" registers represents a logical mailbox + "channel". However, because each channel may have different configuration + parameters and a mailbox "channel" in typical usage means one of a number + of identical channels, each channel in a Google MailBox Array is typically + referred to as a full "mailbox" and the whole collection of mailboxes as + the "mailbox array". + + Mailboxes in an MBA instance have these features: + * 1 to 256 32-bit words of shared memory. + * The ability for the client to ring the main doorbell of the host and be + notified when the host Acks the doorbell. + * The ability for the host to ring the main doorbell of the client and be + notified when the client Acks the doorbell. + + Some mailboxes may also have the ability to have counted doorbells. This + means that the receiver of the doorbell can tell how many times it rung. + This is intended for implementing "queued" mailboxes. See below. + + The MBA hardware doesn't have any specific directionality. That is to + say, both the host and the client have full read and write access to + their shared memory. All mailbox instances have doorbells going both from + the client to the host as well as the host to the client. + + The mailboxes can only be used for communication if the host and client + both agree on conventions. These conventions are described in the + device tree as they describe how the remote firmware is expecting to + communicate. + + Current known in-use conventions: + 1. An RX mailbox with payloads that are of a well-defined size. + On mailboxes of this type, the host is the only one to write shared + memory. After placing a fixed-size message in shared memory, it rings + the main doorbell of the client. The client reads the message and Acks + the doorbell. + 2. A TX mailbox with payloads that could vary in size. + On mailboxes of this type, the mailbox client is the only one to write + shared memory. The client always writes a payload to the start of shared + memory and rings the main host doorbell. The client then looks for the + host to Ack the doorbell. The clients of the mailbox have ways to know + the size of any given message. + 3. A half-duplex TX/RX mailbox. This is a mailbox that can switch between + convention #1 and #2 above. Since both sides write data to the start of + shared memory, the two sides must have some convention to know whose + turn it is to send a message. + 4. A "queued" RX mailbox with a payload of a well-defined size. + This type of mailbox is only possible if the MBA instance can count + doorbells. On mailboxes of this type, the host is the only one to write + shared memory. When the client doorbell rings, the client reads a + fixed-size from the next "slot" in shared memory and then updates its + internal state. The shared memory is treated as a circular queue. + 5. A "queued" TX mailbox with a payload of a well-defined size. + This type of mailbox is only possible if the MBA instance can count + doorbells. On mailboxes of this type, the mailbox client is the only one + to write shared memory. The shared memory is treated as a circular queue. + The client writes a fixed-sized payload to the next "slot" in the shared + memory (where the slot size is determined by the client's first transfer), + updates its internal state, and rings the host doorbell. The client can + keep writing more messages as long as the circular queue isn't full. The + client gets an interrupt when the host Acks a doorbell and can tell how + many doorbells still haven't been Acked. + + Conventions will be supported with a small number of properties specified + for each mailbox. + +properties: + compatible: + items: + - enum: + - google,lga-mailbox-array + - const: google,mailbox-array + + reg: + minItems: 1 + items: + - description: Host registers (not accessible to client) + - description: Global registers (not present on newer IP blocks) + + ranges: true + + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + +patternProperties: + "^mailbox@[0-9a-f]+$": + type: object + description: + Each sub-node is a single-channel mailbox. + + properties: + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + "#mbox-cells": + const: 0 + + google,rx-payload-words: + $ref: /schemas/types.yaml#/definitions/uint32 + maximum: 256 + default: 0 + description: + The number of 32-bit words in each mailbox message from the remote + processor. May be 0 for doorbell-only. If not specified this is + assumed to be 0. + + google,mba-queue-mode: + type: boolean + description: + The remote processor is expecting the shared memory to be treated + as a circular queue and that there may be several outstanding + messages at once. Only usable on instances with counted doorbell + interrupts. + + required: + - reg + - interrupts + - "#mbox-cells" + + additionalProperties: false + +required: + - compatible + - ranges + - reg + - "#address-cells" + - "#size-cells" + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/interrupt-controller/irq.h> + + soc { + #address-cells = <2>; + #size-cells = <2>; + + cpm_ap_ns_mba: mailbox-array@5240000 { + compatible = "google,lga-mailbox-array", "google,mailbox-array"; + reg = <0x0 0x05240000 0x0 0x00010000>, + <0x0 0x05250000 0x0 0x00010000>; + ranges = <0x0 0x0 0x05260000 0x00020000>; + + #address-cells = <1>; + #size-cells = <1>; + + cpm_ap_ns_req_mba_client_0: mailbox@0 { + reg = <0x0000 0x1000>; + interrupts = <GIC_SPI 250 IRQ_TYPE_LEVEL_HIGH 0>; + + #mbox-cells = <0>; + + google,mba-queue-mode; + }; + + cpm_ap_ns_resp_mba_client_1: mailbox@1000 { + reg = <0x1000 0x1000>; + interrupts = <GIC_SPI 251 IRQ_TYPE_LEVEL_HIGH 0>; + + #mbox-cells = <0>; + + google,rx-payload-words = <4>; + google,mba-queue-mode; + }; + }; + }; + +... -- 2.55.0.141.g00534a21ce-goog ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 6/7] dt-bindings: mailbox: goog-mba: Add goog-mba mailbox bindings 2026-07-14 22:21 ` [PATCH 6/7] dt-bindings: mailbox: goog-mba: Add goog-mba mailbox bindings Douglas Anderson @ 2026-07-15 4:51 ` Krzysztof Kozlowski 2026-07-15 16:49 ` Doug Anderson 0 siblings, 1 reply; 10+ messages in thread From: Krzysztof Kozlowski @ 2026-07-15 4:51 UTC (permalink / raw) To: Douglas Anderson, Jassi Brar Cc: Joonwon Kang, Subhash Jadavani, Tudor Ambarus, Lucas Wei, Brian Norris, Peter Griffin, André Draszik, Conor Dooley, Krzysztof Kozlowski, Rob Herring, devicetree, linux-arm-kernel, linux-kernel, linux-samsung-soc On 15/07/2026 00:21, Douglas Anderson wrote: > Introduce bindings for the MailBox Array IP block present in Laguna > SoCs (AKA "lga", AKA "Google Tensor G5"). > > Signed-off-by: Douglas Anderson <dianders@chromium.org> > --- > > .../bindings/mailbox/google,mba.yaml | 216 ++++++++++++++++++ Filename must match compatible. > 1 file changed, 216 insertions(+) > create mode 100644 Documentation/devicetree/bindings/mailbox/google,mba.yaml > > diff --git a/Documentation/devicetree/bindings/mailbox/google,mba.yaml b/Documentation/devicetree/bindings/mailbox/google,mba.yaml > new file mode 100644 > index 000000000000..6c4505a369e2 > --- /dev/null > +++ b/Documentation/devicetree/bindings/mailbox/google,mba.yaml > @@ -0,0 +1,216 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +# Copyright 2025 Google LLC > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/mailbox/google,mba.yaml# > +$schema: http://devicetree.org/meta-schemas/base.yaml# > + > +title: Google MailBox Array > + > +maintainers: > + - Douglas Anderson <dianders@chromium.org> > + > +description: | > + The Google MailBox Array (MBA) is an IP block in Google-designed SoCs > + starting in Laguna (AKA "lga", AKA Google Tensor G5). In a typical SoC > + that includes this IP block, there are a number of instances of the MBA > + controller with each instance having slightly different hardware > + parameters and intended for communication with a different remote > + processor. > + > + An MBA instance has a "host" that is defined as the processor "providing" > + a "service". This is typically not the main Application Processor (AP) but > + is instead some specialized co-processor in the SoC like the Central Power > + Manager (CPM). A processor (like the AP) talking to the "host" of the MBA > + is a "client" of the MBA. A given MBA instance only ever has one host, but > + it may have several clients. For instance, the CPM (an MBA "host") may need > + to send/receive mailbox messages not just from the AP but from other > + processors in the SoC and each of these other processors can be "clients" > + of the same MBA. > + > + The "host" of an MBA instance has full access to everything in the MBA > + instance. It can access its own private set of "host" MBA registers, the > + "global" MBA registers (if they exist), and all of the "client" MBA > + registers. > + > + A "client" of an MBA instance has access to the "global" MBA registers (if > + they exist) and one or more sets of "client" MBA registers. > + > + These bindings are focused on describing the MBA from the point of view of > + a single client. > + > + As per above, a client may have access to several sets of MBA "client" > + registers. Each set of "client" registers represents a logical mailbox > + "channel". However, because each channel may have different configuration > + parameters and a mailbox "channel" in typical usage means one of a number > + of identical channels, each channel in a Google MailBox Array is typically > + referred to as a full "mailbox" and the whole collection of mailboxes as > + the "mailbox array". > + > + Mailboxes in an MBA instance have these features: > + * 1 to 256 32-bit words of shared memory. > + * The ability for the client to ring the main doorbell of the host and be > + notified when the host Acks the doorbell. > + * The ability for the host to ring the main doorbell of the client and be > + notified when the client Acks the doorbell. > + > + Some mailboxes may also have the ability to have counted doorbells. This > + means that the receiver of the doorbell can tell how many times it rung. > + This is intended for implementing "queued" mailboxes. See below. > + > + The MBA hardware doesn't have any specific directionality. That is to > + say, both the host and the client have full read and write access to > + their shared memory. All mailbox instances have doorbells going both from > + the client to the host as well as the host to the client. > + > + The mailboxes can only be used for communication if the host and client > + both agree on conventions. These conventions are described in the > + device tree as they describe how the remote firmware is expecting to > + communicate. > + > + Current known in-use conventions: > + 1. An RX mailbox with payloads that are of a well-defined size. > + On mailboxes of this type, the host is the only one to write shared > + memory. After placing a fixed-size message in shared memory, it rings > + the main doorbell of the client. The client reads the message and Acks > + the doorbell. > + 2. A TX mailbox with payloads that could vary in size. > + On mailboxes of this type, the mailbox client is the only one to write > + shared memory. The client always writes a payload to the start of shared > + memory and rings the main host doorbell. The client then looks for the > + host to Ack the doorbell. The clients of the mailbox have ways to know > + the size of any given message. > + 3. A half-duplex TX/RX mailbox. This is a mailbox that can switch between > + convention #1 and #2 above. Since both sides write data to the start of > + shared memory, the two sides must have some convention to know whose > + turn it is to send a message. > + 4. A "queued" RX mailbox with a payload of a well-defined size. > + This type of mailbox is only possible if the MBA instance can count > + doorbells. On mailboxes of this type, the host is the only one to write > + shared memory. When the client doorbell rings, the client reads a > + fixed-size from the next "slot" in shared memory and then updates its > + internal state. The shared memory is treated as a circular queue. > + 5. A "queued" TX mailbox with a payload of a well-defined size. > + This type of mailbox is only possible if the MBA instance can count > + doorbells. On mailboxes of this type, the mailbox client is the only one > + to write shared memory. The shared memory is treated as a circular queue. > + The client writes a fixed-sized payload to the next "slot" in the shared > + memory (where the slot size is determined by the client's first transfer), > + updates its internal state, and rings the host doorbell. The client can > + keep writing more messages as long as the circular queue isn't full. The > + client gets an interrupt when the host Acks a doorbell and can tell how > + many doorbells still haven't been Acked. > + > + Conventions will be supported with a small number of properties specified > + for each mailbox. > + > +properties: > + compatible: > + items: > + - enum: > + - google,lga-mailbox-array > + - const: google,mailbox-array Don't use generic fallback. Just the SoCs. > + > + reg: > + minItems: 1 > + items: > + - description: Host registers (not accessible to client) > + - description: Global registers (not present on newer IP blocks) You have only one SoC. One SoC has only one IP block, no? > + > + ranges: true > + > + "#address-cells": > + const: 1 > + > + "#size-cells": > + const: 1 > + > +patternProperties: > + "^mailbox@[0-9a-f]+$": > + type: object > + description: > + Each sub-node is a single-channel mailbox. This does not look like correct representation. You have one mailbox controller with multiple mailboxes, not multiple mailbox controllers of single channel boxes. > + > + properties: > + reg: > + maxItems: 1 > + > + interrupts: > + maxItems: 1 > + > + "#mbox-cells": > + const: 0 > + > + google,rx-payload-words: > + $ref: /schemas/types.yaml#/definitions/uint32 > + maximum: 256 > + default: 0 > + description: > + The number of 32-bit words in each mailbox message from the remote > + processor. May be 0 for doorbell-only. If not specified this is > + assumed to be 0. > + > + google,mba-queue-mode: > + type: boolean > + description: > + The remote processor is expecting the shared memory to be treated > + as a circular queue and that there may be several outstanding > + messages at once. Only usable on instances with counted doorbell > + interrupts. > + > + required: > + - reg > + - interrupts > + - "#mbox-cells" > + > + additionalProperties: false > + > +required: > + - compatible > + - ranges > + - reg > + - "#address-cells" > + - "#size-cells" > + > +additionalProperties: false > + > +examples: > + - | > + #include <dt-bindings/interrupt-controller/arm-gic.h> > + #include <dt-bindings/interrupt-controller/irq.h> > + > + soc { > + #address-cells = <2>; > + #size-cells = <2>; > + > + cpm_ap_ns_mba: mailbox-array@5240000 { Drop all unused labels. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 6/7] dt-bindings: mailbox: goog-mba: Add goog-mba mailbox bindings 2026-07-15 4:51 ` Krzysztof Kozlowski @ 2026-07-15 16:49 ` Doug Anderson 2026-07-16 5:46 ` Krzysztof Kozlowski 2026-07-22 14:10 ` Rob Herring 0 siblings, 2 replies; 10+ messages in thread From: Doug Anderson @ 2026-07-15 16:49 UTC (permalink / raw) To: Krzysztof Kozlowski Cc: Jassi Brar, Joonwon Kang, Subhash Jadavani, Tudor Ambarus, Lucas Wei, Brian Norris, Peter Griffin, André Draszik, Conor Dooley, Krzysztof Kozlowski, Rob Herring, devicetree, linux-arm-kernel, linux-kernel, linux-samsung-soc Hi, On Tue, Jul 14, 2026 at 9:51 PM Krzysztof Kozlowski <krzk@kernel.org> wrote: > > On 15/07/2026 00:21, Douglas Anderson wrote: > > Introduce bindings for the MailBox Array IP block present in Laguna > > SoCs (AKA "lga", AKA "Google Tensor G5"). > > > > Signed-off-by: Douglas Anderson <dianders@chromium.org> > > --- > > > > .../bindings/mailbox/google,mba.yaml | 216 ++++++++++++++++++ > > Filename must match compatible. Whoops! Will fix in v2. > > +properties: > > + compatible: > > + items: > > + - enum: > > + - google,lga-mailbox-array > > + - const: google,mailbox-array > > Don't use generic fallback. Just the SoCs. Sure, if you insist. In general the "mba" hardware is designed with enough identification registers that we should be able to autodetect which variant we're on. Thus, my hope is to not ever need to reference the SoC-specific variant in the driver itself. It's not the end of the world to use the "google,lga-mailbox-array" as the generic, I guess... I don't suppose I can change your mind here? If we take "google,lga-mailbox-array" as the generic, then going foward a few generations we end up with: properties: compatible: oneOf: - const: google,lga-mailbox-array - items: - enum: - google,next-mailbox-array - google,nextnext-mailbox-array - google,another-mailbox-array - const: google,lga-mailbox-array If we keep "google,mailbox-array" as the generic, then going forward a few generations we end up with this, which seems nicer / less confusing: properties: compatible: items: - enum: - google,lga-mailbox-array - google,next-mailbox-array - google,nextnext-mailbox-array - google,another-mailbox-array - const: google,mailbox-array Sure, it means that if someone unexpectedly makes a new Google mailbox-array that's totally incompatible then the "google,mailbox-array" sounds too generic, but that doesn't feel like the end of the world. You could call the new mailbox array designed in the year 2037 the "google,2037-mailbox-array" and things would overall be less confusing than using the "google,lga-mailbox-array" as the generic. > > + reg: > > + minItems: 1 > > + items: > > + - description: Host registers (not accessible to client) > > + - description: Global registers (not present on newer IP blocks) > > You have only one SoC. One SoC has only one IP block, no? Nope! There are several instances of the MBA IP block per SoC. I tried to explain the situation exhaustively, but there's always the tradeoff between explaining thoroughly and providing too much text. To answer this specific question concretely, there is one MBA per remote processor. Looking at the downstream DTS, I see at least these MBA instances: * AOC (Always On Compute) * GSA (Google Security Anchor) * GDMC (Google Debug Monitor Core) * CPM (Central Power Manager) Each of these 4 MBA instances has its own "global" registers. To provide more context, each MBA instance can support communication beyond just the AP (Apps Processor). For instance, the AOC's MBA instance could be used to talk between the AOC and AP and also between the AOC and CPM. Let's take this as an example. In this case: * The AOC is the "host" of this MBA. * The AP is a "client" of this MBA. * The CPM is another "client" of this MBA. The AOC is the only one with access to the "host" registers. Everyone (AOC, AP, CPM in this case) has access to the read-only "global" registers describing the MBA instance. The clients have access to several banks of client registers, one per mailbox they can access. The host (AOC in this case) also has access to the client register spaces since that's where the shared message memory is located. The overall MBA instance is best identified by the address of the host registers, even if the client (the AP in this case) can't access those registers. On newer versions of the IP block the "global" register bank was removed and the read-only registers that were part of it were simply copied to each client instance. Does that clarify? > > + > > + ranges: true > > + > > + "#address-cells": > > + const: 1 > > + > > + "#size-cells": > > + const: 1 > > + > > +patternProperties: > > + "^mailbox@[0-9a-f]+$": > > + type: object > > + description: > > + Each sub-node is a single-channel mailbox. > > This does not look like correct representation. You have one mailbox > controller with multiple mailboxes, not multiple mailbox controllers of > single channel boxes. I spent quite a bit of time debating this when rewriting the driver. While we could certainly hack things into the existing "mailbox with a bunch of channels", IMO it would be a worse representation of the hardware. I discussed this in the wall of text in this patch series, but re-hashing it here: Each "mailbox" in the mailbox array is more like a full-fledged mailbox than a channel within a mailbox. Each (single-channel) mailbox: * Has its own client register space. * Has its own interrupt. * Can have a different amount of memory for messages. * Can have its own conventions for communication. If we tried to represent the mailbox array as a single mailbox with a bunch of channels, each instance would have a different number of "reg" entries and a different number of interrupts. We would also need an array describing the communication conventions for each channel. Can it be done? Yes. Is it ugly? Also, yes. Further evidence that the hardware design intended "a bunch of mailboxes" rather than "a mailbox with channels" is that the IP block is called a "mailbox array". ;-) > > +examples: > > + - | > > + #include <dt-bindings/interrupt-controller/arm-gic.h> > > + #include <dt-bindings/interrupt-controller/irq.h> > > + > > + soc { > > + #address-cells = <2>; > > + #size-cells = <2>; > > + > > + cpm_ap_ns_mba: mailbox-array@5240000 { > > Drop all unused labels. Sounds good. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 6/7] dt-bindings: mailbox: goog-mba: Add goog-mba mailbox bindings 2026-07-15 16:49 ` Doug Anderson @ 2026-07-16 5:46 ` Krzysztof Kozlowski 2026-07-16 16:31 ` Doug Anderson 2026-07-22 14:10 ` Rob Herring 1 sibling, 1 reply; 10+ messages in thread From: Krzysztof Kozlowski @ 2026-07-16 5:46 UTC (permalink / raw) To: Doug Anderson Cc: Jassi Brar, Joonwon Kang, Subhash Jadavani, Tudor Ambarus, Lucas Wei, Brian Norris, Peter Griffin, André Draszik, Conor Dooley, Krzysztof Kozlowski, Rob Herring, devicetree, linux-arm-kernel, linux-kernel, linux-samsung-soc On 15/07/2026 18:49, Doug Anderson wrote: > Hi, > > On Tue, Jul 14, 2026 at 9:51 PM Krzysztof Kozlowski <krzk@kernel.org> wrote: >> >> On 15/07/2026 00:21, Douglas Anderson wrote: >>> Introduce bindings for the MailBox Array IP block present in Laguna >>> SoCs (AKA "lga", AKA "Google Tensor G5"). >>> >>> Signed-off-by: Douglas Anderson <dianders@chromium.org> >>> --- >>> >>> .../bindings/mailbox/google,mba.yaml | 216 ++++++++++++++++++ >> >> Filename must match compatible. > > Whoops! Will fix in v2. > > >>> +properties: >>> + compatible: >>> + items: >>> + - enum: >>> + - google,lga-mailbox-array >>> + - const: google,mailbox-array >> >> Don't use generic fallback. Just the SoCs. > > Sure, if you insist. > > In general the "mba" hardware is designed with enough identification > registers that we should be able to autodetect which variant we're on. > Thus, my hope is to not ever need to reference the SoC-specific > variant in the driver itself. It's not the end of the world to use the > "google,lga-mailbox-array" as the generic, I guess... > > I don't suppose I can change your mind here? If we take > "google,lga-mailbox-array" as the generic, then going foward a few > generations we end up with: > > properties: > compatible: > oneOf: > - const: google,lga-mailbox-array > - items: > - enum: > - google,next-mailbox-array > - google,nextnext-mailbox-array > - google,another-mailbox-array > - const: google,lga-mailbox-array This is the expected appriach. > > If we keep "google,mailbox-array" as the generic, then going forward a > few generations we end up with this, which seems nicer / less > confusing: > > properties: > compatible: > items: > - enum: > - google,lga-mailbox-array > - google,next-mailbox-array > - google,nextnext-mailbox-array > - google,another-mailbox-array > - const: google,mailbox-array It is the discouraged approach. I already have a few real examples for Qualcomm when people added such generic mailbox and after some time it turned out not generic. So people wanted to add an another generic one... > > Sure, it means that if someone unexpectedly makes a new Google > mailbox-array that's totally incompatible then the > "google,mailbox-array" sounds too generic, but that doesn't feel like > the end of the world. You could call the new mailbox array designed in And there is simple solution, just use SoC compatibles. Everything is elegant, simple and accurate. > the year 2037 the "google,2037-mailbox-array" and things would overall > be less confusing than using the "google,lga-mailbox-array" as the > generic. > > >>> + reg: >>> + minItems: 1 >>> + items: >>> + - description: Host registers (not accessible to client) >>> + - description: Global registers (not present on newer IP blocks) >> >> You have only one SoC. One SoC has only one IP block, no? > > Nope! There are several instances of the MBA IP block per SoC. I tried > to explain the situation exhaustively, but there's always the tradeoff > between explaining thoroughly and providing too much text. That's ok, the "newer" is confusing. > > To answer this specific question concretely, there is one MBA per > remote processor. Looking at the downstream DTS, I see at least these > MBA instances: > * AOC (Always On Compute) > * GSA (Google Security Anchor) > * GDMC (Google Debug Monitor Core) > * CPM (Central Power Manager) > > Each of these 4 MBA instances has its own "global" registers. > > To provide more context, each MBA instance can support communication > beyond just the AP (Apps Processor). For instance, the AOC's MBA > instance could be used to talk between the AOC and AP and also between > the AOC and CPM. Let's take this as an example. In this case: > > * The AOC is the "host" of this MBA. > * The AP is a "client" of this MBA. > * The CPM is another "client" of this MBA. > > The AOC is the only one with access to the "host" registers. > > Everyone (AOC, AP, CPM in this case) has access to the read-only > "global" registers describing the MBA instance. > > The clients have access to several banks of client registers, one per > mailbox they can access. The host (AOC in this case) also has access > to the client register spaces since that's where the shared message > memory is located. > > The overall MBA instance is best identified by the address of the host > registers, even if the client (the AP in this case) can't access those > registers. > > On newer versions of the IP block the "global" register bank was > removed and the read-only registers that were part of it were simply > copied to each client instance. > > Does that clarify? Yeah, just s/on newer/on all/ ? > > >>> + >>> + ranges: true >>> + >>> + "#address-cells": >>> + const: 1 >>> + >>> + "#size-cells": >>> + const: 1 >>> + >>> +patternProperties: >>> + "^mailbox@[0-9a-f]+$": >>> + type: object >>> + description: >>> + Each sub-node is a single-channel mailbox. >> >> This does not look like correct representation. You have one mailbox >> controller with multiple mailboxes, not multiple mailbox controllers of >> single channel boxes. > > I spent quite a bit of time debating this when rewriting the driver. > While we could certainly hack things into the existing "mailbox with a > bunch of channels", IMO it would be a worse representation of the > hardware. > > I discussed this in the wall of text in this patch series, but > re-hashing it here: > > Each "mailbox" in the mailbox array is more like a full-fledged > mailbox than a channel within a mailbox. Each (single-channel) > mailbox: > * Has its own client register space. That's nothing special yet. Many providers of multiple resources have these resources in dedicated registers. Arguing this, each GPIO in a GPIO controller as well has its own register space so is basically a GPIO controller on its own. > * Has its own interrupt. Just like GPIOs... > * Can have a different amount of memory for messages. > * Can have its own conventions for communication. Well, this could be. But you still have one child per channel (cells=0) and all children address space is in parent's space, so that's clear indication. It's one controller with multiple, although some different, channels. > > If we tried to represent the mailbox array as a single mailbox with a > bunch of channels, each instance would have a different number of > "reg" entries and a different number of interrupts. We would also need No, you would have only one device node. Very clean solution instead of 100 children for each individual mailbox. It's the same with clocks (TI) - you do not get device node per clock, even if TI did it 10 years ago. You do not get here device node per channel. > an array describing the communication conventions for each channel. > Can it be done? Yes. Is it ugly? Also, yes. > > Further evidence that the hardware design intended "a bunch of > mailboxes" rather than "a mailbox with channels" is that the IP block > is called a "mailbox array". ;-) Best regards, Krzysztof ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 6/7] dt-bindings: mailbox: goog-mba: Add goog-mba mailbox bindings 2026-07-16 5:46 ` Krzysztof Kozlowski @ 2026-07-16 16:31 ` Doug Anderson 2026-07-22 17:11 ` Doug Anderson 0 siblings, 1 reply; 10+ messages in thread From: Doug Anderson @ 2026-07-16 16:31 UTC (permalink / raw) To: Krzysztof Kozlowski Cc: Jassi Brar, Joonwon Kang, Subhash Jadavani, Tudor Ambarus, Lucas Wei, Brian Norris, Peter Griffin, André Draszik, Conor Dooley, Krzysztof Kozlowski, Rob Herring, devicetree, linux-arm-kernel, linux-kernel, linux-samsung-soc Hi, On Wed, Jul 15, 2026 at 10:47 PM Krzysztof Kozlowski <krzk@kernel.org> wrote: > > > I don't suppose I can change your mind here? If we take > > "google,lga-mailbox-array" as the generic, then going foward a few > > generations we end up with: > > > > properties: > > compatible: > > oneOf: > > - const: google,lga-mailbox-array > > - items: > > - enum: > > - google,next-mailbox-array > > - google,nextnext-mailbox-array > > - google,another-mailbox-array > > - const: google,lga-mailbox-array > > This is the expected appriach. > > > > > If we keep "google,mailbox-array" as the generic, then going forward a > > few generations we end up with this, which seems nicer / less > > confusing: > > > > properties: > > compatible: > > items: > > - enum: > > - google,lga-mailbox-array > > - google,next-mailbox-array > > - google,nextnext-mailbox-array > > - google,another-mailbox-array > > - const: google,mailbox-array > > It is the discouraged approach. I already have a few real examples for > Qualcomm when people added such generic mailbox and after some time it > turned out not generic. So people wanted to add an another generic one... OK, I'll change it to use "google,lga-mailbox-array" as the generic. > >>> + reg: > >>> + minItems: 1 > >>> + items: > >>> + - description: Host registers (not accessible to client) > >>> + - description: Global registers (not present on newer IP blocks) > >> > >> You have only one SoC. One SoC has only one IP block, no? > > > > Nope! There are several instances of the MBA IP block per SoC. I tried > > to explain the situation exhaustively, but there's always the tradeoff > > between explaining thoroughly and providing too much text. > > That's ok, the "newer" is confusing. > > > > > To answer this specific question concretely, there is one MBA per > > remote processor. Looking at the downstream DTS, I see at least these > > MBA instances: > > * AOC (Always On Compute) > > * GSA (Google Security Anchor) > > * GDMC (Google Debug Monitor Core) > > * CPM (Central Power Manager) > > > > Each of these 4 MBA instances has its own "global" registers. > > > > To provide more context, each MBA instance can support communication > > beyond just the AP (Apps Processor). For instance, the AOC's MBA > > instance could be used to talk between the AOC and AP and also between > > the AOC and CPM. Let's take this as an example. In this case: > > > > * The AOC is the "host" of this MBA. > > * The AP is a "client" of this MBA. > > * The CPM is another "client" of this MBA. > > > > The AOC is the only one with access to the "host" registers. > > > > Everyone (AOC, AP, CPM in this case) has access to the read-only > > "global" registers describing the MBA instance. > > > > The clients have access to several banks of client registers, one per > > mailbox they can access. The host (AOC in this case) also has access > > to the client register spaces since that's where the shared message > > memory is located. > > > > The overall MBA instance is best identified by the address of the host > > registers, even if the client (the AP in this case) can't access those > > registers. > > > > On newer versions of the IP block the "global" register bank was > > removed and the read-only registers that were part of it were simply > > copied to each client instance. > > > > Does that clarify? > > Yeah, just s/on newer/on all/ ? No. Although this driver only supports the "laguna" version of the mailbox array, I tried to look forward to what was coming in the future. On "laguna", the "global" register bank is needed. On SoCs past "laguna" (AKA "newer" ones) there is no global register bank. This is why the global register bank needs to be optional. Yes, I could add some validation to tie it to a specific SoC version, but that doesn't really buy anything. It's just as easy to say that if the global register bank is defined in the device tree that it exists. If the global register bank isn't defined, the info must be in the per-client banks. If you insist, I can make the "global" register space non-optional for now and we can re-litigate when official support for newer SoCs is proposed. > >>> +patternProperties: > >>> + "^mailbox@[0-9a-f]+$": > >>> + type: object > >>> + description: > >>> + Each sub-node is a single-channel mailbox. > >> > >> This does not look like correct representation. You have one mailbox > >> controller with multiple mailboxes, not multiple mailbox controllers of > >> single channel boxes. > > > > I spent quite a bit of time debating this when rewriting the driver. > > While we could certainly hack things into the existing "mailbox with a > > bunch of channels", IMO it would be a worse representation of the > > hardware. > > > > I discussed this in the wall of text in this patch series, but > > re-hashing it here: > > > > Each "mailbox" in the mailbox array is more like a full-fledged > > mailbox than a channel within a mailbox. Each (single-channel) > > mailbox: > > * Has its own client register space. > > That's nothing special yet. Many providers of multiple resources have > these resources in dedicated registers. Arguing this, each GPIO in a > GPIO controller as well has its own register space so is basically a > GPIO controller on its own. > > > * Has its own interrupt. > > Just like GPIOs... Sure, having a giant list of interrupts and register offsets isn't the end of the world. > > * Can have a different amount of memory for messages. > > * Can have its own conventions for communication. I notice you didn't respond to the above bullets. How would I deal with different mailboxes in the array having different communication conventions? Different mailboxes in the array might have different "payload" sizes. Some mailboxes in the array might use "queue" mode conventions and some might not. Do I need to devise some complex scheme for describing which mailboxes in the array use which convention? > Well, this could be. But you still have one child per channel (cells=0) > and all children address space is in parent's space, so that's clear > indication. It's one controller with multiple, although some different, > channels. Sure, it's definitely one IP block and I'm not arguing against that. > > If we tried to represent the mailbox array as a single mailbox with a > > bunch of channels, each instance would have a different number of > > "reg" entries and a different number of interrupts. We would also need > > No, you would have only one device node. Very clean solution instead of > 100 children for each individual mailbox. There are definitely not anywhere near 100 children. At most a given instance of an MBA IP block could have 32 mailboxes. In practice, most have fewer. > It's the same with clocks (TI) - you do not get device node per clock, > even if TI did it 10 years ago. You do not get here device node per channel. Sure, the clock history is one thing to look at here. IMO, this is not the right comparison, though. Trying to describe all of the complexity of a clock tree in device tree is an exercise in futility. It's just too complex to get it right, and there really are hundreds of clocks. The mailbox array, on the other hand, is a much simpler beast. I think regulators and PMICs are a better comparison here. When we describe a PMIC in the device tree, do we have a single PMIC node and then have clients refer to a "regulator ID" to index into which specific regulator in the PMIC they want? No, we don't. We use sub-nodes for each specific regulator. This gives us a nice place in the device tree to put information about each individual regulator, since each regulator in a PMIC is different. Certainly if we had a mailbox controller with a bunch of identical channels then describing them as sub-nodes wouldn't make sense. Existing in-tree mailbox controllers have a bunch of homogenous channels, and thus the existing solution of using a channel ID works well. Here, the sub-nodes buy us something and provide for a cleaner solution. I don't understand the downside of my current proposal. It represents the hardware better (both the HW designers' intentions and the reality of its structure), avoids adding complexity to the device tree, and feels clean. -Doug ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 6/7] dt-bindings: mailbox: goog-mba: Add goog-mba mailbox bindings 2026-07-16 16:31 ` Doug Anderson @ 2026-07-22 17:11 ` Doug Anderson 0 siblings, 0 replies; 10+ messages in thread From: Doug Anderson @ 2026-07-22 17:11 UTC (permalink / raw) To: Krzysztof Kozlowski, Jassi Brar, Rob Herring Cc: Joonwon Kang, Subhash Jadavani, Tudor Ambarus, Lucas Wei, Brian Norris, Peter Griffin, André Draszik, Conor Dooley, Krzysztof Kozlowski, devicetree, linux-arm-kernel, linux-kernel, linux-samsung-soc Hi, On Thu, Jul 16, 2026 at 9:31 AM Doug Anderson <dianders@chromium.org> wrote: > > > >>> +patternProperties: > > >>> + "^mailbox@[0-9a-f]+$": > > >>> + type: object > > >>> + description: > > >>> + Each sub-node is a single-channel mailbox. > > >> > > >> This does not look like correct representation. You have one mailbox > > >> controller with multiple mailboxes, not multiple mailbox controllers of > > >> single channel boxes. > > > > > > I spent quite a bit of time debating this when rewriting the driver. > > > While we could certainly hack things into the existing "mailbox with a > > > bunch of channels", IMO it would be a worse representation of the > > > hardware. > > > > > > I discussed this in the wall of text in this patch series, but > > > re-hashing it here: > > > > > > Each "mailbox" in the mailbox array is more like a full-fledged > > > mailbox than a channel within a mailbox. Each (single-channel) > > > mailbox: > > > * Has its own client register space. > > > > That's nothing special yet. Many providers of multiple resources have > > these resources in dedicated registers. Arguing this, each GPIO in a > > GPIO controller as well has its own register space so is basically a > > GPIO controller on its own. > > > > > * Has its own interrupt. > > > > Just like GPIOs... > > Sure, having a giant list of interrupts and register offsets isn't the > end of the world. > > > > > * Can have a different amount of memory for messages. > > > * Can have its own conventions for communication. > > I notice you didn't respond to the above bullets. How would I deal > with different mailboxes in the array having different communication > conventions? Different mailboxes in the array might have different > "payload" sizes. Some mailboxes in the array might use "queue" mode > conventions and some might not. Do I need to devise some complex > scheme for describing which mailboxes in the array use which > convention? > > > > Well, this could be. But you still have one child per channel (cells=0) > > and all children address space is in parent's space, so that's clear > > indication. It's one controller with multiple, although some different, > > channels. > > Sure, it's definitely one IP block and I'm not arguing against that. > > > > > If we tried to represent the mailbox array as a single mailbox with a > > > bunch of channels, each instance would have a different number of > > > "reg" entries and a different number of interrupts. We would also need > > > > No, you would have only one device node. Very clean solution instead of > > 100 children for each individual mailbox. > > There are definitely not anywhere near 100 children. At most a given > instance of an MBA IP block could have 32 mailboxes. In practice, most > have fewer. > > > > It's the same with clocks (TI) - you do not get device node per clock, > > even if TI did it 10 years ago. You do not get here device node per channel. > > Sure, the clock history is one thing to look at here. IMO, this is not > the right comparison, though. Trying to describe all of the complexity > of a clock tree in device tree is an exercise in futility. It's just > too complex to get it right, and there really are hundreds of clocks. > The mailbox array, on the other hand, is a much simpler beast. > > I think regulators and PMICs are a better comparison here. When we > describe a PMIC in the device tree, do we have a single PMIC node and > then have clients refer to a "regulator ID" to index into which > specific regulator in the PMIC they want? No, we don't. We use > sub-nodes for each specific regulator. This gives us a nice place in > the device tree to put information about each individual regulator, > since each regulator in a PMIC is different. > > Certainly if we had a mailbox controller with a bunch of identical > channels then describing them as sub-nodes wouldn't make sense. > Existing in-tree mailbox controllers have a bunch of homogenous > channels, and thus the existing solution of using a channel ID works > well. Here, the sub-nodes buy us something and provide for a cleaner > solution. > > I don't understand the downside of my current proposal. It represents > the hardware better (both the HW designers' intentions and the reality > of its structure), avoids adding complexity to the device tree, and > feels clean. FWIW, I still feel fairly strongly about the fact that #mailbox-cells shuld be 0 here and the fact that each mailbox in this mailbox array is best expressed in the device-tree by its own node since. In other words, the best model for this hardware is an array of single-channel mailboxes, not one mailbox with many channels. The main reason is that each mailbox in the array is _not_ homogeneous and is not intended to be. The main argument is that every mailbox in the array can have a different message-buffer size. While we can discover the message-buffer size of each mailbox in the array at runtime by reading hardware registers, the different message-buffer sizes suggest that each mailbox in the array is designed to be able to use a different message-passing convention. The message-passing convention is defined by the firmware on the remote side and is _not_ discoverable, so we need a place in the device tree to describe it for each mailbox. Each mailbox in the array having its own node is the proper place to put information about this convention. Krzysztof: Do you still oppose this? I feel pretty strongly, so before changing this to some awkward bindings, I'd love to get confirmation. I'd also be interested if anyone else on the CC list has opinions on the topic. -Doug ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 6/7] dt-bindings: mailbox: goog-mba: Add goog-mba mailbox bindings 2026-07-15 16:49 ` Doug Anderson 2026-07-16 5:46 ` Krzysztof Kozlowski @ 2026-07-22 14:10 ` Rob Herring 2026-07-22 16:57 ` Doug Anderson 1 sibling, 1 reply; 10+ messages in thread From: Rob Herring @ 2026-07-22 14:10 UTC (permalink / raw) To: Doug Anderson Cc: Krzysztof Kozlowski, Jassi Brar, Joonwon Kang, Subhash Jadavani, Tudor Ambarus, Lucas Wei, Brian Norris, Peter Griffin, André Draszik, Conor Dooley, Krzysztof Kozlowski, devicetree, linux-arm-kernel, linux-kernel, linux-samsung-soc On Wed, Jul 15, 2026 at 09:49:14AM -0700, Doug Anderson wrote: > Hi, > > On Tue, Jul 14, 2026 at 9:51 PM Krzysztof Kozlowski <krzk@kernel.org> wrote: > > > > On 15/07/2026 00:21, Douglas Anderson wrote: > > > Introduce bindings for the MailBox Array IP block present in Laguna > > > SoCs (AKA "lga", AKA "Google Tensor G5"). > > > > > > Signed-off-by: Douglas Anderson <dianders@chromium.org> > > > --- > > > > > > .../bindings/mailbox/google,mba.yaml | 216 ++++++++++++++++++ > > > > Filename must match compatible. > > Whoops! Will fix in v2. > > > > > +properties: > > > + compatible: > > > + items: > > > + - enum: > > > + - google,lga-mailbox-array > > > + - const: google,mailbox-array > > > > Don't use generic fallback. Just the SoCs. > > Sure, if you insist. > > In general the "mba" hardware is designed with enough identification > registers that we should be able to autodetect which variant we're on. > Thus, my hope is to not ever need to reference the SoC-specific > variant in the driver itself. It's not the end of the world to use the > "google,lga-mailbox-array" as the generic, I guess... > > I don't suppose I can change your mind here? If we take > "google,lga-mailbox-array" as the generic, then going foward a few > generations we end up with: > > properties: > compatible: > oneOf: > - const: google,lga-mailbox-array > - items: > - enum: > - google,next-mailbox-array > - google,nextnext-mailbox-array > - google,another-mailbox-array > - const: google,lga-mailbox-array > > If we keep "google,mailbox-array" as the generic, then going forward a > few generations we end up with this, which seems nicer / less > confusing: > > properties: > compatible: > items: > - enum: > - google,lga-mailbox-array > - google,next-mailbox-array > - google,nextnext-mailbox-array > - google,another-mailbox-array > - const: google,mailbox-array I find 4 strings nicer than 5 strings. > Sure, it means that if someone unexpectedly makes a new Google > mailbox-array that's totally incompatible then the > "google,mailbox-array" sounds too generic, but that doesn't feel like > the end of the world. You could call the new mailbox array designed in > the year 2037 the "google,2037-mailbox-array" and things would overall > be less confusing than using the "google,lga-mailbox-array" as the > generic. What exactly do we need to do to stop having this conversation? We've done this scheme and version numbers and it never ends well. The reality is the h/w folks can't help themselves from changing things, so nothing remains unchanged for very many generations. Rob ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 6/7] dt-bindings: mailbox: goog-mba: Add goog-mba mailbox bindings 2026-07-22 14:10 ` Rob Herring @ 2026-07-22 16:57 ` Doug Anderson 0 siblings, 0 replies; 10+ messages in thread From: Doug Anderson @ 2026-07-22 16:57 UTC (permalink / raw) To: Rob Herring Cc: Krzysztof Kozlowski, Jassi Brar, Joonwon Kang, Subhash Jadavani, Tudor Ambarus, Lucas Wei, Brian Norris, Peter Griffin, André Draszik, Conor Dooley, Krzysztof Kozlowski, devicetree, linux-arm-kernel, linux-kernel, linux-samsung-soc Hi, On Wed, Jul 22, 2026 at 7:10 AM Rob Herring <robh@kernel.org> wrote: > > > Sure, it means that if someone unexpectedly makes a new Google > > mailbox-array that's totally incompatible then the > > "google,mailbox-array" sounds too generic, but that doesn't feel like > > the end of the world. You could call the new mailbox array designed in > > the year 2037 the "google,2037-mailbox-array" and things would overall > > be less confusing than using the "google,lga-mailbox-array" as the > > generic. > > What exactly do we need to do to stop having this conversation? We've > done this scheme and version numbers and it never ends well. > > The reality is the h/w folks can't help themselves from changing things, > so nothing remains unchanged for very many generations. Stop having the conversation with me, or with everyone? With me, I'll stop pushing since I think I understand pretty well where you and Krzysztof stand on the matter now. Even here, I wasn't pushing hard on the matter but I was trying to understand exactly where the boundary was. As I understood it, things with enough "identification" to disambiguate themselves could use something more generic, especially if no preexisting binding existed. I clearly misunderstood. Mea culpa for the noise on this one. I'm not sure how to avoid repeating the conversation with the rest of the world. I think this will always be a confusing topic. -Doug ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 7/7] mailbox: goog-mba: Introduce the goog-mba mailbox driver 2026-07-14 22:21 [PATCH 0/7] mailbox: Improve the mbox core then introduce the goog-mba driver Douglas Anderson 2026-07-14 22:21 ` [PATCH 6/7] dt-bindings: mailbox: goog-mba: Add goog-mba mailbox bindings Douglas Anderson @ 2026-07-14 22:21 ` Douglas Anderson 1 sibling, 0 replies; 10+ messages in thread From: Douglas Anderson @ 2026-07-14 22:21 UTC (permalink / raw) To: Jassi Brar Cc: Joonwon Kang, Subhash Jadavani, Tudor Ambarus, Lucas Wei, Brian Norris, Peter Griffin, André Draszik, Douglas Anderson, linux-arm-kernel, linux-kernel, linux-samsung-soc Add a driver for the MailBox Array IP block present in Laguna SoCs (AKA "lga", AKA "Google Tensor G5"). The mailbox hardware and theory of operation is described in detail in the devicetree bindings. This driver requires two improvements to the mailbox core in order to function properly. Notably: * mailbox: Add support for mailbox controllers that can queue * mailbox: Find a matching mailbox by fwnode rather than device The goog-mba hardware and conventions used to communicate to remote processors is described in detail in the bindings file. See the bindings patch ("dt-bindings: mailbox: goog-mba: Add goog-mba mailbox bindings"). Signed-off-by: Douglas Anderson <dianders@chromium.org> --- This driver is a rewrite from the downstream driver used in Pixel phones and thus is only lightly tested. The downstream driver needed to jump through some awkward hoops in order to work around the above two patches not being present in the mailbox core. MAINTAINERS | 8 + drivers/mailbox/Kconfig | 8 + drivers/mailbox/Makefile | 2 + drivers/mailbox/goog-mba-priv.h | 108 +++++ drivers/mailbox/goog-mba-trace.h | 183 ++++++++ drivers/mailbox/goog-mba.c | 567 +++++++++++++++++++++++ include/linux/mailbox/goog-mba-message.h | 38 ++ 7 files changed, 914 insertions(+) create mode 100644 drivers/mailbox/goog-mba-priv.h create mode 100644 drivers/mailbox/goog-mba-trace.h create mode 100644 drivers/mailbox/goog-mba.c create mode 100644 include/linux/mailbox/goog-mba-message.h diff --git a/MAINTAINERS b/MAINTAINERS index f37a81950e25..09da5b3a0e86 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11070,6 +11070,14 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux.git F: drivers/firmware/google/ F: include/linux/coreboot.h +GOOGLE MAILBOX ARRAY +M: Douglas Anderson <dianders@chromium.org> +L: linux-kernel@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/mailbox/google,mba.yaml +F: drivers/mailbox/goog-mba* +F: include/linux/mailbox/goog-mba-message.h + GOOGLE TENSOR SoC SUPPORT M: Peter Griffin <peter.griffin@linaro.org> R: André Draszik <andre.draszik@linaro.org> diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 3062ee352f78..ddd08e473b57 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -399,4 +399,12 @@ config RISCV_SBI_MPXY_MBOX or HS-mode hypervisor). Say Y here, unless you are sure you do not need this. +config GOOG_MBA_MBOX + tristate "Google Tensor MBA Mailbox" + help + An implementation of the Google MailBox Array (MBA) driver present in + Google Tensor SoCs starting with Laguna (G5). It is used for + inter-processor communication between the application processor and + co-processors. + endif diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 944d8ea39f34..56b18641f50e 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -84,3 +84,5 @@ obj-$(CONFIG_CIX_MBOX) += cix-mailbox.o obj-$(CONFIG_BCM74110_MAILBOX) += bcm74110-mailbox.o obj-$(CONFIG_RISCV_SBI_MPXY_MBOX) += riscv-sbi-mpxy-mbox.o + +obj-$(CONFIG_GOOG_MBA_MBOX) += goog-mba.o diff --git a/drivers/mailbox/goog-mba-priv.h b/drivers/mailbox/goog-mba-priv.h new file mode 100644 index 000000000000..bfe03993a7d4 --- /dev/null +++ b/drivers/mailbox/goog-mba-priv.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2025 Google LLC + */ + +#ifndef _GOOG_MBA_PRIV_H_ +#define _GOOG_MBA_PRIV_H_ + +#include <linux/mailbox_controller.h> + +struct goog_mbox_info { + /** @mbox: Mailbox controller structure. */ + struct mbox_controller mbox; + + /** @np: Device tree node */ + struct device_node *np; + + /** @chan: Mailbox channel structure; only 1 channel per mailbox. */ + struct mbox_chan chan; + + /** @mba: Pointer to the mailbox array containing this mailbox. */ + struct goog_mba_info *mba; + + /** @iomem: IO memory associated with this mailbox. */ + void __iomem *iomem; + + /** @irq: Linux IRQ associated with this mailbox. */ + int irq; + + /** @msg_buffer_words: Number of 32-bit words present in hardware. */ + unsigned int msg_buffer_words; + + /** + * @tx_payload_words: Number of 32-bit words in a tx mailbox message. + * + * In queue mode this is detected on the first TX transfer and subsequent + * transfers must match. + */ + unsigned int tx_payload_words; + + /** @rx_payload_words: Number of 32-bit words in a rx mailbox message. */ + unsigned int rx_payload_words; + + /** + * @rx_buffer: Memory storage for payload when receiving + * + * When we get a message from the other side we copy it here before + * acknowledging the message and passing it to the client. Buffer + * is `payload_words * 4` bytes big. + */ + u32 *rx_buffer; + + /** + * @queue_mode: If true, the other side uses the "queue mode" protocol. + * + * In the "queue mode" protocol, we can send more than one message at + * once and we treat the message buffer like a circular queue, with + * each entry being `payload_words` big. + */ + bool queue_mode; + + + /* QUEUE MODE ONLY BELOW */ + + /** + * @tx_idx: For queue mode, index into msg buffer to write the next msg. + * + * Always between 0 and msg_buffer_words - 1. Increments by payload_words + * after each transmission and wraps to 0 if it's == msg_buffer_words. + */ + unsigned int tx_idx; + + /** + * @rx_idx: For queue mode, index into msg buffer to read the next msg. + * + * Always between 0 and msg_buffer_words - 1. Increments by rx_payload_words + * after each reception and wraps to 0 if it's == msg_buffer_words. + */ + unsigned int rx_idx; + + /** + * @lock: For queue mode, protects outstanding_msgs + * + * We update `outstanding_msgs` in the interrupt handler and when + * queuing up a message. This protects those two accesses. + */ + spinlock_t lock; + + /** + * @outstanding_msgs: For queue mode, num msgs we've written but not acked + * + * After we start each transmission we grab the `lock` and increment + * this by 1. In the interrupt handler when we see that some messages + * were transferred we decrease this and send out the proper number + * of acks. + */ + unsigned int outstanding_msgs; +}; + +struct goog_mba_info { + /** @dev: Pointer to the `struct device` */ + struct device *dev; + + /** @global_iomem: Pointer to global IO memory, or NULL */ + void __iomem *global_iomem; +}; + +#endif /* _GOOG_MBA_PRIV_H_ */ diff --git a/drivers/mailbox/goog-mba-trace.h b/drivers/mailbox/goog-mba-trace.h new file mode 100644 index 000000000000..02be79757fcb --- /dev/null +++ b/drivers/mailbox/goog-mba-trace.h @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM goog_mba + +#if !defined(_GOOG_MBA_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _GOOG_MBA_TRACE_H + +#include <linux/tracepoint.h> + +#include "goog-mba-priv.h" + +TRACE_EVENT( + goog_mba_process_nq_txdone, + + TP_PROTO(const struct goog_mbox_info *goog_mbox), + + TP_ARGS(goog_mbox), + + TP_STRUCT__entry( + __string(dev_name, dev_name(goog_mbox->mba->dev)) + __string(name, goog_mbox->np->full_name) + ), + + TP_fast_assign( + __assign_str(dev_name); + __assign_str(name); + ), + + TP_printk("%s %s", __get_str(dev_name), __get_str(name)) +); + +TRACE_EVENT( + goog_mba_process_q_txdone, + + TP_PROTO(const struct goog_mbox_info *goog_mbox, u32 reqs_completed, u32 outstanding_msgs), + + TP_ARGS(goog_mbox, reqs_completed, outstanding_msgs), + + TP_STRUCT__entry( + __string(dev_name, dev_name(goog_mbox->mba->dev)) + __string(name, goog_mbox->np->full_name) + __field(u32, outstanding_msgs) + __field(u32, reqs_completed) + ), + + TP_fast_assign( + __assign_str(dev_name); + __assign_str(name); + __entry->outstanding_msgs = outstanding_msgs; + __entry->reqs_completed = reqs_completed; + ), + + TP_printk("%s %s: reqs_completed=%u outstanding_msgs=%u", + __get_str(dev_name), __get_str(name), __entry->reqs_completed, + __entry->outstanding_msgs) +); + +TRACE_EVENT( + goog_mba_send_data_nq, + + TP_PROTO(const struct goog_mbox_info *goog_mbox, const u32 *payload, + unsigned int payload_words), + + TP_ARGS(goog_mbox, payload, payload_words), + + TP_STRUCT__entry( + __string(dev_name, dev_name(goog_mbox->mba->dev)) + __string(name, goog_mbox->np->full_name) + __field(u32, payload_words) + __dynamic_array(u32, payload, payload_words) + ), + + TP_fast_assign( + __assign_str(dev_name); + __assign_str(name); + __entry->payload_words = payload_words; + memcpy(__get_dynamic_array(payload), payload, + payload_words * sizeof(u32)); + ), + + TP_printk("%s %s: data=%s", + __get_str(dev_name), __get_str(name), + __print_array(__get_dynamic_array(payload), + __entry->payload_words, sizeof(u32))) +); + +TRACE_EVENT( + goog_mba_send_data_q, + + TP_PROTO(const struct goog_mbox_info *goog_mbox, const u32 *payload, + unsigned int payload_words), + + TP_ARGS(goog_mbox, payload, payload_words), + + TP_STRUCT__entry( + __string(dev_name, dev_name(goog_mbox->mba->dev)) + __string(name, goog_mbox->np->full_name) + __field(u32, tx_idx) + __field(u32, payload_words) + __dynamic_array(u32, payload, payload_words) + ), + + TP_fast_assign( + __assign_str(dev_name); + __assign_str(name); + __entry->tx_idx = goog_mbox->tx_idx; + __entry->payload_words = payload_words; + memcpy(__get_dynamic_array(payload), payload, + payload_words * sizeof(u32)); + ), + + TP_printk("%s %s: tx_idx=%u data=%s", + __get_str(dev_name), __get_str(name), __entry->tx_idx, + __print_array(__get_dynamic_array(payload), + __entry->payload_words, sizeof(u32))) +); + +TRACE_EVENT( + goog_mba_process_nq_rx, + + TP_PROTO(const struct goog_mbox_info *goog_mbox), + + TP_ARGS(goog_mbox), + + TP_STRUCT__entry( + __string(dev_name, dev_name(goog_mbox->mba->dev)) + __string(name, goog_mbox->np->full_name) + __field(u32, rx_payload_words) + __dynamic_array(u32, payload, goog_mbox->rx_payload_words) + ), + + TP_fast_assign( + __assign_str(dev_name); + __assign_str(name); + __entry->rx_payload_words = goog_mbox->rx_payload_words; + memcpy(__get_dynamic_array(payload), goog_mbox->rx_buffer, + goog_mbox->rx_payload_words * sizeof(u32)); + ), + + TP_printk("%s %s: data=%s", + __get_str(dev_name), __get_str(name), + __print_array(__get_dynamic_array(payload), + __entry->rx_payload_words, sizeof(u32))) +); + +TRACE_EVENT( + goog_mba_process_q_rx, + + TP_PROTO(const struct goog_mbox_info *goog_mbox), + + TP_ARGS(goog_mbox), + + TP_STRUCT__entry( + __string(dev_name, dev_name(goog_mbox->mba->dev)) + __string(name, goog_mbox->np->full_name) + __field(u32, rx_idx) + __field(u32, rx_payload_words) + __dynamic_array(u32, payload, goog_mbox->rx_payload_words) + ), + + TP_fast_assign( + __assign_str(dev_name); + __assign_str(name); + __entry->rx_idx = goog_mbox->rx_idx; + __entry->rx_payload_words = goog_mbox->rx_payload_words; + memcpy(__get_dynamic_array(payload), goog_mbox->rx_buffer, + goog_mbox->rx_payload_words * sizeof(u32)); + ), + + TP_printk("%s %s: rx_idx=%u data=%s", + __get_str(dev_name), __get_str(name), __entry->rx_idx, + __print_array(__get_dynamic_array(payload), + __entry->rx_payload_words, sizeof(u32))) +); + +#endif /* _GOOG_MBA_TRACE_H */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH ../drivers/mailbox +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE goog-mba-trace +#include <trace/define_trace.h> diff --git a/drivers/mailbox/goog-mba.c b/drivers/mailbox/goog-mba.c new file mode 100644 index 000000000000..54b6ed787b71 --- /dev/null +++ b/drivers/mailbox/goog-mba.c @@ -0,0 +1,567 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Google MailBox Array (MBA) Driver + * + * Copyright (c) 2025 Google LLC + */ + +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/mailbox_controller.h> +#include <linux/mailbox/goog-mba-message.h> +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/slab.h> +#include <linux/spinlock.h> + +#include "goog-mba-priv.h" + +#define CREATE_TRACE_POINTS +#include "goog-mba-trace.h" + +#define CLIENT_IRQ_TRIG_OFFSET 0x0 +#define SET_HOST_IRQ 0x1 + +#define CLIENT_IRQ_CONFIG_OFFSET 0x4 +#define ENABLE_HOST_AUTO_ACK BIT(8) +#define CLIENT_IRQ_MASK_MSG_INT BIT(16) +#define CLIENT_IRQ_MASK_ACK_INT BIT(24) + +#define CLIENT_IRQ_STATUS_OFFSET 0x8 +#define CLIENT_IRQ_STATUS_MSG_INT 0x1 +#define CLIENT_IRQ_STATUS_ACK_INT 0x100 + +#define CLIENT_MBA_IP_VER 0x30 +#define CLIENT_NUM_MSG_REG 0x34 +#define CLIENT_OUTSTANDING_MSG 0x10 + +#define GLOBAL_NUM_MSG_REG_OFFSET(x) (0x10 + ((x) * 4)) +#define GLOBAL_MBA_IP_VER_OFFSET 4 + +#define CLIENT_CLIENT_DOORBELL_TRIG 0x20 +#define CLIENT_DOORBELL_MASK_OFFSET 0x24 +#define CLIENT_DOORBELL_STATUS_OFFSET 0x28 +#define CLIENT_HOST_DOORBELL_OFFSET 0x38 +#define CLIENT_CLIENT_DOORBELL_OFFSET 0x3c + +#define MAX_MBA_CHANNELS 1 +#define NR_PHANDLE_ARG_COUNT 1 + +#define MSG_OFFSET(i) (0x100 + (i) * sizeof(u32)) + +#define MBA_IP_MAJOR_VER_1 0x1 +#define MBA_IP_MAJOR_VER_3 0x3 + +#define MBA_IP_MAJOR_VER_SHIFT 24 +#define MBA_IP_MAJOR_VER_MASK 0xff +#define MBA_IP_MINOR_VER_SHIFT 16 +#define MBA_IP_MINOR_VER_MASK 0xff +#define MBA_IP_INCREMENTAL_VER_SHIFT 0 +#define MBA_IP_INCREMENTAL_VER_MASK 0xffff + +/** + * goog_mba_handle_tx_interrupt() - Handle interrupt that remote Acked our msg. + * @goog_mbox: The mailbox info. + */ +static void goog_mba_handle_tx_interrupt(struct goog_mbox_info *goog_mbox) +{ + unsigned int reqs_completed; + int i; + + /* + * ACK interrupt needs to be cleared before reading CLIENT_OUTSTANDING_MSG. + * Then if a "race" happens and another message gets Acked after we clear + * but before we read CLIENT_OUTSTANDING_MSG then the worst that will + * happen is we'll get a followup interrupt that will show 0 reqs_completed. + */ + writel(CLIENT_IRQ_STATUS_ACK_INT, goog_mbox->iomem + CLIENT_IRQ_STATUS_OFFSET); + + if (goog_mbox->queue_mode) { + u32 outstanding_msgs; + + outstanding_msgs = readl(goog_mbox->iomem + CLIENT_OUTSTANDING_MSG); + spin_lock(&goog_mbox->lock); + + if (goog_mbox->outstanding_msgs >= outstanding_msgs) { + reqs_completed = goog_mbox->outstanding_msgs - outstanding_msgs; + } else { + /* + * The hardware's track of outstanding messages should always + * be less than or equal to the number of messages we queued. + * If it thinks there are more messages outstanding than we + * queued, something is wrong. Assume nothing was completed. + */ + dev_warn_ratelimited(goog_mbox->mba->dev, + "%pOFP: unexpected outstanding msgs: %u -> %u\n", + goog_mbox->np, goog_mbox->outstanding_msgs, + outstanding_msgs); + reqs_completed = 0; + } + goog_mbox->outstanding_msgs = outstanding_msgs; + spin_unlock(&goog_mbox->lock); + + trace_goog_mba_process_q_txdone(goog_mbox, reqs_completed, outstanding_msgs); + } else { + reqs_completed = 1; + trace_goog_mba_process_nq_txdone(goog_mbox); + } + + for (i = 0; i < reqs_completed; i++) + mbox_chan_txdone(&goog_mbox->chan, 0); +} + +/** + * goog_mba_handle_rx_interrupt() - Handle interrupt that remote send a msg. + * @goog_mbox: The mailbox info. + */ +static void goog_mba_handle_rx_interrupt(struct goog_mbox_info *goog_mbox) +{ + struct goog_mba_rx_msg msg = { + .payload = goog_mbox->rx_buffer, + .payload_words = goog_mbox->rx_payload_words, + }; + int i; + + for (i = 0; i < goog_mbox->rx_payload_words; i++) + goog_mbox->rx_buffer[i] = readl(goog_mbox->iomem + + MSG_OFFSET(goog_mbox->rx_idx + i)); + + if (goog_mbox->queue_mode) { + goog_mbox->rx_idx = (goog_mbox->rx_idx + goog_mbox->rx_payload_words) % + goog_mbox->msg_buffer_words; + trace_goog_mba_process_q_rx(goog_mbox); + } else { + trace_goog_mba_process_nq_rx(goog_mbox); + } + + /* + * Ack the interrupt after we've read the message to local memory but + * before passing it to the client. This frees up space for the remote + * processor to send another message as the client is processing this one. + */ + writel(CLIENT_IRQ_STATUS_MSG_INT, goog_mbox->iomem + CLIENT_IRQ_STATUS_OFFSET); + + mbox_chan_received_data(&goog_mbox->chan, &msg); +} + +/** + * goog_mba_isr() - Main interrupt routine + * @irq: The IRQ number. + * @data: Data passed when registering (the goog_mbox_info for this IRQ). + * + * Return: IRQ_HANDLED if IRQ was handled; IRQ_NONE if no interrupt was found. + */ +static irqreturn_t goog_mba_isr(int irq, void *data) +{ + struct goog_mbox_info *goog_mbox = data; + u32 irq_status; + + irq_status = readl(goog_mbox->iomem + CLIENT_IRQ_STATUS_OFFSET); + if (!irq_status) + return IRQ_NONE; + + while (true) { + if (irq_status & CLIENT_IRQ_STATUS_ACK_INT) + goog_mba_handle_tx_interrupt(goog_mbox); + + if (irq_status & CLIENT_IRQ_STATUS_MSG_INT) { + goog_mba_handle_rx_interrupt(goog_mbox); + + /* + * In queue mode the RX interrupt will re-assert itself + * right after we clear it if there is more than one + * message waiting. As an optimization to avoid returning + * and immediately re-triggering our interrupt, re-check. + * + * NOTE: we don't need to loop for the TX (Ack) case + * since TX interrupts aren't counted in the same way. + */ + if (goog_mbox->queue_mode) + irq_status = readl(goog_mbox->iomem + CLIENT_IRQ_STATUS_OFFSET); + else + break; + } else { + break; + } + } + + return IRQ_HANDLED; +} + +/** + * goog_mba_send_data() - Mailbox op for send_data. + * @chan: The Linux mbox_chan structure associated with the mailbox. + * @msg: The mailbox message, expected to be of type `struct goog_mba_tx_msg`. + * If NULL, we'll assume a 0-byte doorbell-only message. + * + * Return: 0 if the data was sent; -EBUSY if the queue was full; other + * negative error values for other problems. + */ +static int goog_mba_send_data(struct mbox_chan *chan, void *msg) +{ + struct goog_mbox_info *goog_mbox = chan->con_priv; + struct device *dev = goog_mbox->mba->dev; + bool queue_mode = goog_mbox->queue_mode; + unsigned int payload_words = 0; + const u32 *payload = NULL; + bool is_init = false; + unsigned int tx_idx; + unsigned int i; + unsigned long flags; + + if (msg) { + struct goog_mba_tx_msg *mba_msg = msg; + + payload_words = mba_msg->payload_words; + payload = mba_msg->payload; + is_init = mba_msg->init; + } + + if (payload_words > goog_mbox->msg_buffer_words) { + dev_err(dev, "%pOFP: Payload too big: %u > %u\n", + goog_mbox->np, payload_words, goog_mbox->msg_buffer_words); + return -EINVAL; + } + + /* + * Currently all queue-mode transfers need to be the same size and + * need to evenly divide the message buffer. If this is the first + * transfer, we need to validate/store the payload_words. For subsequent + * transfers we just need to confirm it hasn't changed. + */ + if (queue_mode) { + if (!goog_mbox->tx_payload_words && payload_words) { + if (goog_mbox->msg_buffer_words % payload_words != 0) { + dev_err(dev, "%pOFP: Invalid initial TX queue payload words: %u\n", + goog_mbox->np, payload_words); + return -EINVAL; + } + goog_mbox->tx_payload_words = payload_words; + } else if (payload_words != goog_mbox->tx_payload_words) { + dev_err(dev, "%pOFP: Payload size mismatch: %u vs %u\n", + goog_mbox->np, payload_words, goog_mbox->tx_payload_words); + return -EINVAL; + } + } + + /* + * HW can handle full duplex but there is no current scheme for dividing + * up the message buffer between TX and RX portions. Non-queue mode + * could work half-duplex, but that doesn't make sense in queue mode. + * If space is reserved for RX then disallow using it for TX. + */ + if (queue_mode && payload_words && goog_mbox->rx_payload_words) { + dev_err(dev, "%pOFP: Can't TX if buffer is used for RX\n", goog_mbox->np); + return -EINVAL; + } + + if (queue_mode) { + bool out_of_space; + + spin_lock_irqsave(&goog_mbox->lock, flags); + out_of_space = payload_words && + (goog_mbox->outstanding_msgs >= + goog_mbox->msg_buffer_words / payload_words); + spin_unlock_irqrestore(&goog_mbox->lock, flags); + + /* + * IMPORTANT: don't print an error for this. It's normal and + * expected that the core will keep trying to queue messages + * until the controller reports -EBUSY. + */ + if (out_of_space) + return -EBUSY; + + tx_idx = goog_mbox->tx_idx; + trace_goog_mba_send_data_q(goog_mbox, payload, payload_words); + } else { + tx_idx = 0; + trace_goog_mba_send_data_nq(goog_mbox, payload, payload_words); + } + + for (i = 0; i < payload_words; i++) + writel(payload[i], goog_mbox->iomem + MSG_OFFSET(tx_idx + i)); + + if (queue_mode) { + if (is_init) + goog_mbox->tx_idx = 0; + else + goog_mbox->tx_idx = (goog_mbox->tx_idx + payload_words) % + goog_mbox->msg_buffer_words; + } + + /* + * We need to be careful on how we deal with `outstanding_msgs`. + * The hardware will give us an interrupt every time it transfers + * a message, but if it transfers two messages before our interrupt + * handler fires then we'll still only get one interrupt. We have + * to look at the difference between the hardware's idea of + * `outstanding_msgs` and ours to figure out how many messages were + * actually transferred. + * + * We need to start the transfer and increment our concept of + * `outstanding_msgs` in lockstep so protect against the interrupt + * handler also touching `outstanding_msgs`. + */ + if (queue_mode) + spin_lock_irqsave(&goog_mbox->lock, flags); + + writel(SET_HOST_IRQ, goog_mbox->iomem + CLIENT_IRQ_TRIG_OFFSET); + + if (queue_mode) { + goog_mbox->outstanding_msgs++; + spin_unlock_irqrestore(&goog_mbox->lock, flags); + } + + return 0; +} + +/** + * goog_mba_startup() - Mailbox op for startup. + * @chan: The Linux mbox_chan structure associated with the mailbox. + * + * Return: 0 for OK; negative error code if problems. + */ +static int goog_mba_startup(struct mbox_chan *chan) +{ + struct goog_mbox_info *goog_mbox = chan->con_priv; + + writel(ENABLE_HOST_AUTO_ACK | CLIENT_IRQ_MASK_MSG_INT | CLIENT_IRQ_MASK_ACK_INT, + goog_mbox->iomem + CLIENT_IRQ_CONFIG_OFFSET); + enable_irq(goog_mbox->irq); + + return 0; +} + +/** + * goog_mba_shutdown() - Mailbox op for shutdown. + * @chan: The Linux mbox_chan structure associated with the mailbox. + */ +static void goog_mba_shutdown(struct mbox_chan *chan) +{ + struct goog_mbox_info *goog_mbox = chan->con_priv; + + disable_irq(goog_mbox->irq); + writel(0x0, goog_mbox->iomem + CLIENT_IRQ_CONFIG_OFFSET); +} + +static const struct mbox_chan_ops goog_mba_chan_ops = { + .send_data = goog_mba_send_data, + .startup = goog_mba_startup, + .shutdown = goog_mba_shutdown, +}; + +/** + * goog_mba_get_msg_buf_words() - Return # msg buffer words in HW for this mailbox. + * @goog_mbox: The mailbox info. + * @np: The device tree node associated with this mailbox. + * + * Return: The number of 32-bit words in the hardware message buffer. + */ +static unsigned int goog_mba_get_msg_buf_words(struct goog_mbox_info *goog_mbox, + struct device_node *np) +{ + struct goog_mba_info *mba = goog_mbox->mba; + struct resource res; + unsigned int index; + + /* + * On newer IP there's no global space and the register moved to the + * client address space. + */ + if (!mba->global_iomem) + return readl(goog_mbox->iomem + CLIENT_NUM_MSG_REG); + + /* + * On older IP we need to find the index so we can look up the value + * in the global memory. Our index is based on the physical address + * of the mbox since on older hardware mailboxes are 4K apart. + */ + if (of_address_to_resource(np, 0, &res)) { + dev_err(mba->dev, "%pOFP: Failed to find physical address\n", np); + return 0; + } + index = (res.start & 0x1ffff) / 0x1000; + + return readl(mba->global_iomem + GLOBAL_NUM_MSG_REG_OFFSET(index)); +} + +/** + * of_node_put_void() - of_node_put() for passing to devm_add_action_or_reset(). + * @data: Our struct device_node pointer. + */ +static void of_node_put_void(void *data) +{ + of_node_put(data); +} + +/** + * goog_mba_mbox_init() - Initialize one single mailbox. + * @goog_mbox: The mailbox info. + * @mba: The array containing this mailbox. + * @np: The device tree node associated with this mailbox. + * + * Return: 0 or a negative error code. If an error is returned, the error has + * already been logged. + */ +static int goog_mba_mbox_init(struct goog_mbox_info *goog_mbox, + struct goog_mba_info *mba, struct device_node *np) +{ + struct mbox_controller *mbox = &goog_mbox->mbox; + struct mbox_chan *chan = &goog_mbox->chan; + struct device *dev = mba->dev; + unsigned int msg_buffer_words; + u32 rx_payload_words; + int ret; + + goog_mbox->mba = mba; + + of_node_get(np); + ret = devm_add_action_or_reset(dev, of_node_put_void, np); + if (ret) + return ret; + goog_mbox->np = np; + + goog_mbox->iomem = devm_of_iomap(dev, np, 0, NULL); + if (IS_ERR(goog_mbox->iomem)) + return dev_err_probe(dev, PTR_ERR(goog_mbox->iomem), + "%pOFP: Failed to map memory\n", np); + + /* Start with all interrupts disabled and cleared */ + writel(0x0, goog_mbox->iomem + CLIENT_IRQ_CONFIG_OFFSET); + writel(CLIENT_IRQ_STATUS_MSG_INT | CLIENT_IRQ_STATUS_ACK_INT, + goog_mbox->iomem + CLIENT_IRQ_STATUS_OFFSET); + + goog_mbox->irq = of_irq_get(np, 0); + if (goog_mbox->irq <= 0) { + if (goog_mbox->irq == 0) + goog_mbox->irq = -EINVAL; + return dev_err_probe(dev, goog_mbox->irq, "%pOFP: Failed to get IRQ\n", np); + } + ret = devm_request_irq(dev, goog_mbox->irq, goog_mba_isr, + IRQF_NO_SUSPEND | IRQF_NO_AUTOEN, + NULL, goog_mbox); + if (ret) + return dev_err_probe(dev, ret, "%pOFP: Failed to request interrupt\n", np); + + goog_mbox->queue_mode = of_property_read_bool(np, "google,mba-queue-mode"); + + rx_payload_words = 0; + ret = of_property_read_u32(np, "google,rx-payload-words", &rx_payload_words); + goog_mbox->rx_payload_words = rx_payload_words; + + msg_buffer_words = goog_mba_get_msg_buf_words(goog_mbox, np); + goog_mbox->msg_buffer_words = msg_buffer_words; + + if (goog_mbox->queue_mode && !msg_buffer_words) + return dev_err_probe(dev, -EINVAL, + "%pOFP: Queue mode requires non-zero buffer\n", np); + + if (msg_buffer_words < rx_payload_words) + return dev_err_probe(dev, -EINVAL, + "%pOFP: Buffer (%u) < RX Payload (%u)\n", + np, msg_buffer_words, rx_payload_words); + if (goog_mbox->queue_mode && rx_payload_words && msg_buffer_words % rx_payload_words != 0) + return dev_err_probe(dev, -EINVAL, + "%pOFP: Queue buffer (%u) must be multiple of RX payload (%u)\n", + np, msg_buffer_words, rx_payload_words); + + if (rx_payload_words) { + goog_mbox->rx_buffer = devm_kcalloc(dev, rx_payload_words, + sizeof(*goog_mbox->rx_buffer), GFP_KERNEL); + if (!goog_mbox->rx_buffer) + return -ENOMEM; + } + + mbox->fwnode = of_fwnode_handle(np); + mbox->dev = dev; + mbox->ops = &goog_mba_chan_ops; + mbox->chans = chan; + mbox->num_chans = 1; + mbox->txdone_irq = true; + mbox->has_queue = goog_mbox->queue_mode; + spin_lock_init(&goog_mbox->lock); + + chan->con_priv = goog_mbox; + + ret = devm_mbox_controller_register(dev, mbox); + if (ret) + return dev_err_probe(dev, ret, + "%pOFP: Failed to register mailbox controller\n", np); + + return 0; +} + +/** + * goog_mba_probe() - MBA probe routine. + * @pdev: Our platform device. + * + * Return: 0 or a negative error code. + */ +static int goog_mba_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct goog_mbox_info *goog_mboxes; + struct goog_mba_info *mba; + unsigned int num_mboxes; + unsigned int i; + int ret; + + mba = devm_kzalloc(dev, sizeof(*mba), GFP_KERNEL); + if (!mba) + return -ENOMEM; + mba->dev = dev; + + num_mboxes = of_get_available_child_count(dev->of_node); + goog_mboxes = devm_kzalloc(dev, sizeof(*goog_mboxes) * num_mboxes, GFP_KERNEL); + if (!goog_mboxes) + return -ENOMEM; + + /* + * The first memory range is the memory range that the other side + * of the mailbox uses. The second memory range is the shared/global + * range. Note that newer versions of the IP don't have the global + * range, so mba->global_iomem is left NULL on newer IP. + */ + if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) { + mba->global_iomem = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(mba->global_iomem)) + return dev_err_probe(dev, PTR_ERR(mba->global_iomem), + "Failed to iomap global region\n"); + } + + i = 0; + for_each_available_child_of_node_scoped(dev->of_node, child_np) { + ret = goog_mba_mbox_init(&goog_mboxes[i], mba, child_np); + if (ret) + return ret; + i++; + } + + return 0; +} + +static const struct of_device_id goog_mba_match[] = { + { .compatible = "google,mailbox-array" }, + { /* Sentinel */ } +}; +MODULE_DEVICE_TABLE(of, goog_mba_match); + +static struct platform_driver mba = { + .driver = { + .name = "goog-mba", + .of_match_table = goog_mba_match, + }, + .probe = goog_mba_probe, +}; + +module_platform_driver(mba); + +MODULE_DESCRIPTION("Google MailBox Array (MBA) Driver"); +MODULE_AUTHOR("Douglas Anderson <dianders@chromium.org>"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/mailbox/goog-mba-message.h b/include/linux/mailbox/goog-mba-message.h new file mode 100644 index 000000000000..5c3d47e3ded3 --- /dev/null +++ b/include/linux/mailbox/goog-mba-message.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Google MailBox Array (MBA) Mailbox Message + * + * Copyright (c) 2025 Google LLC + */ + +#ifndef _LINUX_MAILBOX_GOOG_MBA_MESSAGE_H_ +#define _LINUX_MAILBOX_GOOG_MBA_MESSAGE_H_ + +#include <linux/types.h> + +struct goog_mba_tx_msg { + /** @payload: The contents of the message to send. */ + const u32 *payload; + + /** @payload_words: The number of 32-bit words in the payload. */ + u8 payload_words; + + /** + * @init: Initialize queue settings after sending. + * + * Tell the mailbox driver that this is a special "initialize" + * message for a queue-based mailbox. This allows the mailbox driver + * to keep its state synced with the remote side of the mailbox. + */ + bool init; +}; + +struct goog_mba_rx_msg { + /** @payload: The contents of the message received. */ + const u32 *payload; + + /** @payload_words: The number of 32-bit words in the payload. */ + u8 payload_words; +}; + +#endif /* _LINUX_MAILBOX_GOOG_MBA_MESSAGE_H_ */ -- 2.55.0.141.g00534a21ce-goog ^ permalink raw reply related [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-07-22 17:12 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-07-14 22:21 [PATCH 0/7] mailbox: Improve the mbox core then introduce the goog-mba driver Douglas Anderson 2026-07-14 22:21 ` [PATCH 6/7] dt-bindings: mailbox: goog-mba: Add goog-mba mailbox bindings Douglas Anderson 2026-07-15 4:51 ` Krzysztof Kozlowski 2026-07-15 16:49 ` Doug Anderson 2026-07-16 5:46 ` Krzysztof Kozlowski 2026-07-16 16:31 ` Doug Anderson 2026-07-22 17:11 ` Doug Anderson 2026-07-22 14:10 ` Rob Herring 2026-07-22 16:57 ` Doug Anderson 2026-07-14 22:21 ` [PATCH 7/7] mailbox: goog-mba: Introduce the goog-mba mailbox driver Douglas Anderson
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox