Skip to content

Nord: HPASS ADSP0/1/2 cluster support (+ RRD USB_1 enablement) - #981

Merged
Komal Bajaj (Komal-Bajaj) merged 12 commits into
qualcomm-linux:staging/nordfrom
apateriy-qcom:nord-staging-cluster-190826
Aug 19, 2026
Merged

Nord: HPASS ADSP0/1/2 cluster support (+ RRD USB_1 enablement)#981
Komal Bajaj (Komal-Bajaj) merged 12 commits into
qualcomm-linux:staging/nordfrom
apateriy-qcom:nord-staging-cluster-190826

Conversation

@apateriy-qcom

Copy link
Copy Markdown

Nord's HPASS domain contains three independent QDSP6SS instances (ADSP0/1/2), but they are
not independent at runtime: ADSP0 owns the HPASS-domain PLLs, AG_NOC, RSCp, CESTA, THROTTLE
and QTMR that all three need. Firmware on these cores cannot tolerate one member being
started or stopped on its own — peer SSR notifications time out, and the cluster ends up
wedged until all three are stopped and restarted in dependency order.

This series adds a generic "cluster" concept to the PAS remoteproc driver and wires Nord's
ADSP1/ADSP2 up as cluster members of ADSP0, so that the three boot root-first and are torn
down as a single unit.

It also carries one unrelated cherry-pick enabling USB_1 on the Nord RRD board

@apateriy-qcom
apateriy-qcom force-pushed the nord-staging-cluster-190826 branch from fde76b2 to e66f41a Compare August 19, 2026 12:00
Shawn Guo added 12 commits August 19, 2026 18:07
Enable Nord SoC USB_1 controller with the eUSB2 repeater and the onboard
Genesys Logic GL3590 4-port USB 3.2 Gen1 hub as a peer-hub pair
(usb5e3,610 HS die + usb5e3,625 SS die).

Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
…ot property

Document the qcom,cluster-root phandle property used to describe HPASS's
ADSP0/1/2 cluster relationship. Every member of a cluster carries the
property, including the instance owning the shared resources, which
references itself; instances referencing the same node form one cluster
that boots in order and is torn down as a single unit.

The relationship is described with a phandle rather than by containment
in a parent node, as ti,k3-r5f-rproc and xlnx,zynqmp-r5fss do, because
the hardware does not express it by containment either: the three QDSP6SS
blocks are register-independent, with no shared register window for a
container node to describe.

Also add the qcom,nord-adsp1-pas and qcom,nord-adsp2-pas compatible
strings used by the non-root cluster members.

Assisted-by: LLM
Link: https://lore.kernel.org/r/20260815132541.1575121-2-shengchao.guo@oss.qualcomm.com
Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
Some Qualcomm SoCs group multiple remote processors into a cluster
(e.g. Nord's ADSP0/1/2, which share HPASS-domain PLLs, AG_NOC, RSCp
and other resources owned by ADSP0). Firmware on these clusters cannot
tolerate the peer-shutdown notifications that qcom_sysmon and
qcom_glink_ssr send between independently started/stopped remote
processors.

Add an opaque cluster identifier to struct rproc so that those
notification paths, which live in different subsystems (remoteproc
and rpmsg), can recognize siblings in the same cluster and suppress
notifications between them, without introducing a module dependency
between the two subsystems.

Assisted-by: LLM
Link: https://lore.kernel.org/r/20260815132541.1575121-3-shengchao.guo@oss.qualcomm.com
Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
…iblings

