Uplink Power Control in 5G NR
Open- and closed-loop power control for PUSCH, PUCCH and PRACH.
Uplink power control is how the UE decides how loud to shout. Too quiet and the gNB cannot decode you; too loud and you drown out your neighbours and flatten your battery. 5G NR (TS 38.213) tunes every uplink transmission — PUSCH, PUCCH, SRS and the PRACH preamble — so it arrives at the gNB just strong enough, and no stronger, all while respecting the UE's hard power ceiling P_CMAX.
Introduction
Uplink power control is the set of physical-layer procedures (TS 38.213) by which the UE computes, for every uplink transmission occasion, exactly how many dBm to radiate. It runs continuously the whole time the UE is transmitting — from the very first PRACH preamble during random access, through every scheduled PUSCH and PUCCH in RRC_CONNECTED, to each SRS sounding burst.
It sits at the boundary between what the UE can see and what only the gNB can see. The UE knows how weak the downlink sounds to it (pathloss) and how many resources it was granted; the gNB knows how the UE's signal actually arrives at its receiver. Power control combines both: an open loop the UE computes for itself, and a closed loop the gNB steers with correction commands. The accuracy tolerances and the enumerated value sets behind these procedures live in TS 38.101.
It matters because the uplink is interference-limited and battery-limited at the same time. Every extra dB a UE transmits buys it a little SINR but costs its neighbours interference and costs its own battery life. Get power control wrong and you either lose cell-edge users (too quiet) or collapse capacity and drain handsets (too loud). Get it right and dozens of UEs at wildly different distances all arrive at the gNB cleanly decodable.
On this page
Why uplink power control is needed
In plain words: imagine a room where dozens of people at different distances all speak to one listener at once. Someone standing right next to the listener only needs to whisper; someone across the room must speak up. If everyone shouted, the listener would hear only noise, and everyone's voice would give out. Power control is the rule that tells each speaker to be exactly as loud as needed to be heard — and no louder.
The downlink is the easy direction: one base station transmits and it has plenty of power and a clean view of the whole cell. The uplink is the hard direction — many battery-powered UEs at wildly different distances all share the same cell, and their signals collide at the gNB's receiver. Power control solves three problems at once.
A set of procedures that set the transmit power of every uplink physical signal and channel — PUSCH, PUCCH, SRS and the PRACH preamble — per carrier, per bandwidth part (BWP), bounded by the UE's configured maximum output power P_CMAX.
Manage interference: a near UE blasting at full power raises the noise floor for everyone (the "near-far" problem). Save UE power: transmitting only as much as needed extends battery life. Meet the target SINR: the gNB needs a minimum signal-to-interference-plus-noise ratio to decode at the chosen modulation and coding.
Two loops working together: an open loop where the UE estimates its own pathloss from downlink reference signals and compensates for it, and a closed loop where the gNB sends explicit correction commands (TPC) whenever the open-loop estimate is not quite right.
The one-line intuition: open loop is the UE's best guess based on how weak the cell sounds to it; closed loop is the gNB nudging that guess up or down based on what it actually receives at its antenna.
Every uplink physical channel gets its own power-control chain. They share the same two-loop philosophy, but each has its own target level, its own pathloss reference, and its own state. Understanding one — PUSCH — teaches you all of them, because PUCCH and SRS are variations on the same equation and the PRACH preamble is the special case that runs before any loop exists.
Open-loop control — compensate for your own pathloss
The UE cannot measure how strong its own signal arrives at the gNB, but it can measure how weak the gNB's downlink reference signals arrive at it. That measured pathloss (PL) is the heart of open-loop control. The UE takes the reference signal's known transmit power, subtracts the received power (RSRP) it measured, and the difference is the one-way pathloss in dB.
Which reference signal to measure is not left to chance: the network points the UE at a specific downlink RS through pathlossReferenceRS, which may be an SSB or a CSI-RS resource. In beam-based FR2 this matters enormously — the pathloss on one beam is nothing like the pathloss on another, so each uplink beam is tied to the pathloss reference that shares its spatial direction. Up to a handful of pathloss reference RSs can be configured per BWP (PUSCH-PathlossReferenceRS), each with its own index the grant can point at.
Two parameters then shape the open-loop target, both signalled by the network:
| Parameter | Meaning | Typical range |
|---|---|---|
P0 | The target received power the gNB wants to see at its antenna, per resource block. It is the sum of a cell-wide nominal component (P0-nominal, broadcast) and a UE-specific component (P0-UE, dedicated). Raising P0 asks every UE to arrive louder — better SINR, more interference, shorter battery life. | p0-nominal roughly −202 to +24 dBm in 1 dB steps; p0-UE an offset of about −16 to +15 dB. |
alpha (α) | The fractional pathloss compensation factor. alpha=1 means fully compensate pathloss so all UEs arrive at the same level ("full compensation"). alpha<1 means far UEs deliberately arrive a bit weaker ("fractional") — this caps how much power cell-edge UEs inject into neighbours, trading their throughput for lower system interference. | Enumerated set {0, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}. |
Why fractional? If every UE fully compensated pathloss, a cell-edge UE with 120 dB of loss would transmit at full blast, spilling huge interference into adjacent cells. Setting alpha around 0.7–0.9 lets far UEs "give up" a little SINR so the whole network runs cleaner and total cell capacity rises.
The open-loop baseline is therefore just P0 + alpha·PL. Everything else in the full power equation — the bandwidth term, the modulation term, and the closed-loop correction — is layered on top of this baseline. A UE can be given several open-loop parameter sets (several P0/alpha pairs via P0-PUSCH-AlphaSet, each with its own pathlossReferenceRS) and the scheduling grant selects which one applies, so different beams or panels can run entirely different open-loop budgets.
Closed-loop control — the gNB nudges you
Open loop is only an estimate. Pathloss measurements lag reality, the UE's power amplifier has tolerances, and interference at the gNB fluctuates in ways the UE can never see. So the gNB watches what it actually receives and issues corrections as Transmit Power Control (TPC) commands, carried in the DCI that schedules your uplink.
Each TPC command is a 2-bit field — a small step from the set {−1, 0, +1, +3} dB in accumulated mode (or the absolute set {−4, −1, +1, +4} dB) — that the UE folds into a running closed-loop adjustment term, written f(i) for PUSCH and g(i) for PUCCH.
To correct residual error the open loop cannot see: real interference at the gNB receiver, amplifier drift, calibration error, and rapidly changing channels. It is the fine-tuning knob sitting on top of the coarse open-loop estimate.
Two modes. In accumulated mode the steps add up over time, so a run of +1s slowly ramps you up. In absolute mode each command replaces the previous adjustment outright. Which mode applies is set by tpc-Accumulation; accumulation is the common case.
TPC reaches the UE two ways. The dedicated way is a field inside the same scheduling DCI that grants the transmission — DCI format 0_0/0_1/0_2 for PUSCH, and 1_0/1_1/1_2 for PUCCH, monitored in the UE-specific search space on PDCCH. The group-common way is a special DCI addressed to many UEs at once: DCI format 2_2, scrambled by TPC-PUSCH-RNTI or TPC-PUCCH-RNTI in a Type3-PDCCH common search space, where each UE reads its own tpc-Index position. Format 2_2 lets the gNB tweak a whole group's power without spending a scheduling grant on each one.
| Open loop | Closed loop | |
|---|---|---|
| Who decides | The UE, from its own measurement | The gNB, from what it receives |
| Based on | Downlink pathloss (PL) via pathlossReferenceRS | Actual received SINR / power at the gNB |
| Formula term | P0 + alpha·PL | f(i) for PUSCH, g(i) for PUCCH |
| Carried by | RRC / broadcast configuration | TPC field in scheduling DCI, or group-common DCI format 2_2 |
| Update rate | Slow (measurement filtering) | Fast (per grant / per command) |
| Correction style | Absolute target level | Accumulated steps, or absolute per command |
Spec note (TS 38.213): the UE can maintain more than one closed-loop process — up to two independent f(i)/g(i) accumulators. The grant selects which one to update and apply via a closed-loop index (tied to the SRI / sri-PUSCH-PowerControl mapping), so different uplink beams or panels are tracked independently and do not corrupt each other's history.
LTE → NR: LTE had a single closed-loop process per channel and a fixed pathloss reference (the cell-specific CRS). NR generalises both: multiple f(i)/g(i) accumulators and a per-BWP set of configurable pathlossReferenceRS (SSB or CSI-RS), because beamforming means "the cell's pathloss" is no longer a single number.
The PUSCH power formula
All of the above lands in one equation. For PUSCH transmission occasion i, on carrier f of serving cell c, the UE sets its transmit power (in dBm) as:
Reading it term by term:
| Term | What it does |
|---|---|
P_CMAX | The UE's configured maximum output power for this carrier. The min() means you never exceed it — if the sum wants more, you clip and lose full compensation ("power-limited"). Bounded above by the UE power class (e.g. 23 dBm for a class-3 handset) minus any configured backoff. |
P0 | Open-loop target level = P0-nominal (cell-wide, broadcast) + P0-UE (dedicated). Where the gNB wants your per-RB received power to land. |
| 10·log10(2μ·MRB) | Bandwidth scaling. More scheduled resource blocks M_RB means more total power to keep the per-RB received level on target; μ (mu) is the numerology / subcarrier-spacing index (0–4 for 15–240 kHz SCS), so wider subcarriers count too. |
alpha·PL | Fractional pathloss compensation: multiply measured pathloss by α (the enumerated 0–1 set). Together with P0 this is the open-loop core. |
| ΔTF | The transport-format offset. Higher-order modulation and coding rate need more SINR, so a bit more power; derived from the MCS via deltaMCS. Set to 0 when deltaMCS is disabled. |
| f(i) | The accumulated (or absolute) closed-loop TPC adjustment for the selected closed-loop process. |
Q&A-ready: P0 + alpha·PL is the open loop; the bandwidth and transport-format terms account for how much and how densely you are sending; f(i) is the gNB's live correction; and min(P_CMAX, …) is the ceiling. When you hit that ceiling the excess is simply lost, which is exactly what power-headroom reporting exists to warn about.
PUCCH and SRS power control
PUCCH carries uplink control information — HARQ ACK/NACK, scheduling requests, and CSI reports — and it must be very reliable, because a dropped ACK/NACK poisons the HARQ loop. Its power formula has the same shape as PUSCH but with two important differences: there is no variable bandwidth term (a PUCCH resource has a format-fixed size), and instead of a transport-format offset it uses a format-dependent offset plus a term for how many UCI bits it is carrying.
Term by term: P0-PUCCH is again P0-nominal-PUCCH + P0-UE-PUCCH; pathloss is compensated fully (effectively α=1 — control must not be sacrificed the way cell-edge data can be); Δ_F-PUCCH(F) is a per-format power offset that reflects how robust each PUCCH format is (a short Format 0/2 versus a long, DMRS-rich Format 1/3/4 need different power for the same reliability); Δ_TF scales power up with the number of UCI bits carried; and g(i) is the PUCCH closed-loop accumulator, driven by TPC in DCI format 1_0/1_1/1_2 or in group-common DCI format 2_2.
SRS (Sounding Reference Signal) lets the gNB estimate the uplink channel for scheduling and beam management. Its power formula mirrors PUSCH: its own P0-SRS and alpha_SRS (in SRS-ResourceSet), a bandwidth term for the number of sounded RBs, and a closed-loop term h(i) that can be configured (via srs-PowerControlAdjustmentStates) to share PUSCH's accumulator (so sounding and data track together) or run separately.
| Signal | How its power is set |
|---|---|
PUSCH | Full formula: open loop (P0-PUSCH, alpha) + bandwidth term + transport-format Δ_TF + closed loop f(i). |
PUCCH | P0-PUCCH, full pathloss compensation, per-format offset Δ_F-PUCCH, UCI-bit term, closed loop g(i). No variable bandwidth term. |
SRS | Own P0-SRS and alpha_SRS, bandwidth term, closed loop h(i) — optionally aligned to PUSCH. |
| PRACH preamble | No pathloss-driven loop yet: open-loop target + estimated PL, then power ramping across attempts (see below). |
Prioritisation: when the sum of all uplink powers in a slot would exceed P_CMAX, the UE scales down — but PUCCH and PRACH are protected first, because dropping an ACK/NACK or a preamble is far more damaging than shaving a little PUSCH. PUSCH carrying UCI is protected before PUSCH carrying only data.
PRACH ramping and power headroom
Before a UE is connected it has no C-RNTI, no scheduling grant, and therefore no closed loop — so the PRACH preamble uses a different mechanism entirely: open-loop targeting plus power ramping. The UE first computes a starting power from a target level and its own pathloss estimate:
where preambleReceivedTargetPower is the received level the gNB wants the preamble to arrive at (broadcast in RACH-ConfigCommon), and PL is the pathloss estimated from the SSB the UE selected. If no Random Access Response (RAR) arrives within the window, the UE assumes it was too quiet, steps its power up by powerRampingStep (enumerated {0, 2, 4, 6} dB), and retransmits — repeating until it either gets a RAR or reaches preambleTransMax attempts, at which point it declares a random-access problem to higher layers.
Spec note: the ramping counter (PREAMBLE_POWER_RAMPING_COUNTER) only advances when the UE actually retransmits at the same beam/SSB. If the UE reselects a different SSB beam, the counter is not incremented so switching beams does not unfairly keep escalating power. Once random access completes, the UE transitions to the normal PUSCH/PUCCH closed loops.
Whatever the channel, the UE eventually runs into P_CMAX — the point where the formula asks for more power than the amplifier can deliver. The gNB needs to know when that happens, because a power-limited UE cannot benefit from a larger grant. That is the job of the Power Headroom Report (PHR).
PHR is a MAC Control Element reporting the difference, in dB, between P_CMAX and the power the UE would have used for its current transmission — how much headroom it has left. The reported value maps to a range of roughly −32 to +38 dB.
Positive headroom means the UE could transmit on more RBs or at higher MCS — the scheduler can grant more. Negative or zero headroom means the UE is already clipping; a bigger grant would only spread the same power thinner and hurt.
Triggered by phr-Config conditions: a periodic timer (phr-PeriodicTimer), a pathloss change beyond phr-Tx-PowerFactorChange since the last report (dl-PathlossChange), or a prohibit timer (phr-ProhibitTimer) expiring.
The link back to power control: PHR is the feedback that closes the scheduling loop the way TPC closes the power loop. Power control decides how loud the UE transmits; PHR tells the scheduler whether the UE has room to be told to transmit more.
⚠ Common pitfalls / gotchas
- Confusing
P0(a per-RB received target at the gNB) with the UE's transmit power.P0is where the signal should land, not what the UE radiates. - Assuming the bandwidth term scales with the whole carrier. It scales with
M_RB— the scheduled RBs in this grant — so a UE granted fewer RBs transmits less total power for the same per-RB target. - Forgetting that a wrong
pathlossReferenceRS(pointing at a beam the UE is not actually facing in FR2) yields a pathloss estimate that is wildly off, so the open-loop baseline is wrong before the closed loop even starts correcting. - Reading a persistently low or negative
PHRas a bug. It usually means the UE is genuinely power-limited (cell edge, high MCS, many RBs) and the scheduler should back off the grant, not push harder. - Mixing accumulated and absolute
TPCinterpretation: in accumulated mode a lone "0" step is a hold, but in absolute mode the same codepoint is an absolute setting — misreadingtpc-Accumulationcorrupts the whole f(i) history.
Open loop and closed loop together
The figure shows the two loops feeding one power decision: the UE estimates pathloss from the downlink reference signal to set the open-loop baseline, transmits, and the gNB returns TPC commands that fold into the closed-loop term while PHR flows back to the scheduler.
Summary
Uplink power control is two cooperating loops bounded by one ceiling. The open loop is the UE's own estimate — measure downlink pathloss against pathlossReferenceRS, aim for the gNB's per-RB target P0, and compensate pathloss by a fraction alpha. The closed loop is the gNB's correction — TPC commands in scheduling DCI (or group-common DCI format 2_2) that accumulate into f(i)/g(i). The full PUSCH formula stacks a bandwidth term and a transport-format term on that base, and the whole sum is clipped at P_CMAX.
PUCCH and SRS reuse the same shape with their own parameters — PUCCH compensates pathloss fully and protects control, SRS can track PUSCH. The PRACH preamble runs before any loop exists, so it uses open-loop targeting plus power ramping. And PHR closes the circle: it tells the scheduler when the UE has hit its ceiling and a bigger grant would only hurt. The practical mantra: arrive at the gNB just decodable, never louder, and let the closed loop mop up what the estimate missed.
Q. What is the difference between open-loop and closed-loop uplink power control?
A. Open loop is the UE's own estimate: it measures downlink pathloss from pathlossReferenceRS and sets power as P0 + alpha·PL. Closed loop is the gNB's correction on top: TPC commands in DCI adjust a running term f(i)/g(i), accumulated or absolute, to fix residual error the UE cannot see.
Q. What does alpha control, and why use a value below 1?
A. alpha is fractional pathloss compensation. At 1, all UEs arrive at the same level but cell-edge UEs transmit at high power and interfere with neighbours. Below 1, far UEs arrive weaker, sacrificing some SINR to reduce inter-cell interference and lift overall cell capacity.
Q. How do the PUSCH and PUCCH power formulas differ?
A. PUSCH has a variable bandwidth term 10·log10(2μ·M_RB) and a transport-format offset from the MCS. PUCCH has no variable bandwidth term (its size is fixed by format), compensates pathloss fully, and instead uses a format-dependent offset Δ_F-PUCCH plus a term for the number of UCI bits, with its own accumulator g(i).
Q. How does PRACH preamble power control differ from PUSCH?
A. The UE is not connected yet, so there is no TPC closed loop. It uses power ramping: begin at preambleReceivedTargetPower + estimated PL, and if no RAR arrives, retransmit a step higher (powerRampingStep) up to preambleTransMax attempts.
Q. What is a Power Headroom Report and why does the scheduler need it?
A. PHR is a MAC CE reporting the gap between P_CMAX and the power the UE would use. Positive headroom tells the scheduler the UE can take a bigger grant or higher MCS; near-zero or negative headroom means the UE is power-limited and a larger grant would not help.
Where this connects
Power control sets how loud the UE transmits; three neighbours set when and what. Getting time-aligned at the gNB is a related uplink discipline, the UCI carried on PUCCH is a protected special case of this power budget, and the very first uplink power decision happens during random access.