File indexing completed on 2025-05-11 08:23:00
0001
0002
0003
0004
0005
0006
0007
0008 #include "fsl_ocotp.h"
0009
0010
0011
0012
0013
0014 #ifndef FSL_COMPONENT_ID
0015 #define FSL_COMPONENT_ID "platform.drivers.ocotp"
0016 #endif
0017
0018 #if defined(FSL_FEATURE_OCOTP_HAS_STATUS) && FSL_FEATURE_OCOTP_HAS_STATUS
0019 #define OCOTP_STATUS_READ_DED_MASK \
0020 (OCOTP_OUT_STATUS0_DED0_MASK | OCOTP_OUT_STATUS0_DED1_MASK | OCOTP_OUT_STATUS0_DED2_MASK | \
0021 OCOTP_OUT_STATUS0_DED3_MASK)
0022 #endif
0023
0024
0025 #define OCOTP_TIMING_WAIT_NS (uint64_t)150
0026
0027 #define OCOTP_TIMING_RELEX_NS (uint64_t)100
0028
0029 #define OCOTP_TIMING_PROGRAM_NS (uint64_t)10000
0030
0031 #define OCOTP_TIMING_READ_NS (uint64_t)40
0032
0033
0034 #define OCOTP_WRITE_UNLOCK_KEY (0x3E77)
0035
0036
0037
0038
0039 #if (defined(FSL_FEATURE_OCOTP_HAS_TIMING_CTRL) && FSL_FEATURE_OCOTP_HAS_TIMING_CTRL)
0040
0041
0042
0043
0044
0045
0046 static void OCOTP_SetReadTiming(OCOTP_Type *base, ocotp_timing_t timingConfig);
0047
0048
0049
0050
0051
0052
0053
0054 static void OCOTP_SetWriteTiming(OCOTP_Type *base, ocotp_timing_t timingConfig);
0055 #endif
0056
0057
0058
0059
0060 #if (defined(FSL_FEATURE_OCOTP_HAS_TIMING_CTRL) && FSL_FEATURE_OCOTP_HAS_TIMING_CTRL)
0061
0062 static ocotp_timing_t s_timingConfig;
0063 #endif
0064
0065
0066
0067
0068
0069 status_t OCOTP_ReloadShadowRegister(OCOTP_Type *base)
0070 {
0071 assert(NULL != base);
0072
0073 status_t status = kStatus_Success;
0074
0075
0076 while (OCOTP_CheckBusyStatus(base))
0077 {
0078 }
0079
0080
0081 OCOTP_ClearErrorStatus(base);
0082
0083 #if (defined(FSL_FEATURE_OCOTP_HAS_TIMING_CTRL) && FSL_FEATURE_OCOTP_HAS_TIMING_CTRL)
0084
0085 OCOTP_SetReadTiming(base, s_timingConfig);
0086
0087
0088 while (OCOTP_CheckBusyStatus(base))
0089 {
0090 }
0091 #endif
0092
0093 #if defined(OCOTP_OUT_STATUS0_DED_RELOAD_MASK)
0094
0095 base->OUT_STATUS0_CLR = OCOTP_OUT_STATUS0_DED_RELOAD_MASK;
0096 #endif
0097
0098
0099 base->CTRL_SET = OCOTP_CTRL_RELOAD_SHADOWS(1);
0100
0101
0102 while (OCOTP_CheckBusyStatus(base))
0103 {
0104 }
0105
0106 while (OCOTP_CTRL_RELOAD_SHADOWS_MASK == (base->CTRL & OCOTP_CTRL_RELOAD_SHADOWS_MASK))
0107 {
0108 }
0109
0110 #if defined(OCOTP_OUT_STATUS0_DED_RELOAD_MASK)
0111 if ((base->OUT_STATUS0 & OCOTP_OUT_STATUS0_DED_RELOAD_MASK) != 0U)
0112 {
0113 status = kStatus_OCOTP_ReloadError;
0114 }
0115 #endif
0116
0117 return status;
0118 }
0119
0120 #if (defined(FSL_FEATURE_OCOTP_HAS_TIMING_CTRL) && FSL_FEATURE_OCOTP_HAS_TIMING_CTRL)
0121 static void OCOTP_SetReadTiming(OCOTP_Type *base, ocotp_timing_t timingConfig)
0122 {
0123 uint32_t timingValue = base->TIMING;
0124
0125 timingValue &= ~(OCOTP_TIMING_RELAX_MASK | OCOTP_TIMING_STROBE_READ_MASK | OCOTP_TIMING_WAIT_MASK);
0126 timingValue |= OCOTP_TIMING_RELAX(timingConfig.relax) | OCOTP_TIMING_STROBE_READ(timingConfig.strobe_read) |
0127 OCOTP_TIMING_WAIT(timingConfig.wait);
0128 base->TIMING = timingValue;
0129 }
0130
0131 static void OCOTP_SetWriteTiming(OCOTP_Type *base, ocotp_timing_t timingConfig)
0132 {
0133 uint32_t timingValue = base->TIMING;
0134
0135 timingValue &= ~(OCOTP_TIMING_RELAX_MASK | OCOTP_TIMING_STROBE_PROG_MASK | OCOTP_TIMING_WAIT_MASK);
0136 timingValue |= OCOTP_TIMING_RELAX(timingConfig.relax) | OCOTP_TIMING_STROBE_PROG(timingConfig.strobe_prog) |
0137 OCOTP_TIMING_WAIT(timingConfig.wait);
0138
0139 base->TIMING = timingValue;
0140 }
0141 #endif
0142
0143
0144 void OCOTP_Init(OCOTP_Type *base, uint32_t srcClock_Hz)
0145 {
0146 assert(NULL != base);
0147 #if (defined(FSL_FEATURE_OCOTP_HAS_TIMING_CTRL) && FSL_FEATURE_OCOTP_HAS_TIMING_CTRL)
0148 assert(0UL != srcClock_Hz);
0149 #endif
0150
0151 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0152
0153 CLOCK_EnableClock(kCLOCK_Ocotp);
0154 #endif
0155
0156 #if (defined(FSL_FEATURE_OCOTP_HAS_TIMING_CTRL) && FSL_FEATURE_OCOTP_HAS_TIMING_CTRL)
0157
0158 s_timingConfig.wait = (uint32_t)((OCOTP_TIMING_WAIT_NS * srcClock_Hz + 1000000000U) / 1000000000U - 1U);
0159
0160
0161 s_timingConfig.relax = (uint32_t)((OCOTP_TIMING_RELEX_NS * srcClock_Hz + 1000000000U) / 1000000000U - 1U);
0162
0163
0164 s_timingConfig.strobe_prog = (uint32_t)((OCOTP_TIMING_PROGRAM_NS * srcClock_Hz + 500000000U) / 1000000000U) +
0165 2U * (s_timingConfig.relax + 1U) - 1U;
0166
0167
0168 s_timingConfig.strobe_read = (uint32_t)((OCOTP_TIMING_READ_NS * srcClock_Hz + 1000000000U) / 1000000000U) +
0169 2U * (s_timingConfig.relax + 1U) - 1U;
0170 #endif
0171 }
0172
0173
0174 void OCOTP_Deinit(OCOTP_Type *base)
0175 {
0176 assert(NULL != base);
0177
0178 #if (defined(FSL_FEATURE_OCOTP_HAS_TIMING_CTRL) && FSL_FEATURE_OCOTP_HAS_TIMING_CTRL)
0179 s_timingConfig.wait = 0UL;
0180 s_timingConfig.relax = 0UL;
0181 s_timingConfig.strobe_prog = 0UL;
0182 s_timingConfig.strobe_read = 0UL;
0183 #endif
0184
0185 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0186
0187 CLOCK_DisableClock(kCLOCK_Ocotp);
0188 #endif
0189 }
0190
0191
0192 uint32_t OCOTP_ReadFuseShadowRegister(OCOTP_Type *base, uint32_t address)
0193 {
0194 assert(NULL != base);
0195
0196 uint32_t data = 0U;
0197
0198 (void)OCOTP_ReadFuseShadowRegisterExt(base, address, &data, 1);
0199
0200 return data;
0201 }
0202
0203 status_t OCOTP_ReadFuseShadowRegisterExt(OCOTP_Type *base, uint32_t address, uint32_t *data, uint8_t fuseWords)
0204 {
0205 assert((fuseWords > 0U) && (fuseWords <= OCOTP_READ_FUSE_DATA_COUNT));
0206 assert(NULL != data);
0207
0208 status_t status = kStatus_Success;
0209
0210 #if (OCOTP_READ_FUSE_DATA_COUNT > 1U)
0211 uint32_t i;
0212 #endif
0213
0214
0215 while (OCOTP_CheckBusyStatus(base))
0216 {
0217 }
0218
0219
0220 if (OCOTP_CheckErrorStatus(base))
0221 {
0222 OCOTP_ClearErrorStatus(base);
0223 }
0224
0225 #if (defined(FSL_FEATURE_OCOTP_HAS_TIMING_CTRL) && FSL_FEATURE_OCOTP_HAS_TIMING_CTRL)
0226
0227 OCOTP_SetReadTiming(base, s_timingConfig);
0228
0229
0230 while (OCOTP_CheckBusyStatus(base))
0231 {
0232 }
0233
0234
0235 if (OCOTP_CheckErrorStatus(base))
0236 {
0237 OCOTP_ClearErrorStatus(base);
0238 }
0239 #endif
0240
0241 #if defined(OCOTP_STATUS_READ_DED_MASK)
0242
0243 base->OUT_STATUS0_CLR = OCOTP_STATUS_READ_DED_MASK;
0244 #endif
0245
0246
0247 base->CTRL_CLR = OCOTP_CTRL_CLR_ADDR_MASK;
0248 base->CTRL_SET = OCOTP_CTRL_SET_ADDR(address);
0249
0250
0251 #if defined(OCOTP_READ_CTRL_READ_NUM_MASK)
0252 base->READ_CTRL = (base->READ_CTRL & ~(OCOTP_READ_CTRL_READ_NUM_MASK)) |
0253 OCOTP_READ_CTRL_READ_NUM((uint32_t)fuseWords - 1U) | OCOTP_READ_CTRL_READ_FUSE_MASK;
0254 #else
0255 base->READ_CTRL |= OCOTP_READ_CTRL_READ_FUSE_MASK;
0256 #endif
0257
0258
0259 while (OCOTP_CheckBusyStatus(base))
0260 {
0261 }
0262
0263
0264 if (OCOTP_CheckErrorStatus(base))
0265 {
0266
0267 OCOTP_ClearErrorStatus(base);
0268
0269 status = kStatus_OCOTP_AccessError;
0270 }
0271
0272 #if defined(OCOTP_STATUS_READ_DED_MASK)
0273 if ((base->OUT_STATUS0 & OCOTP_STATUS_READ_DED_MASK) != 0U)
0274 {
0275 status = kStatus_Fail;
0276 }
0277 #endif
0278
0279 #if (OCOTP_READ_FUSE_DATA_COUNT == 1U)
0280 *data = base->READ_FUSE_DATA;
0281 #else
0282 for (i = 0; i < fuseWords; i++)
0283 {
0284 data[i] = base->READ_FUSE_DATAS[i].READ_FUSE_DATA;
0285 }
0286 #endif
0287
0288 return status;
0289 }
0290
0291
0292 status_t OCOTP_WriteFuseShadowRegister(OCOTP_Type *base, uint32_t address, uint32_t data)
0293 {
0294 return OCOTP_WriteFuseShadowRegisterWithLock(base, address, data, false);
0295 }
0296
0297 status_t OCOTP_WriteFuseShadowRegisterWithLock(OCOTP_Type *base, uint32_t address, uint32_t data, bool lock)
0298 {
0299 assert(NULL != base);
0300
0301 status_t status = kStatus_Success;
0302
0303 #if defined(FSL_FEATURE_OCOTP_HAS_STATUS) && FSL_FEATURE_OCOTP_HAS_STATUS
0304 uint32_t regStatus;
0305 #endif
0306
0307 #if !(defined(FSL_FEATURE_OCOTP_HAS_WORDLOCK) && FSL_FEATURE_OCOTP_HAS_WORDLOCK)
0308 if (lock)
0309 {
0310 return kStatus_InvalidArgument;
0311 }
0312 #endif
0313
0314
0315 while (OCOTP_CheckBusyStatus(base))
0316 {
0317 }
0318
0319
0320 if (OCOTP_CheckErrorStatus(base))
0321 {
0322 OCOTP_ClearErrorStatus(base);
0323 }
0324
0325 #if (defined(FSL_FEATURE_OCOTP_HAS_TIMING_CTRL) && FSL_FEATURE_OCOTP_HAS_TIMING_CTRL)
0326
0327 OCOTP_SetWriteTiming(base, s_timingConfig);
0328
0329
0330 while (OCOTP_CheckBusyStatus(base))
0331 {
0332 }
0333
0334
0335 if (OCOTP_CheckErrorStatus(base))
0336 {
0337 OCOTP_ClearErrorStatus(base);
0338 }
0339 #endif
0340
0341 #if defined(FSL_FEATURE_OCOTP_HAS_STATUS) && FSL_FEATURE_OCOTP_HAS_STATUS
0342
0343 base->OUT_STATUS0_CLR = (OCOTP_OUT_STATUS0_PROGFAIL_MASK | OCOTP_OUT_STATUS0_LOCKED_MASK);
0344 #endif
0345
0346
0347 #if (defined(FSL_FEATURE_OCOTP_HAS_WORDLOCK) && FSL_FEATURE_OCOTP_HAS_WORDLOCK)
0348 base->CTRL_CLR = OCOTP_CTRL_CLR_ADDR_MASK | OCOTP_CTRL_WR_UNLOCK_MASK | OCOTP_CTRL_WORDLOCK_MASK;
0349 #else
0350 base->CTRL_CLR = OCOTP_CTRL_CLR_ADDR_MASK | OCOTP_CTRL_WR_UNLOCK_MASK;
0351 #endif
0352
0353 #if (defined(FSL_FEATURE_OCOTP_HAS_WORDLOCK) && FSL_FEATURE_OCOTP_HAS_WORDLOCK)
0354 if (lock)
0355 {
0356 base->CTRL_SET =
0357 OCOTP_CTRL_SET_ADDR(address) | OCOTP_CTRL_WR_UNLOCK(OCOTP_WRITE_UNLOCK_KEY) | OCOTP_CTRL_WORDLOCK_MASK;
0358 }
0359 else
0360 #endif
0361 {
0362 base->CTRL_SET = OCOTP_CTRL_SET_ADDR(address) | OCOTP_CTRL_WR_UNLOCK(OCOTP_WRITE_UNLOCK_KEY);
0363 }
0364
0365
0366 base->DATA = data;
0367
0368
0369 while (OCOTP_CheckBusyStatus(base))
0370 {
0371 }
0372
0373
0374 if (OCOTP_CheckErrorStatus(base))
0375 {
0376
0377 OCOTP_ClearErrorStatus(base);
0378
0379 status = kStatus_OCOTP_AccessError;
0380 }
0381
0382 #if defined(FSL_FEATURE_OCOTP_HAS_STATUS) && FSL_FEATURE_OCOTP_HAS_STATUS
0383 regStatus = base->OUT_STATUS0;
0384
0385 if ((regStatus & OCOTP_OUT_STATUS0_PROGFAIL_MASK) != 0U)
0386 {
0387 status = kStatus_OCOTP_ProgramFail;
0388 }
0389 else if ((regStatus & OCOTP_OUT_STATUS0_LOCKED_MASK) != 0U)
0390 {
0391 status = kStatus_OCOTP_Locked;
0392 }
0393 else
0394 {
0395
0396 }
0397 #endif
0398
0399 if (kStatus_Success == status)
0400 {
0401
0402 status = OCOTP_ReloadShadowRegister(base);
0403 }
0404
0405 return status;
0406 }