1717
1818#include  <zephyr/devicetree.h> 
1919#include  <zephyr/kernel.h> 
20- #include  <zephyr/devicetree.h> 
2120#include  <zephyr/init.h> 
2221#include  <zephyr/logging/log.h> 
2322#include  <zephyr/cache.h> 
@@ -50,46 +49,43 @@ static inline void power_and_clock_configuration(void)
5049 */ 
5150#if  DT_ENUM_HAS_VALUE (LFXO_NODE , load_capacitors , internal )
5251	uint32_t  xosc32ktrim  =  NRF_FICR -> XOSC32KTRIM ;
53- 
54- 	uint32_t  offset_k  = 
55- 		(xosc32ktrim  &  FICR_XOSC32KTRIM_OFFSET_Msk ) >> FICR_XOSC32KTRIM_OFFSET_Pos ;
56- 
52+ 	/* The SLOPE field is in the two's complement form, hence this special 
53+ 	 * handling. Ideally, it would result in just one SBFX instruction for 
54+ 	 * extracting the slope value, at least gcc is capable of producing such 
55+ 	 * output, but since the compiler apparently tries first to optimize 
56+ 	 * additions and subtractions, it generates slightly less than optimal 
57+ 	 * code. 
58+ 	 */ 
5759	uint32_t  slope_field_k  = 
5860		(xosc32ktrim  &  FICR_XOSC32KTRIM_SLOPE_Msk ) >> FICR_XOSC32KTRIM_SLOPE_Pos ;
5961	uint32_t  slope_mask_k  =  FICR_XOSC32KTRIM_SLOPE_Msk  >> FICR_XOSC32KTRIM_SLOPE_Pos ;
6062	uint32_t  slope_sign_k  =  (slope_mask_k  -  (slope_mask_k  >> 1 ));
6163	int32_t  slope_k  =  (int32_t )(slope_field_k  ^ slope_sign_k ) -  (int32_t )slope_sign_k ;
62- 
64+ 	uint32_t  offset_k  = 
65+ 		(xosc32ktrim  &  FICR_XOSC32KTRIM_OFFSET_Msk ) >> FICR_XOSC32KTRIM_OFFSET_Pos ;
6366	/* As specified in the nRF54L15 PS: 
6467	 * CAPVALUE = round( (2*CAPACITANCE - 12) * (FICR->XOSC32KTRIM.SLOPE + 0.765625 * 2^9)/(2^9) 
6568	 *            + FICR->XOSC32KTRIM.OFFSET/(2^6) ); 
6669	 * where CAPACITANCE is the desired capacitor value in pF, holding any 
6770	 * value between 4 pF and 18 pF in 0.5 pF steps. 
6871	 */ 
6972
70- 	/* Encoding of desired capacitance (single ended) to value required for INTCAP core 
71- 	 * calculation: (CAP_VAL - 4 pF)* 0.5 
72- 	 * That translate to ((CAP_VAL_FEMTO_F - 4000fF) * 2UL) / 1000UL 
73- 	 * 
74- 	 * NOTE: The desired capacitance value is used in encoded from in INTCAP calculation formula 
75- 	 *       That is different than in case of HFXO. 
76- 	 */ 
77- 	uint32_t  cap_val_encoded  =  (((DT_PROP (LFXO_NODE , load_capacitance_femtofarad ) -  4000UL )
78- 				     *  2UL ) / 1000UL );
73+ 	uint32_t  lfxo_intcap_femto_f  =  DT_PROP (LFXO_NODE , load_capacitance_femtofarad );
7974
8075	/* Calculation of INTCAP code before rounding. Min that calculations here are done on 
8176	 * values multiplied by 2^9, e.g. 0.765625 * 2^9 = 392. 
8277	 * offset_k should be divided by 2^6, but to add it to value shifted by 2^9 we have to 
83- 	 * multiply it be 2^3. 
78+ 	 * multiply it be 2^3. Capacitance value passed to the formula is in femto Farads to 
79+ 	 * avoid floating point data type. Hence, offset_k needs to be multiplied by 1000. 
8480	 */ 
85- 	uint32_t  mid_val  =  (2UL  *  cap_val_encoded  -  12UL )  *  ( uint32_t )( slope_k   +   392UL )
86- 			    +  (offset_k  << 3UL );
81+ 	uint32_t  lfxo_intcap_mid_val  =  (2UL  *  lfxo_intcap_femto_f  -  12000UL )
82+ 			*  ( uint32_t )( slope_k   +   392UL )  +  (offset_k  << 3UL )  *   1000UL ;
8783
88- 	/* Get integer part of the INTCAP code  */ 
89- 	uint32_t  lfxo_intcap  =  mid_val  >>  9UL ;
84+ 	/* Get integer part of the INTCAP by dividing by 2^9 and convert to pico Farads.  */ 
85+ 	uint32_t  lfxo_intcap  =  lfxo_intcap_mid_val  /  512000UL ;
9086
91- 	/* Round based on fractional part */ 
92- 	if  (( mid_val   &   BIT_MASK ( 9 ))  >  ( BIT_MASK ( 9 ) /  2 ) ) {
87+ 	/* Round based on fractional part.  */ 
88+ 	if  (lfxo_intcap_mid_val  %  512000UL  >=  256000UL ) {
9389		lfxo_intcap ++ ;
9490	}
9591
@@ -107,11 +103,11 @@ static inline void power_and_clock_configuration(void)
107103	 * additions and subtractions, it generates slightly less than optimal 
108104	 * code. 
109105	 */ 
110- 	uint32_t  slope_field  = 
106+ 	uint32_t  slope_field_m  = 
111107		(xosc32mtrim  &  FICR_XOSC32MTRIM_SLOPE_Msk ) >> FICR_XOSC32MTRIM_SLOPE_Pos ;
112- 	uint32_t  slope_mask  =  FICR_XOSC32MTRIM_SLOPE_Msk  >> FICR_XOSC32MTRIM_SLOPE_Pos ;
113- 	uint32_t  slope_sign  =  (slope_mask  -  (slope_mask  >> 1 ));
114- 	int32_t  slope_m  =  (int32_t )(slope_field  ^ slope_sign ) -  (int32_t )slope_sign ;
108+ 	uint32_t  slope_mask_m  =  FICR_XOSC32MTRIM_SLOPE_Msk  >> FICR_XOSC32MTRIM_SLOPE_Pos ;
109+ 	uint32_t  slope_sign_m  =  (slope_mask_m  -  (slope_mask_m  >> 1 ));
110+ 	int32_t  slope_m  =  (int32_t )(slope_field_m  ^ slope_sign_m ) -  (int32_t )slope_sign_m ;
115111	uint32_t  offset_m  = 
116112		(xosc32mtrim  &  FICR_XOSC32MTRIM_OFFSET_Msk ) >> FICR_XOSC32MTRIM_OFFSET_Pos ;
117113	/* As specified in the nRF54L15 PS: 
@@ -121,22 +117,19 @@ static inline void power_and_clock_configuration(void)
121117	 * holding any value between 4.0 pF and 17.0 pF in 0.25 pF steps. 
122118	 */ 
123119
124- 	/* NOTE 1: Requested HFXO internal capacitance in femto Faradas is used directly in formula 
125- 	 *         to calculate INTCAP code. That is different than in case of LFXO. 
126- 	 * 
127- 	 * NOTE 2: PS formula uses piko Farads, the implementation of the formula uses femto Farads 
128- 	 *         to avoid use of floating point data type. 
129- 	 */ 
130- 	uint32_t  cap_val_femto_f  =  DT_PROP (HFXO_NODE , load_capacitance_femtofarad );
120+ 	uint32_t  hfxo_intcap_femto_f  =  DT_PROP (HFXO_NODE , load_capacitance_femtofarad );
131121
132- 	uint32_t  mid_val_intcap  =  (((cap_val_femto_f  -  5500UL ) *  (uint32_t )(slope_m  +  791UL ))
133- 		 +  (offset_m  << 2UL ) *  1000UL ) >> 8UL ;
122+ 	/* Capacitance value passed to the formula is in femto Farads to 
123+ 	 * avoid floating point data type. Hence, offset_m needs to be multiplied by 1000. 
124+ 	 */ 
125+ 	uint32_t  hfxo_intcap_mid_val  =  (((hfxo_intcap_femto_f  -  5500UL )
126+ 			*  (uint32_t )(slope_m  +  791UL )) +  (offset_m  << 2UL ) *  1000UL ) >> 8UL ;
134127
135- 	/* Convert the calculated value to piko Farads */ 
136- 	uint32_t  hfxo_intcap  =  mid_val_intcap  / 1000 ;
128+ 	/* Convert the calculated value to piko Farads.  */ 
129+ 	uint32_t  hfxo_intcap  =  hfxo_intcap_mid_val  / 1000 ;
137130
138- 	/* Round based on fractional part */ 
139- 	if  (mid_val_intcap  % 1000  >= 500 ) {
131+ 	/* Round based on fractional part.  */ 
132+ 	if  (hfxo_intcap_mid_val  % 1000  >= 500 ) {
140133		hfxo_intcap ++ ;
141134	}
142135
0 commit comments