Nord Clock driver Support - #40
Conversation
Align the Qualcomm clock driver filenames with the clk-<vendor> naming used by the rest of the clk subsystem, and with the clk_qcom.h header they implement. No functional change. Update sub.mk in the same commit so the tree still builds; renaming the sources alone leaves srcs-y pointing at the old paths. Signed-off-by: Naresh Nunna <nnunna@qti.qualcomm.com> Assisted-by: Claude:claude-opus-5
Add an API to copy a resource's auxiliary data blob by resource ID. For ARC resources this is the list of corner levels the rail supports, which RPMh commands index into rather than accepting a raw voltage. This is a prerequisite for the QUP SE clock driver's CX/MX voltage vote, which resolves a rail's supported-corner ordinal list via this API before voting a corner over RPMh. copy_aux_data() previously clamped the copy to the caller's buffer and returned success, so a caller with an undersized buffer received a silently truncated blob it had no way to detect. Return TEE_ERROR_SHORT_BUFFER with the required size instead, and copy nothing. Both existing callers query metadata only (NULL data buffer, zero length) and never reach this path. Also fix cmd_db_get_entry_by_res_id() to clear result->len on the zero-length-entry path, which cmd_db_get_aux() exercises. Signed-off-by: Naresh Nunna <nnunna@qti.qualcomm.com> Assisted-by: Claude:claude-opus-5
Register each QUPv3 serial-engine RCG on lemans as a standard struct clk with no parent (clk_ops: enable/disable/set_rate/get_rate), consumed on demand by a future TEE-side SPI/I2C driver via qcom_clk_get_by_name() (this platform has no secure DT, so DT-based acquire isn't available). set_rate walks a per-domain frequency-config table (mux/divider/MND/ DFS-index), and votes a CX/MX voltage corner via RPMh around the rate change -- raise before programming, lower after -- using an aggregate reference-counted vote model. The voltage vote requires cmd_db_get_addr()/cmd_db_get_aux() to resolve the rail's RPMh resource address and its supported-corner ordinal list, so CFG_QCOM_CMD_DB/ CFG_QCOM_RPMH_CLIENT are now force-enabled whenever CFG_QCOM_CLK_BSP=y (default y). CX and MX are voted as a pair, so a failure between the two would leave the rails disagreeing with the cached corner while the no-change shortcut suppressed the corrective re-vote. Track that mismatch and re-vote both rails on the next call. The rail-vote backend lives in clk-qcom-vreg.c behind the qcom_clk_vreg_vote() contract, so a non-RPMh target can supply its own without touching the RCG walker. The per-target domain table and frequency plans live in platform/<flavor>/clk-qcom-bsp.c, keeping the filename flavor-generic so enabling CFG_QCOM_CLK_BSP on another target needs no sub.mk change. Known gap, documented but not blocking: the voltage vote is bypassed on a hardware-driven DFS switch (it only covers explicit set_rate). Signed-off-by: Naresh Nunna <nnunna@qti.qualcomm.com> Assisted-by: Claude:claude-opus-5
The CBCR-to-CMD_RCGR distance used to derive one register's location from another is not architectural: it is 8 bytes on lemans but not constant across chipsets (nord's QUP SEs sit 0x10 apart, and nord's QUPv3 wrapper 3 keeps no fixed relation at all). Deriving offsets that way silently breaks on any target where the assumption doesn't hold. Give struct qcom_clk_domain and struct qcom_clk_src_vote a full physical address per register (cmd_rcgr_addr/cbcr_addr/vote_reg_addr) instead of one GCC-relative offset each, matching how the reference clock driver's own HWIO_<reg>_ADDR macros are built. Add struct qcom_clk_window so a domain names the register window its addresses fall inside rather than assuming a single global GCC base -- needed because some targets split their QUP SEs across more than one clock controller. The walker resolves each address against its domain's window and bounds-checks it before use. Convert lemans' header macros from GCC-relative offsets to (GCC_BASE + offset) form to match, and update its BSP table to the renamed struct fields. No functional change on lemans: GCC_BASE is still the only window, and every resolved address is identical to the previous offset-based one. Signed-off-by: Naresh Nunna <nnunna@qti.qualcomm.com> Assisted-by: Claude:claude-opus-5
Add Nord (wildcat) platform support for the QUPv3 serial-engine clock walker: quadrant-controller GCC bases/windows, cmd_db AOP message-RAM window and RPMh base, and the SOCCP PAS clock group needed by the walker's RPMh/cmd_db client path. Unlike lemans, Nord's cmd_db blob address is not fixed at build time -- AOP publishes it as a pointer word in AOP message RAM, so cmd_db_init() reads that pointer and maps the blob on the fly via core_mmu_add_mapping() instead of the static register_phys_mem()/ phys_to_virt() path lemans uses. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
| srcs-y += clock-qcom.c | ||
| srcs-$(CFG_QCOM_PAS_PTA) += platform/$(PLATFORM_FLAVOR)/clock-qcom-pas.c | ||
| srcs-y += clk-qcom.c | ||
| srcs-$(CFG_QCOM_PAS_PTA) += platform/$(PLATFORM_FLAVOR)/clk-qcom-pas.c |
There was a problem hiding this comment.
Can we leave clock-qcom-pas.c and not change anything here for PIL?
There was a problem hiding this comment.
This is just a file name change to align with optee overall driver naming structure among different vendors.
There was a problem hiding this comment.
I don't see pas code for other vendors, so may be let us leave the pass code rename.
| * rather than its own CBCR's CLK_ENABLE bit. CLK_OFF is still polled on the | ||
| * SE's own CBCR regardless, since the vote register has no status bit. | ||
| */ | ||
| static TEE_Result qcom_qup_clk_enable(struct clk *clk) |
There was a problem hiding this comment.
Why are we not having a common cbcr and need a qup clock enable?
There was a problem hiding this comment.
This is due to the optee framework registration, clients gets to use upstream clk enable API which gets linked to our internal qti API. client would get clk handle by using clk_get_by_name and that would return pointer to a structure. with clock details... addr, vote addr and stuff.. this API would internally figure out the voting stuff..for enabling clock based on the data in the structure. the bare enable_cbcr API which is already present only tackles direct cbc address which is being used by pas so did not modify that ...since pas doesn't really use bsp to fit into this framework
| return ret < 0 ? TEE_ERROR_TIMEOUT : TEE_SUCCESS; | ||
| } | ||
|
|
||
| static void qcom_qup_clk_disable(struct clk *clk) |
There was a problem hiding this comment.
If you can have a common enable/disable of a clock.
| * revisions v1..v4. Offsets are relative to the domain's CMD_RCGR register | ||
| * (qcom_clk_domain.cmd_rcgr_offset, itself GCC-relative). | ||
| */ | ||
| #define QCOM_RCG_CFG_REG_OFFSET 0x4 |
There was a problem hiding this comment.
This is a common offset, so you can make a common offset.
|
how do I test this code? |
There was a problem hiding this comment.
Pull request overview
Adds Nord Qualcomm clock support, including QUPv3 clock domains, voltage voting, DFS, and SOCCP PAS control.
Changes:
- Adds Nord and Lemans QUP clock BSPs and shared clock-provider logic.
- Adds RPMh CX/MX voting and command-database auxiliary data access.
- Adds Nord platform addresses, build configuration, and SOCCP support.
Reviewed changes
Copilot reviewed 18 out of 20 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
core/include/drivers/qcom/cmd_db/cmd_db.h |
Declares auxiliary-data lookup API. |
core/include/drivers/clk_qcom.h |
Exposes BSP clock APIs and SOCCP group. |
core/include/drivers/clk_qcom_bsp.h |
Defines clock BSP data structures. |
core/drivers/qcom/cmd_db/cmd_db.c |
Supports dynamic database mapping and auxiliary data. |
core/drivers/clk/qcom/sub.mk |
Builds renamed driver and platform backends. |
core/drivers/clk/qcom/platform/nord/clock_group_qcom.h |
Defines Nord clock and reset registers. |
core/drivers/clk/qcom/platform/nord/clk-qcom-pas.c |
Implements SOCCP clock/reset sequencing. |
core/drivers/clk/qcom/platform/nord/clk-qcom-bsp.c |
Provides Nord QUP frequency plans and domains. |
core/drivers/clk/qcom/platform/lemans/clock_group_qcom.h |
Adds Lemans QUP register definitions. |
core/drivers/clk/qcom/platform/lemans/clk-qcom-pas.c |
Implements Lemans PAS clock/reset handling. |
core/drivers/clk/qcom/platform/lemans/clk-qcom-bsp.c |
Provides Lemans QUP clock domains. |
core/drivers/clk/qcom/platform/kodiak/clk-qcom-pas.c |
Moves Kodiak PAS implementation to renamed source. |
core/drivers/clk/qcom/clock-qcom.c |
Removes superseded clock driver source. |
core/drivers/clk/qcom/clk-qcom.c |
Adds shared QUP clock provider and DFS support. |
core/drivers/clk/qcom/clk-qcom-vreg.c |
Implements aggregate RPMh rail voting. |
core/drivers/clk/qcom/clk_qcom_vreg.h |
Declares rail-vote backend contract. |
core/arch/arm/plat-qcom/wildcat/nord/target.mk |
Enables Nord clock dependencies. |
core/arch/arm/plat-qcom/wildcat/nord/target_config.h |
Defines Nord hardware windows. |
core/arch/arm/plat-qcom/wildcat/arch_config.h |
Adds Wildcat AOP and RPMh addresses. |
core/arch/arm/plat-qcom/hoya/lemans/target.mk |
Enables Lemans QUP clock BSP dependencies. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| uint32_t res_hz = 0; | ||
| TEE_Result res = TEE_SUCCESS; | ||
|
|
||
| res = qcom_domain_set_rate(qup->domain, rate, &qup->corner, &res_hz); |
| REG_POLL_TIMEOUT(cbcr, 10 * 1000, 10, &ret, cbcr_branch_on); | ||
|
|
||
| return ret < 0 ? TEE_ERROR_TIMEOUT : TEE_SUCCESS; |
| qcom_qup_clks = calloc(bsp->n_domains, sizeof(*qcom_qup_clks)); | ||
| if (!qcom_qup_clks) | ||
| return TEE_ERROR_OUT_OF_MEMORY; |
| qup = clk->priv; | ||
| return qup->domain; |
| if (!buf || !len || !*len || *len > UINT32_MAX || | ||
| !is_valid_res_id(res_id)) | ||
| return TEE_ERROR_BAD_PARAMETERS; | ||
|
|
||
| result.len = *len; | ||
|
|
||
| mutex_lock(&query_db.lock); | ||
|
|
||
| if (!query_db.data) { | ||
| mutex_unlock(&query_db.lock); | ||
| return TEE_ERROR_BAD_STATE; | ||
| } | ||
|
|
||
| res = cmd_db_get_entry_by_res_id(res_id, &result, buf); | ||
| if (res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) | ||
| *len = result.len; |
Jorge A. Ramirez-Ortiz (@ldts) this is similar implementation for SPI driver consumption for serial engine qup clocks. the basic sanity is done but end to end use case would be tested along with SPI driver only. SSG team was asking for this not sure if they have any other dependency so raised the PR. |
|
So will you add the SPI driver to this PR? |
Right... the plan is to get this PR merged along with SPI driver. in the meanwhile if SSG really needs this for any other FBC activities, this can serve the requirement. we will work with buses team similar to lemans on Nord as well for getting this support merged. |
sure but we can not merge this code without the driver. both should be proposed as part of the same pull request. |
nnunna94, Would request you to please mark this PR as draft for now & once we have full E2E working piece we can mark it as "ready for review". Meanwhile interested (internal team/POCs) folks can still review the change when its draft and share comments to you. |
done |
No description provided.