hpm_otp_drv.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * Copyright (c) 2021 HPMicro
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. *
  6. */
  7. #include "hpm_common.h"
  8. #include "hpm_soc.h"
  9. #include "hpm_otp_drv.h"
  10. /***********************************************************************************************************************
  11. * Definitions
  12. **********************************************************************************************************************/
  13. #define SHADOW_INDEX_IN_PMIC_OTP_END (15U)
  14. #define OTP_UNLOCK_MAGIC_NUM (0x4E45504FUL) /*!< ASCII: OPEN */
  15. #define OTP_LOCK_MAGIC_NUM (~OTP_UNLOCK_MAGIC_NUM)
  16. #define OTP_CMD_PROGRAM (0x574F4C42UL) /*!< ASCII: BLOW */
  17. #define OTP_CMD_READ (0x44414552UL) /*!< ASCII: READ */
  18. /***********************************************************************************************************************
  19. * Codes
  20. **********************************************************************************************************************/
  21. void otp_init(void)
  22. {
  23. }
  24. void otp_deinit(void)
  25. {
  26. }
  27. uint32_t otp_read_from_shadow(uint32_t addr)
  28. {
  29. uint32_t ret_val = 0;
  30. if (addr < ARRAY_SIZE(HPM_OTP->SHADOW)) {
  31. ret_val = (addr <= SHADOW_INDEX_IN_PMIC_OTP_END) ? HPM_OTP->SHADOW[addr] : HPM_OTPSHW->SHADOW[addr];
  32. }
  33. return ret_val;
  34. }
  35. uint32_t otp_read_from_ip(uint32_t addr)
  36. {
  37. uint32_t ret_val = 0;
  38. if (addr < ARRAY_SIZE(HPM_OTP->SHADOW)) {
  39. ret_val = HPM_OTP->FUSE[addr];
  40. }
  41. return ret_val;
  42. }
  43. hpm_stat_t otp_program(uint32_t addr, const uint32_t *src, uint32_t num_of_words)
  44. {
  45. hpm_stat_t status = status_invalid_argument;
  46. do {
  47. uint32_t fuse_idx_max = ARRAY_SIZE(HPM_OTP->SHADOW);
  48. HPM_BREAK_IF((addr >= fuse_idx_max) || (num_of_words > fuse_idx_max) || (addr + num_of_words > fuse_idx_max));
  49. /* Enable 2.5V LDO for FUSE programming */
  50. uint32_t reg_val = (HPM_PCFG->LDO2P5 & ~PCFG_LDO2P5_VOLT_MASK) | PCFG_LDO2P5_ENABLE_MASK | PCFG_LDO2P5_VOLT_SET(2500);
  51. HPM_PCFG->LDO2P5 = reg_val;
  52. /* Wait until LDO is ready */
  53. while (!IS_HPM_BITMASK_SET(HPM_PCFG->LDO2P5, PCFG_DCDC_MODE_READY_MASK)) {
  54. }
  55. HPM_OTP->UNLOCK = OTP_UNLOCK_MAGIC_NUM;
  56. for (uint32_t i = 0; i < num_of_words; i++) {
  57. HPM_OTP->FUSE[addr++] = *src++;
  58. }
  59. HPM_OTP->UNLOCK = OTP_LOCK_MAGIC_NUM;
  60. /* Disable 2.5V LDO after FUSE programming for saving power */
  61. HPM_PCFG->LDO2P5 &= ~PCFG_LDO2P5_ENABLE_MASK;
  62. status = status_success;
  63. } while (false);
  64. return status;
  65. }
  66. hpm_stat_t otp_reload(otp_region_t region)
  67. {
  68. hpm_stat_t status = status_invalid_argument;
  69. if ((uint32_t)region < 0x10 && (region >= otp_region0_mask)) {
  70. HPM_OTP->LOAD_REQ = (uint32_t)region;
  71. HPM_OTP->LOAD_COMP = (uint32_t)region;
  72. while (!IS_HPM_BITMASK_SET(HPM_OTP->LOAD_COMP, region)) {
  73. }
  74. status = status_success;
  75. }
  76. return status;
  77. }
  78. hpm_stat_t otp_lock_otp(uint32_t addr, otp_lock_option_t lock_option)
  79. {
  80. hpm_stat_t status = status_invalid_argument;
  81. do {
  82. HPM_BREAK_IF(addr >= ARRAY_SIZE(HPM_OTP->SHADOW) || (lock_option > otp_lock_option_max));
  83. OTP_Type *otp_base = (addr <= SHADOW_INDEX_IN_PMIC_OTP_END) ? HPM_OTP : HPM_OTPSHW;
  84. uint32_t lock_reg_idx = (addr << 1) / 32;
  85. uint32_t lock_reg_offset = (addr << 1) % 32;
  86. uint32_t lock_mask = ((uint32_t)lock_option) << lock_reg_offset;
  87. otp_base->FUSE_LOCK[lock_reg_idx] = lock_mask;
  88. status = status_success;
  89. } while (false);
  90. return status;
  91. }
  92. hpm_stat_t otp_lock_shadow(uint32_t addr, otp_lock_option_t lock_option)
  93. {
  94. hpm_stat_t status = status_invalid_argument;
  95. do {
  96. HPM_BREAK_IF(addr >= ARRAY_SIZE(HPM_OTP->SHADOW) || (lock_option > otp_lock_option_max));
  97. OTP_Type *otp_base = (addr <= SHADOW_INDEX_IN_PMIC_OTP_END) ? HPM_OTP : HPM_OTPSHW;
  98. uint32_t lock_reg_idx = (addr << 1) / 32;
  99. uint32_t lock_reg_offset = (addr << 1) % 32;
  100. uint32_t lock_mask = ((uint32_t)lock_option) << lock_reg_offset;
  101. otp_base->SHADOW_LOCK[lock_reg_idx] = lock_mask;
  102. status = status_success;
  103. } while (false);
  104. return status;
  105. }
  106. hpm_stat_t otp_set_configurable_region(uint32_t start, uint32_t num_of_words)
  107. {
  108. hpm_stat_t status = status_invalid_argument;
  109. do {
  110. uint32_t max_fuse_idx = ARRAY_SIZE(HPM_OTP->SHADOW);
  111. HPM_BREAK_IF((start >= max_fuse_idx) || (num_of_words > max_fuse_idx) || ((start + num_of_words) > max_fuse_idx));
  112. HPM_OTP->REGION[3] = OTP_REGION_START_SET(start)
  113. | OTP_REGION_STOP_SET(start + num_of_words);
  114. status = status_success;
  115. } while (false);
  116. return status;
  117. }
  118. hpm_stat_t otp_write_shadow_register(uint32_t addr, uint32_t val)
  119. {
  120. hpm_stat_t status = status_invalid_argument;
  121. do {
  122. HPM_BREAK_IF(addr >= ARRAY_SIZE(HPM_OTP->SHADOW));
  123. uint32_t lock_reg_idx = (addr << 1) / 32;
  124. uint32_t lock_reg_offset = (addr << 1) % 32;
  125. uint32_t lock_mask = 3U << lock_reg_offset;
  126. OTP_Type *otp_base = (addr <= SHADOW_INDEX_IN_PMIC_OTP_END) ? HPM_OTP : HPM_OTPSHW;
  127. otp_lock_option_t lock_opt = (otp_lock_option_t) ((otp_base->SHADOW_LOCK[lock_reg_idx] & lock_mask)
  128. >> lock_reg_offset);
  129. if (lock_opt != otp_no_lock) {
  130. status = otp_write_disallowed;
  131. break;
  132. }
  133. otp_base->SHADOW[addr] = val;
  134. status = status_success;
  135. } while (false);
  136. return status;
  137. }