1 /*
2  * Copyright 2018 - 2023 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #ifndef FSL_PRINCE_H_
9 #define FSL_PRINCE_H_
10 
11 #include "fsl_common.h"
12 
13 #include FFR_INCLUDE
14 
15 /*!
16  * @addtogroup prince
17  * @{
18  */
19 
20 /*******************************************************************************
21  * Definitions
22  ******************************************************************************/
23 
24 /*! @name Driver version */
25 /*! @{ */
26 /*! @brief PRINCE driver version 2.6.0.
27  *
28  * Current version: 2.6.0
29  *
30  * Change log:
31  * - Version 2.0.0
32  *   - Initial version.
33  * - Version 2.1.0
34  *   - Update for the A1 rev. of LPC55Sxx serie.
35  * - Version 2.2.0
36  *   - Add runtime checking of the A0 and A1 rev. of LPC55Sxx serie to support
37  *     both silicone revisions.
38  * - Version 2.3.0
39  *   - Add support for LPC55S1x and LPC55S2x series
40  * - Version 2.3.0
41  *   - Fix MISRA-2012 issues.
42  * - Version 2.3.1
43  *   - Add support for LPC55S0x series
44  * - Version 2.3.2
45  *   - Fix documentation of enumeration. Extend PRINCE example.
46  * - Version 2.4.0
47  *   - Add support for LPC55S3x series
48  * - Version 2.5.0
49  *   - Add PRINCE_Config() and PRINCE_Reconfig() features.
50  * - Version 2.5.1
51  *   - Fix build error due to renamed symbols
52  * - Version 2.6.0
53  *   - Renamed CSS to ELS
54  */
55 #define FSL_PRINCE_DRIVER_VERSION (MAKE_VERSION(2, 6, 0))
56 /*! @} */
57 
58 #if (defined(LPC55S04_SERIES) || defined(LPC55S06_SERIES))
59 /* LPC55S0x series*/
60 #define FSL_PRINCE_DRIVER_LPC55S0x
61 #include "fsl_puf.h"
62 
63 #elif (defined(LPC55S14_SERIES) || defined(LPC55S16_SERIES))
64 /* LPC55S1x series*/
65 #define FSL_PRINCE_DRIVER_LPC55S1x
66 #include "fsl_puf.h"
67 
68 #elif (defined(LPC55S26_SERIES) || defined(LPC55S28_SERIES))
69 /* LPC55S2x series*/
70 #define FSL_PRINCE_DRIVER_LPC55S2x
71 #include "fsl_puf.h"
72 
73 #elif (defined(LPC55S69_cm33_core0_SERIES) || defined(LPC55S69_cm33_core1_SERIES) || \
74        defined(LPC55S66_cm33_core0_SERIES) || defined(LPC55S66_cm33_core1_SERIES))
75 /* LPC55S6x series*/
76 #define FSL_PRINCE_DRIVER_LPC55S6x
77 #include "fsl_puf.h"
78 
79 #elif (defined(LPC55S36_SERIES))
80 /* LPC55S3x series*/
81 #define FSL_PRINCE_DRIVER_LPC55S3x
82 #define PRINCE PRINCE0
83 #include "fsl_mem_interface.h"
84 #include "mcux_els.h"                // Power Down Wake-up Init
85 #include <mcuxClEls.h>              // Interface to the entire nxpClEls component
86 #include <mcuxCsslFlowProtection.h> // Code flow protection
87 #else
88 #error "No valid CPU defined!"
89 #endif
90 
91 #define FSL_PRINCE_DRIVER_SUBREGION_SIZE_IN_KB (8U)
92 #define FSL_PRINCE_DRIVER_MAX_FLASH_ADDR \
93     ((uint32_t)FSL_FEATURE_SYSCON_FLASH_SIZE_BYTES - (FSL_PRINCE_DRIVER_SUBREGION_SIZE_IN_KB * 2U * 1024U))
94 
95 #if !defined(ALIGN_DOWN)
96 #define ALIGN_DOWN(x, a) ((x) & (uint32_t)(-((int32_t)(a))))
97 #endif
98 
99 /*! @brief Secure status enumeration. */
100 typedef enum _skboot_status
101 {
102     kStatus_SKBOOT_Success               = 0x5ac3c35au, /*!< PRINCE Success */
103     kStatus_SKBOOT_Fail                  = 0xc35ac35au, /*!< PRINCE Fail */
104     kStatus_SKBOOT_InvalidArgument       = 0xc35a5ac3u, /*!< PRINCE Invalid argument */
105     kStatus_SKBOOT_KeyStoreMarkerInvalid = 0xc3c35a5au, /*!< PRINCE Invalid marker */
106 } skboot_status_t;
107 
108 /*! @brief Secure boolean enumeration. */
109 typedef enum _secure_bool
110 {
111     kSECURE_TRUE  = 0xc33cc33cU, /*!< PRINCE true */
112     kSECURE_FALSE = 0x5aa55aa5U, /*!< PRINCE false */
113 } secure_bool_t;
114 
115 /*! @brief Prince region. */
116 typedef enum _prince_region
117 {
118     kPRINCE_Region0 = 0U, /*!< PRINCE region 0 */
119     kPRINCE_Region1 = 1U, /*!< PRINCE region 1 */
120     kPRINCE_Region2 = 2U, /*!< PRINCE region 2 */
121 } prince_region_t;
122 
123 /*! @brief Prince lock. */
124 typedef enum _prince_lock
125 {
126     kPRINCE_Region0Lock = 1U,   /*!< PRINCE region 0 lock */
127     kPRINCE_Region1Lock = 2U,   /*!< PRINCE region 1 lock */
128     kPRINCE_Region2Lock = 4U,   /*!< PRINCE region 2 lock */
129     kPRINCE_MaskLock    = 256U, /*!< PRINCE mask register lock */
130 } prince_lock_t;
131 
132 /*! @brief Prince flag. */
133 typedef enum _prince_flags
134 {
135     kPRINCE_Flag_None       = 0U, /*!< PRINCE Flag None */
136     kPRINCE_Flag_EraseCheck = 1U, /*!< PRINCE Flag Erase check */
137     kPRINCE_Flag_WriteCheck = 2U, /*!< PRINCE Flag Write check */
138 } prince_flags_t;
139 
140 #if defined(FSL_PRINCE_DRIVER_LPC55S3x)
141 typedef struct
142 {
143     uint32_t target_prince_region : 2; // 0/1/2
144     uint32_t reserved : 22;
145     uint32_t tag : 8; // Fixed to 0x50 ('P')
146 } prince_prot_region_option_t;
147 typedef struct
148 {
149     prince_prot_region_option_t option;
150     uint32_t start;
151     uint32_t length;
152 } prince_prot_region_arg_t;
153 
154 /*! @brief Prince fixed tag in prince_prot_region_option_t structure */
155 #define PRINCE_TAG       0x50u
156 #define PRINCE_TAG_SHIFT 24u
157 /*! @brief Prince region count */
158 #define PRINCE_REGION_COUNT 3u
159 /*! @brief Define for ELS key store indexes */
160 #define NXP_DIE_MEM_ENC_SK    2u
161 #define NXP_DIE_MEM_IV_ENC_SK 4u
162 /*! @brief KDF mask and key properties for NXP_DIE_MEM_IV_ENC_SK (see SYSCON documentation)*/
163 #define SYSCON_ELS_KDF_MASK 0x07000FCF
164 /*! @brief CFPA version and IV indexes (see Protected Flash Region table) */
165 #define CFPA_VER_OFFSET       0x04
166 #define CFPA_PRINCE_IV_OFFSET 0x14u
167 /*! @brief CMPA SR and lock indexes (see Protected Flash Region table) */
168 #define CMPA_PRINCE_SR_OFFSET   0x24u
169 #define CMPA_PRINCE_LOCK_OFFSET 0x20u
170 /*! @brief CFPA scrach version and IV addresses (see Protected Flash Region table) */
171 #define CFPA_SCRATCH_VER 0x3dc04
172 #define CFPA_SCRATCH_IV  0x3dc14
173 /*! @brief CMPA lock bit-field defines (see Protected Flash Region table) */
174 #define PRINCE_BASE_ADDR_LOCK_REG0_SHIFT (16u)
175 #define PRINCE_BASE_ADDR_LOCK_REG0_MASK  (0x3u << PRINCE_BASE_ADDR_LOCK_REG0_SHIFT)
176 #define PRINCE_BASE_ADDR_LOCK_REG1_SHIFT (18u)
177 #define PRINCE_BASE_ADDR_LOCK_REG1_MASK  (0x3u << PRINCE_BASE_ADDR_LOCK_REG1_SHIFT)
178 #define PRINCE_BASE_ADDR_LOCK_REG2_SHIFT (20u)
179 #define PRINCE_BASE_ADDR_LOCK_REG2_MASK  (0x3u << PRINCE_BASE_ADDR_LOCK_REG2_SHIFT)
180 
181 #endif /* defined(FSL_PRINCE_DRIVER_LPC55S3x) */
182 
183 /*******************************************************************************
184  * API
185  ******************************************************************************/
186 #if defined(__cplusplus)
187 extern "C" {
188 #endif
189 
190 /*!
191  * @brief Enable data encryption.
192  *
193  * This function enables PRINCE on-the-fly data encryption.
194  *
195  * @param base PRINCE peripheral address.
196  */
PRINCE_EncryptEnable(PRINCE_Type * base)197 static inline void PRINCE_EncryptEnable(PRINCE_Type *base)
198 {
199     base->ENC_ENABLE = 1u;
200 }
201 
202 /*!
203  * @brief Disable data encryption.
204  *
205  * This function disables PRINCE on-the-fly data encryption.
206  *
207  * @param base PRINCE peripheral address.
208  */
PRINCE_EncryptDisable(PRINCE_Type * base)209 static inline void PRINCE_EncryptDisable(PRINCE_Type *base)
210 {
211     base->ENC_ENABLE = 0u;
212 }
213 
214 /*!
215  * @brief Is Enable data encryption.
216  *
217  * This function test if PRINCE on-the-fly data encryption is enabled.
218  *
219  * @param base PRINCE peripheral address.
220  * @return true if enabled, false if not
221  */
PRINCE_IsEncryptEnable(PRINCE_Type * base)222 static inline bool PRINCE_IsEncryptEnable(PRINCE_Type *base)
223 {
224     return (base->ENC_ENABLE == 1u) ? true : false;
225 }
226 
227 /*!
228  * @brief Sets PRINCE data mask.
229  *
230  * This function sets the PRINCE mask that is used to mask decrypted data.
231  *
232  * @param base PRINCE peripheral address.
233  * @param mask 64-bit data mask value.
234  */
PRINCE_SetMask(PRINCE_Type * base,uint64_t mask)235 static inline void PRINCE_SetMask(PRINCE_Type *base, uint64_t mask)
236 {
237     base->MASK_LSB = (uint32_t)(mask & 0xffffffffu);
238     base->MASK_MSB = (uint32_t)(mask >> 32u);
239 }
240 
241 /*!
242  * @brief Locks access for specified region registers or data mask register.
243  *
244  * This function sets lock on specified region registers or mask register.
245  *
246  * @param base PRINCE peripheral address.
247  * @param lock registers to lock. This is a logical OR of members of the
248  *             enumeration ::prince_lock_t
249  */
PRINCE_SetLock(PRINCE_Type * base,uint32_t lock)250 static inline void PRINCE_SetLock(PRINCE_Type *base, uint32_t lock)
251 {
252     base->LOCK = lock & 0x1ffu;
253 }
254 
255 #if !defined(FSL_PRINCE_DRIVER_LPC55S3x)
256 /*!
257  * @brief Generate new IV code.
258  *
259  * This function generates new IV code and stores it into the persistent memory.
260  * Ensure about 800 bytes free space on the stack when calling this routine with the store parameter set to true!
261  *
262  * @param region PRINCE region index.
263  * @param iv_code IV code pointer used for storing the newly generated 52 bytes long IV code.
264  * @param store flag to allow storing the newly generated IV code into the persistent memory (FFR).
265  * @param flash_context pointer to the flash driver context structure.
266  *
267  * @return kStatus_Success upon success
268  * @return kStatus_Fail    otherwise, kStatus_Fail is also returned if the key code for the particular
269  *                         PRINCE region is not present in the keystore (though new IV code has been provided)
270  */
271 status_t PRINCE_GenNewIV(prince_region_t region, uint8_t *iv_code, bool store, flash_config_t *flash_context);
272 #endif /* !defined(FSL_PRINCE_DRIVER_LPC55S3x) */
273 
274 #if !defined(FSL_PRINCE_DRIVER_LPC55S3x)
275 /*!
276  * @brief Load IV code.
277  *
278  * This function enables IV code loading into the PRINCE bus encryption engine.
279  *
280  * @param region PRINCE region index.
281  * @param iv_code IV code pointer used for passing the IV code.
282  *
283  * @return kStatus_Success upon success
284  * @return kStatus_Fail    otherwise
285  */
286 status_t PRINCE_LoadIV(prince_region_t region, uint8_t *iv_code);
287 #endif /* !defined(FSL_PRINCE_DRIVER_LPC55S3x) */
288 
289 #if !defined(FSL_PRINCE_DRIVER_LPC55S3x)
290 /*!
291  * @brief Allow encryption/decryption for specified address range.
292  *
293  * This function sets the encryption/decryption for specified address range.
294  * The SR mask value for the selected Prince region is calculated from provided
295  * start_address and length parameters. This calculated value is OR'ed with the
296  * actual SR mask value and stored into the PRINCE SR_ENABLE register and also
297  * into the persistent memory (FFR) to be used after the device reset. It is
298  * possible to define several nonadjacent encrypted areas within one Prince
299  * region when calling this function repeatedly. If the length parameter is set
300  * to 0, the SR mask value is set to 0 and thus the encryption/decryption for
301  * the whole selected Prince region is disabled.
302  * Ensure about 800 bytes free space on the stack when calling this routine!
303  *
304  * @param region PRINCE region index.
305  * @param start_address start address of the area to be encrypted/decrypted.
306  * @param length length of the area to be encrypted/decrypted.
307  * @param flash_context pointer to the flash driver context structure.
308  * @param regenerate_iv flag to allow IV code regenerating, storing into
309  *        the persistent memory (FFR) and loading into the PRINCE engine
310  *
311  * @return kStatus_Success upon success
312  * @return kStatus_Fail    otherwise
313  */
314 status_t PRINCE_SetEncryptForAddressRange(
315     prince_region_t region, uint32_t start_address, uint32_t length, flash_config_t *flash_context, bool regenerate_iv);
316 #endif /* !defined(FSL_PRINCE_DRIVER_LPC55S3x) */
317 
318 /*!
319  * @brief Gets the PRINCE Sub-Region Enable register.
320  *
321  * This function gets PRINCE SR_ENABLE register.
322  *
323  * @param base PRINCE peripheral address.
324  * @param region PRINCE region index.
325  * @param sr_enable Sub-Region Enable register pointer.
326  *
327  * @return kStatus_Success upon success
328  * @return kStatus_InvalidArgument
329  */
330 status_t PRINCE_GetRegionSREnable(PRINCE_Type *base, prince_region_t region, uint32_t *sr_enable);
331 
332 /*!
333  * @brief Gets the PRINCE region base address register.
334  *
335  * This function gets PRINCE BASE_ADDR register.
336  *
337  * @param base PRINCE peripheral address.
338  * @param region PRINCE region index.
339  * @param region_base_addr Region base address pointer.
340  *
341  * @return kStatus_Success upon success
342  * @return kStatus_InvalidArgument
343  */
344 status_t PRINCE_GetRegionBaseAddress(PRINCE_Type *base, prince_region_t region, uint32_t *region_base_addr);
345 
346 /*!
347  * @brief Sets the PRINCE region IV.
348  *
349  * This function sets specified AES IV for the given region.
350  *
351  * @param base PRINCE peripheral address.
352  * @param region Selection of the PRINCE region to be configured.
353  * @param iv 64-bit AES IV in little-endian byte order.
354  */
355 status_t PRINCE_SetRegionIV(PRINCE_Type *base, prince_region_t region, const uint8_t iv[8]);
356 
357 /*!
358  * @brief Sets the PRINCE region base address.
359  *
360  * This function configures PRINCE region base address.
361  *
362  * @param base PRINCE peripheral address.
363  * @param region Selection of the PRINCE region to be configured.
364  * @param region_base_addr Base Address for region.
365  */
366 status_t PRINCE_SetRegionBaseAddress(PRINCE_Type *base, prince_region_t region, uint32_t region_base_addr);
367 
368 /*!
369  * @brief Sets the PRINCE Sub-Region Enable register.
370  *
371  * This function configures PRINCE SR_ENABLE register.
372  *
373  * @param base PRINCE peripheral address.
374  * @param region Selection of the PRINCE region to be configured.
375  * @param sr_enable Sub-Region Enable register value.
376  */
377 status_t PRINCE_SetRegionSREnable(PRINCE_Type *base, prince_region_t region, uint32_t sr_enable);
378 
379 #if !defined(FSL_PRINCE_DRIVER_LPC55S3x)
380 /*!
381  * @brief Erases the flash sectors encompassed by parameters passed into function.
382  *
383  * This function erases the appropriate number of flash sectors based on the
384  * desired start address and length. It deals with the flash erase function
385  * complenentary to the standard erase API of the IAP1 driver. This implementation
386  * additionally checks if the whole encrypted PRINCE subregions are erased at once
387  * to avoid secrets revealing. The checker implementation is limited to one contiguous
388  * PRINCE-controlled memory area.
389  *
390  * @param config The pointer to the flash driver context structure.
391  * @param start The start address of the desired flash memory to be erased.
392  *              The start address needs to be prince-sburegion-aligned.
393  * @param lengthInBytes The length, given in bytes (not words or long-words)
394  *                      to be erased. Must be prince-sburegion-size-aligned.
395  * @param key The value used to validate all flash erase APIs.
396  *
397  * @return #kStatus_FLASH_Success API was executed successfully.
398  * @return #kStatus_FLASH_InvalidArgument An invalid argument is provided.
399  * @return #kStatus_FLASH_AlignmentError The parameter is not aligned with the specified baseline.
400  * @return #kStatus_FLASH_AddressError The address is out of range.
401  * @return #kStatus_FLASH_EraseKeyError The API erase key is invalid.
402  * @return #kStatus_FLASH_CommandFailure Run-time error during the command execution.
403  * @return #kStatus_FLASH_CommandNotSupported Flash API is not supported.
404  * @return #kStatus_FLASH_EccError A correctable or uncorrectable error during command execution.
405  * @return #kStatus_FLASH_EncryptedRegionsEraseNotDoneAtOnce Encrypted flash subregions are not erased at once.
406  */
407 status_t PRINCE_FlashEraseWithChecker(flash_config_t *config, uint32_t start, uint32_t lengthInBytes, uint32_t key);
408 #endif /* !defined(FSL_PRINCE_DRIVER_LPC55S3x) */
409 
410 #if !defined(FSL_PRINCE_DRIVER_LPC55S3x)
411 /*!
412  * @brief Programs flash with data at locations passed in through parameters.
413  *
414  * This function programs the flash memory with the desired data for a given
415  * flash area as determined by the start address and the length. It deals with the
416  * flash program function complenentary to the standard program API of the IAP1 driver.
417  * This implementation additionally checks if the whole PRINCE subregions are
418  * programmed at once to avoid secrets revealing. The checker implementation is limited
419  * to one contiguous PRINCE-controlled memory area.
420  *
421  * @param config The pointer to the flash driver context structure.
422  * @param start The start address of the desired flash memory to be programmed. Must be
423  *              prince-sburegion-aligned.
424  * @param src A pointer to the source buffer of data that is to be programmed
425  *            into the flash.
426  * @param lengthInBytes The length, given in bytes (not words or long-words),
427  *                      to be programmed. Must be prince-sburegion-size-aligned.
428  *
429  * @return #kStatus_FLASH_Success API was executed successfully.
430  * @return #kStatus_FLASH_InvalidArgument An invalid argument is provided.
431  * @return #kStatus_FLASH_AlignmentError Parameter is not aligned with the specified baseline.
432  * @return #kStatus_FLASH_AddressError Address is out of range.
433  * @return #kStatus_FLASH_AccessError Invalid instruction codes and out-of bounds addresses.
434  * @return #kStatus_FLASH_CommandFailure Run-time error during the command execution.
435  * @return #kStatus_FLASH_CommandFailure Run-time error during the command execution.
436  * @return #kStatus_FLASH_CommandNotSupported Flash API is not supported.
437  * @return #kStatus_FLASH_EccError A correctable or uncorrectable error during command execution.
438  * @return #kStatus_FLASH_SizeError Encrypted flash subregions are not programmed at once.
439  */
440 status_t PRINCE_FlashProgramWithChecker(flash_config_t *config, uint32_t start, uint8_t *src, uint32_t lengthInBytes);
441 #endif /* !defined(FSL_PRINCE_DRIVER_LPC55S3x) */
442 
443 #if defined(FSL_PRINCE_DRIVER_LPC55S3x)
444 /*!
445  * @brief Configures PRINCE setting.
446  *
447  * This function does the initial PRINCE configuration via ROM IAP API call.
448  * PRINCE_SR_x configuration for each region configuration is stored into FFR (CMPA).
449  * PRINCE IV erase counters (MCTR_INT_IV_CTRx) in CFPA are updated accordingly.
450  *
451  * Note: This function is expected to be called once in the device lifetime,
452  * typically during the initial device provisioning, since it is programming the CMPA pages in PFR flash.
453  *
454  * @param coreCtx The pointer to the ROM API driver context structure.
455  * @param config The pointer to the PRINCE driver configuration structure.
456  *
457  * @retval #kStatus_Success
458  * @retval #kStatus_CommandUnsupported
459  * @retval #kStatus_InvalidArgument
460  * @retval #kStatus_FLASH_ModifyProtectedAreaDisallowed
461  * @retval #kStatusMemoryRangeInvalid
462  * @retval #kStatus_Fail
463  * @retval #kStatus_OutOfRange
464  * @retval #kStatus_SPI_BaudrateNotSupport
465  */
466 status_t PRINCE_Configure(api_core_context_t *coreCtx, prince_prot_region_arg_t *config);
467 #endif /* defined(FSL_PRINCE_DRIVER_LPC55S3x) */
468 
469 #if defined(FSL_PRINCE_DRIVER_LPC55S3x)
470 /*!
471  * @brief Reconfigures PRINCE setting.
472  *
473  * This function is used to re-configure PRINCE IP based on configuration stored in FFR.
474  * This function also needs to be called after wake up from power-down mode to regenerate IV
475  * encryption key in ELS key store whose presence is necessary for correct PRINCE operation
476  * during erase and write operations to encrypted regions of internal flash memory
477  * (dependency for correct operation of MEM_Erase() and MEM_Write() after wake up from power-down mode).
478  *
479  * @param coreCtx The pointer to the ROM API driver context structure.
480  *
481  * @retval #kStatus_Success
482  * @retval #kStatus_CommandUnsupported
483  * @retval #kStatus_InvalidArgument
484  * @retval #kStatus_FLASH_ModifyProtectedAreaDisallowed
485  * @retval #kStatusMemoryRangeInvalid
486  * @retval #kStatus_Fail
487  * @retval #kStatus_OutOfRange
488  * @retval #kStatus_SPI_BaudrateNotSupport
489  */
490 status_t PRINCE_Reconfigure(api_core_context_t *coreCtx);
491 #endif /* defined(FSL_PRINCE_DRIVER_LPC55S3x) */
492 
493 #if (defined(FSL_PRINCE_DRIVER_LPC55S0x)) || defined(FSL_PRINCE_DRIVER_LPC55S1x) || defined(FSL_PRINCE_DRIVER_LPC55S3x)
494 /*!
495  * @brief Gets the PRINCE Error status register.
496  *
497  * @param base PRINCE peripheral address.
498  *
499  * @return PRINCE Error status register
500  */
PRINCE_GetErrorStatus(PRINCE_Type * base)501 static inline uint32_t PRINCE_GetErrorStatus(PRINCE_Type *base)
502 {
503     return base->ERR;
504 }
505 
506 /*!
507  * @brief Clears the PRINCE Error status register.
508  *
509  * @param base PRINCE peripheral address.
510  */
PRINCE_ClearErrorStatus(PRINCE_Type * base)511 static inline void PRINCE_ClearErrorStatus(PRINCE_Type *base)
512 {
513     base->ERR = 0U;
514 }
515 #endif /* defined(FSL_PRINCE_DRIVER_LPC55S0x) || defined(FSL_PRINCE_DRIVER_LPC55S1x) || \
516           defined(FSL_PRINCE_DRIVER_LPC55S3x) */
517 
518 #if defined(__cplusplus)
519 }
520 #endif
521 
522 /*!
523  *@}
524  */
525 
526 #endif /* FSL_PRINCE_H_ */
527