Skip to content

Commit c501081

Browse files
ananglcarlescufi
authored andcommitted
soc: nrf53: Fix extraction of the XOSC32MTRIM.SLOPE bitfield
The value in this bitfield is provided in the two's complement form, so it requires special handling. Previously, it was read as just an unsigned value and this could result in a wrongly computed CAPVALUE. Signed-off-by: Andrzej Głąbek <[email protected]>
1 parent 6cbb3f5 commit c501081

File tree

1 file changed

+15
-4
lines changed
  • soc/arm/nordic_nrf/nrf53

1 file changed

+15
-4
lines changed

soc/arm/nordic_nrf/nrf53/soc.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,16 +134,27 @@ static int nordicsemi_nrf53_init(const struct device *arg)
134134
#if defined(CONFIG_SOC_HFXO_CAP_INTERNAL)
135135
/* This register is only accessible from secure code. */
136136
uint32_t xosc32mtrim = soc_secure_read_xosc32mtrim();
137+
/* The SLOPE field is in the two's complement form, hence this special
138+
* handling. Ideally, it would result in just one SBFX instruction for
139+
* extracting the slope value, at least gcc is capable of producing such
140+
* output, but since the compiler apparently tries first to optimize
141+
* additions and subtractions, it generates slightly less than optimal
142+
* code.
143+
*/
144+
uint32_t slope_field = (xosc32mtrim & FICR_XOSC32MTRIM_SLOPE_Msk)
145+
>> FICR_XOSC32MTRIM_SLOPE_Pos;
146+
uint32_t slope_mask = FICR_XOSC32MTRIM_SLOPE_Msk
147+
>> FICR_XOSC32MTRIM_SLOPE_Pos;
148+
uint32_t slope_sign = (slope_mask - (slope_mask >> 1));
149+
int32_t slope = (int32_t)(slope_field ^ slope_sign) - (int32_t)slope_sign;
150+
uint32_t offset = (xosc32mtrim & FICR_XOSC32MTRIM_OFFSET_Msk)
151+
>> FICR_XOSC32MTRIM_OFFSET_Pos;
137152
/* As specified in the nRF5340 PS:
138153
* CAPVALUE = (((FICR->XOSC32MTRIM.SLOPE+56)*(CAPACITANCE*2-14))
139154
* +((FICR->XOSC32MTRIM.OFFSET-8)<<4)+32)>>6;
140155
* where CAPACITANCE is the desired capacitor value in pF, holding any
141156
* value between 7.0 pF and 20.0 pF in 0.5 pF steps.
142157
*/
143-
uint32_t slope = (xosc32mtrim & FICR_XOSC32MTRIM_SLOPE_Msk)
144-
>> FICR_XOSC32MTRIM_SLOPE_Pos;
145-
uint32_t offset = (xosc32mtrim & FICR_XOSC32MTRIM_OFFSET_Msk)
146-
>> FICR_XOSC32MTRIM_OFFSET_Pos;
147158
uint32_t capvalue =
148159
((slope + 56) * (CONFIG_SOC_HFXO_CAP_INT_VALUE_X2 - 14)
149160
+ ((offset - 8) << 4) + 32) >> 6;

0 commit comments

Comments
 (0)