================================== Clock tree — GCC, domain CCs, RPMh ================================== The clock controllers a bootloader has to bring up (or inherit) before any bus, storage or display works. The SM6350 clock tree has four layers: fixed **sources** (the board crystal and the sleep clock), the **RPMh** clocks voted through the RSC/AOP, the **GCC** global controller, and per-block **domain controllers** (GPU/display/video/camera/NPU). CPU and L3 clocks are separate, driven by the OSM/EPSS hardware. Everything here is from ``artifacts/boot_a/board.dts`` and the XBL ``uefiplat.cfg`` MMAP; every controller base is corroborated by the XBL map. Sources ======= .. list-table:: :header-rows: 1 :widths: 22 18 20 40 * - Node - Compatible - Frequency - Role * - ``xo-board`` - ``fixed-clock`` - **76.8 MHz** (``0x493E000``) - the board crystal reference; the 19.2 MHz CXO domain distributed to PHYs and PMICs derives from it * - ``sleep-clk`` - ``fixed-clock`` - **≈32.768 kHz** (``0x7FFC`` = 32 764) - the always-on sleep clock * - ``mpm2-sleep-counter`` - ``qcom,mpm2-sleep-counter`` - ``0xC221000`` - the sleep-clock counter (XBL MMAP ``SLP_CNTR``) GCC — the global clock controller ================================= ``qcom,lagoon-gcc`` (also ``"syscon"``), **``0x100000`` size ``0x1F0000``**, ``phandle 0x1f`` — ``#clock-cells = 1`` and ``#reset-cells = 1`` (it is both the clock and the reset provider). XBL MMAP: ``"GCC CLK CTL" 0x00100000 size 0x200000``. GCC owns the gates and root clock generators (RCGs) for the peripheral fabric — every consumer in the storage and pin docs indexes into it: - **UFS** host + PHY clocks (ids ``0x6E``–``0x79``) and the ``core_reset`` BCR (reset id ``0x04``); see :doc:`storage`. - **SDCC1/2** iface/core/ice clocks (ids ``0x65``–``0x6B``); see :doc:`storage`. - **QUP** SE clocks for all fifteen serial engines, including the console UART on ``qup13`` (:doc:`/boot/qup-buses`). - **USB**, NoC config clocks, and the ``cfg_ahb`` feed into each domain CC (e.g. VIDEOCC's ``cfg_ahb_clk`` = gcc id ``0x86``). The clock ids are opaque enums of the ``qcom,lagoon-gcc`` driver (the provider only declares ``#clock-cells = 1``); the tree references them numerically. A replacement bootloader ungates the same gcc ids XBL used to reach the console and UFS. Domain clock controllers ======================== Each big block has its own CC, fed a ``cfg_ahb`` reference from GCC and voting its own rails. All are ``…"syscon"`` with ``#clock-cells = 1`` + ``#reset-cells = 1``: .. list-table:: :header-rows: 1 :widths: 18 24 16 42 * - Controller - Node / base - XBL MMAP - Powers * - **GPUCC** - ``qcom,lagoon-gpucc`` ``0x3D90000``/``0x9000`` - ``GPU_CC`` - Adreno A619 + GMU (:doc:`gpu`) * - **DISPCC** - ``qcom,lagoon-dispcc`` ``0xAF00000``/``0x20000`` - ``DISP_CC`` - DPU / DSI → e-ink pipeline (:doc:`/display/panel`) * - **VIDEOCC** - ``qcom,lagoon-videocc`` ``0xAAF0000``/``0x10000`` - ``VIDEO_CC`` - Venus video codec (``cfg_ahb_clk`` = gcc ``0x86``) * - **CAMCC** - ``qcom,lagoon-camcc`` ``0xAD00000``/``0x16000`` - ``TITAN_CAM_CC`` - camera (Titan ISP) — **unused** (:doc:`absent-hardware`) * - **NPUCC** - ``qcom,lagoon-npucc`` ``0x9980000``/``0x10000`` (+3 windows) - ``NPU_CC`` - NPU / neural DSP. Extra windows ``0x9800000``, ``0x9810000`` and an 8-byte fuse window at ``0x7841E0`` inside the security-control/QFPROM region (``0x780000``, :doc:`/open-questions`) RPMh clocks and AOP-CC ====================== The shared / always-on clocks are not memory-mapped controllers — they are *voted* through the RPMh path (APSS RSC → AOP), so their nodes carry no ``reg``: - ``qcom,lagoon-rpmh-clk`` (``phandle 0x1e``, ``#clock-cells = 1``) — the RPMh clock provider. Clock **id 0** is the CXO; id ``0x14`` is the UFS/PHY reference (:doc:`storage`). Peripherals request these and the RSC aggregates the votes to AOP (:doc:`/soc/aop`). - ``qcom,aop-qmp-clk`` (``qcom,aopcc``, ``phandle 0x1d``) — the QDSS / AOP clock, driven over the **AOP QMP mailbox** (``mboxes = <0x02 0x00>``) rather than a register block. **PMIC clock dividers.** Three PMICs expose a ``qcom,spmi-clkdiv`` at SPMI offset ``0x5B00`` — ``pm6350_div_clk1``, ``pm7250b_div_clk1``, ``pm6150l_div_clk1`` — each fed from the RPMh CXO (``clocks = ``). These are the divided sleep/RF clocks the PMICs hand to off-die radios (:doc:`/soc/pmic`). CPU and L3 clocks (OSM / EPSS) ============================== The eight CPUs are **not** clocked by GCC. They use the on-die OSM/EPSS DCVS hardware: - ``qcom,cpufreq-hw`` — two frequency domains: ``freq-domain0`` at **``0x18323000``** and ``freq-domain1`` at **``0x18325800``**. The tree splits the cores by ``capacity-dmips-mhz``: ``cpu@0``–``cpu@500`` at **1024** (six efficiency cores) and ``cpu@600``/``cpu@700`` at **1894** (two performance cores) — the SM6350's 6 + 2 Kryo 660 (A55/A77) arrangement. - Per-cluster clock control (XBL MMAP): ``SILVER_CLK_CTL 0x18280000``, ``GOLD_CLK_CTL 0x18282000``, ``L3_CLK_CTL 0x18284000``, ``GOLDPLUS_CLK_CTL 0x18286000``, each with an adaptive-clock-distribution block (``SILVER_ACD 0x18290000``, ``GOLD_ACD``, ``GOLDPLUS_ACD``, ``L3_ACD``). ``GOLDPLUS`` is a reference-design prime-core slot, unpopulated on lagoon. - ``APSS_RSC_RSCCR 0x18200000`` coordinates the CPU/L3 rail states; ``RPMH_CPRF_CPRF 0xC200000`` is the CPR (closed-loop voltage) block for the RPMh rails. What a bootloader must do ========================= XBL has already enabled the XO, brought the RPMh/RSC path up, and ungated the GCC clocks it needed to read UFS and drive the console; those clocks are still running at ABL hand-off (:doc:`/boot/below-uefi`). A bootloader that **inherits** XBL state has a live clock tree. A **from-scratch** bootloader would need, in order (an engineering inference from the DTB/XBL map, not a sequence that has been tested against actual from-scratch bootloader code): start the XO, vote the RPMh CXO through the RSC, ungate the GCC console-UART (``qup13``) and UFS gates, then bring up the UFS PHY reference (rpmh id ``0x14``) before the storage sequence in :doc:`storage`. Domain CCs (GPU/DISP/VIDEO/CAM/NPU) are only needed by their respective blocks and are not on the boot path. Static end ========== The controllers, their bases, the source frequencies, the CPU-domain split and the vote topology are all fixed from the tree and XBL map. The **live gate/RCG state** (which clock is on, at what rate, at any moment) is a set of runtime register values in each CC window; those windows are ``NS_DEVICE`` (XPU-open) so they are readable on a live device, but they are not static data and change as drivers vote. The per-controller *clock-id → leaf* tables live in the ``qcom,lagoon-*cc`` kernel drivers, not in this dump. Provenance ========== :Source: ``artifacts/boot_a/board.dts`` (``qcom,lagoon-{gcc,gpucc,dispcc,videocc, camcc,npucc}``, ``qcom,lagoon-rpmh-clk``, ``qcom,aop-qmp-clk``, ``xo-board`` / ``sleep-clk``, ``qcom,cpufreq-hw``, ``qcom,spmi-clkdiv``, ``cpu@*`` capacities) and ``_READONLY/lun1/xbl_a.bin`` (``uefiplat.cfg`` MMAP for every CC base + the CPU/L3 CLK_CTL/ACD windows). :Method: DTB node reading + XBL MMAP cross-check; frequencies decoded from the ``fixed-clock`` values. No code executed. :Cross-refs: :doc:`storage` (UFS/SDCC clock ids), :doc:`/boot/qup-buses` (QUP SE clocks), :doc:`/soc/aop` (RSC/RPMh vote path), :doc:`gpu` (GPUCC), :doc:`/display/panel` (DISPCC), :doc:`/soc/pmic` (PMIC clkdivs), :doc:`absent-hardware` (CAMCC).