Firmware on clustered remote processors (e.g. Nord's HPASS ADSP0/1/2)
cannot handle the SSCTL peer-shutdown notification sysmon sends
whenever a sibling in the same cluster starts or stops, and the QMI
request instead times out.

Skip sysmon_notify() when the notifying and the notified instance share
the cluster identifier their owning rproc driver put in rproc->cluster.
The suppression is done on the receiving side, so that a cluster member
keeps notifying, and being notified by, remote processors outside its
cluster. Instances whose rproc has no cluster set are completely
unaffected.

Assisted-by: LLM
Link: https://lore.kernel.org/r/20260815132541.1575121-4-shengchao.guo@oss.qualcomm.com
Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
…ter siblings

Like qcom_sysmon's SSCTL notify, clustered remote processors (e.g.
Nord's HPASS ADSP0/1/2) cannot handle the glink_ssr DO_CLEANUP
broadcast sent to siblings whenever one of them starts or stops,
leaving qcom_glink_ssr_notifier_call() to time out waiting for
CLEANUP_DONE.

Pass the stopping remoteproc's cluster identifier through
qcom_glink_ssr_notify(), and plumb each edge's own cluster identifier
down from the remoteproc that registers it, so that
qcom_glink_ssr_notifier_call() can skip the DO_CLEANUP send when the
sender and the receiving edge share a cluster. As in qcom_sysmon, the
suppression is done on the receiving side, so that a cluster member
keeps sending DO_CLEANUP to, and receiving it from, remote processors
outside its cluster. Edges with no cluster set are unaffected.

The receiving edge's identifier is carried in struct qcom_glink rather
than looked up from the rproc that owns it, so that glink_ssr does not
have to reach into struct remoteproc: RPMSG_QCOM_GLINK does not depend
on REMOTEPROC, and the identifier is deliberately opaque to keep the
two subsystems independent of each other.

Assisted-by: LLM
Link: https://lore.kernel.org/r/20260815132541.1575121-5-shengchao.guo@oss.qualcomm.com
Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
On Nord, ADSP0/1/2 share HPASS-domain resources (PLLs, AG_NOC, RSCp,
CESTA, THROTTLE, QTMR) owned by ADSP0, and their firmware cannot
tolerate one member being started or stopped independently of the
others. Modeling that requires each PAS instance to know which other
instances it is grouped with.

Add a small registry of clusters, keyed by the device_node every member's
"qcom,cluster-root" phandle points at, and join it at probe. Membership
is answerable from the node being probed alone: every member carries the
property, and the one referencing itself is the root, so there is no need
to search the device tree for nodes referencing a given instance.

A dependent member is rejected at probe if its root is disabled in DT,
since its boot could never be sequenced after a root that will not bind.

Publish the cluster in rproc->cluster, which is all sysmon and
glink_ssr need to stop notifying siblings of each other's SSR events.
The cluster is left only after rproc_del() has stopped this member, so
that the suppression is still in effect for that stop, and is unwound on
every probe error path, since a member freed while still linked into the
cluster would be walked by its siblings.

Instances without "qcom,cluster-root" are completely unaffected:
qcom_pas.cluster stays NULL for them.

Assisted-by: LLM
Link: https://lore.kernel.org/r/20260815132541.1575121-6-shengchao.guo@oss.qualcomm.com
Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
…t-first

The cluster root owns the HPASS resources shared with its siblings and
initializes them as part of its own boot, so ADSP1/ADSP2 can only cold
boot once ADSP0 is up. Booting a dependent member first leaves it
without the clocks, resets and NoC configuration it needs.

Gate a dependent member's qcom_pas_start() on the root having started.
The root being enabled in DT does not imply it has already bound, as
probe order between the two is not guaranteed, so fail the boot if the
root has not bound rather than dereferencing it. If the root has bound
but is not running yet, wait briefly on a completion the root signals
from its own qcom_pas_start(), so that a member racing the root through
a restart does not fail outright.

The completion starts out signaled, since a member may be attached to
already-running firmware at probe, and is only cleared once the root
actually goes down. A dependent member's boot racing the root's stop can
therefore still observe a stale completion, in which case it falls back
to failing on the root's state.

Assisted-by: LLM
Link: https://lore.kernel.org/r/20260815132541.1575121-7-shengchao.guo@oss.qualcomm.com
Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
… ADSP clusters

The firmware of a Nord HPASS ADSP cluster cannot tolerate one member
being stopped or restarted independently of the others: doing so leaves
sysmon/glink_ssr notify requests to siblings timing out, and the whole
cluster unable to recover without manually stopping all three and
restarting them in dependency order.

Coordinate an explicit stop or crash of any member across the whole
cluster in two phases, since hardware testing showed that whichever
member's PAS/TZ hardware power-off happens chronologically last always
fails its own graceful shutdown ack (both the sysmon SSCTL QMI ack and
the SMEM-bit/IRQ ack), regardless of whether that member is the cluster
root.

Phase 1 fans the stop out to every participant concurrently via a
per-member work item and waits, at a barrier, for every participant to
finish requesting and awaiting its own graceful ack while the whole
cluster is still fully powered. Only once every participant has cleared
the barrier does phase 2 let each of them proceed to its actual PAS/TZ
hardware power-off, so no member is ever asking firmware to ack a
shutdown after a sibling's hardware is already gone. The fan-out has to
be deferred to a work item rather than calling rproc_shutdown() inline,
because qcom_pas_stop() runs with the remoteproc core holding the
stopping member's own rproc->lock, and reaching for a sibling's
rproc->lock from inside that critical section would risk an ABBA
deadlock against a concurrent operation on that sibling.

Membership in a round is decided once, by
qcom_pas_cluster_member_stops(), and recorded per member, so that the
participant count and the two counters it seeds can never diverge. The
crashed member that triggered the round is a participant even though its
rproc->state is still RPROC_CRASHED -- the core only sets RPROC_OFFLINE
after ops->stop() returns -- while a sibling crashing concurrently is
deliberately excluded, being already torn down by its own recovery.

On a crash, cascade the stop the same way but also auto-restart the
whole cluster root-first once every participant has fully powered off,
reusing the root_booted completion to keep non-root members'
qcom_pas_start() from racing ahead of the root's boot. An explicit stop
leaves the ordered restart to users or higher-level policy.

Devices without "qcom,cluster-root" are completely unaffected, since
qcom_pas.cluster stays NULL for them.

Assisted-by: LLM
Link: https://lore.kernel.org/r/20260815132541.1575121-8-shengchao.guo@oss.qualcomm.com
Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
Add support for additional Hexagon ADSP cores on Nord (adsp1/adsp2),
which sit alongside the existing adsp0 as HPASS cluster members.

Link: https://lore.kernel.org/r/20260815132541.1575121-9-shengchao.guo@oss.qualcomm.com
Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
Add device tree nodes to support ADSP1/2 which share HPASS clock/reset/NoC
resources with ADSP0 and must boot after it. Give all three a
qcom,cluster-root property so that they form one cluster which boots
ADSP0 first and crashes or stops as a single unit. ADSP1/2 reference
ADSP0, which owns those shared resources, and ADSP0 references itself, so
that every member of the cluster declares its own membership rather than
leaving the owner's implicit.

Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
Enable ADSP1 and ADSP2 remoteproc on the Nord RRD board.

Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
Enable ADSP1 and ADSP2 remoteproc on the Nord Ride SX board.

Signed-off-by: Shawn Guo <shengchao.guo@oss.qualcomm.com>
@apateriy-qcom
apateriy-qcom force-pushed the nord-staging-cluster-190826 branch from e66f41a to a5391f8 Compare August 19, 2026 12:37
@Komal-Bajaj
Komal Bajaj (Komal-Bajaj) merged commit 1f3a5a8 into qualcomm-linux:staging/nord Aug 19, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants