1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright 2021 NXP 4 */ 5 #include <arm.h> 6 #include <initcall.h> 7 #include <mm/core_memprot.h> 8 #include <mm/core_mmu.h> 9 #include <imx.h> 10 #include <io.h> 11 #include <drivers/imx_ocotp.h> 12 #include <kernel/tee_common_otp.h> 13 14 #define OCOTP_CTRL 0x0 15 16 #if defined(CFG_MX8MP) 17 #define OCOTP_CTRL_ERROR BIT32(10) 18 #define OCOTP_CTRL_BUSY BIT32(9) 19 #else 20 #define OCOTP_CTRL_ERROR BIT32(9) 21 #define OCOTP_CTRL_BUSY BIT32(8) 22 #endif 23 24 #if defined(CFG_MX6) || defined(CFG_MX7ULP) 25 #define OCOTP_SHADOW_OFFSET(_b, _w) ((_b) * (0x80) + (_w) * (0x10) + 0x400) 26 #else 27 #define OCOTP_SHADOW_OFFSET(_b, _w) ((_b) * (0x40) + (_w) * (0x10) + 0x400) 28 #endif 29 30 struct ocotp_instance { 31 unsigned char nb_banks; 32 unsigned char nb_words; 33 TEE_Result (*get_die_id)(uint64_t *ret_uid); 34 }; 35 36 static vaddr_t g_base_addr; 37 static struct mutex fuse_read = MUTEX_INITIALIZER; 38 static const struct ocotp_instance *g_ocotp; 39 40 #if defined(CFG_MX6) 41 static void ocotp_clock_enable(void) 42 { 43 vaddr_t va = core_mmu_get_va(CCM_BASE, MEM_AREA_IO_SEC, CCM_SIZE); 44 45 io_setbits32(va + CCM_CCGR2, BM_CCM_CCGR2_OCOTP_CTRL); 46 } 47 #elif defined(CFG_MX7) 48 static void ocotp_clock_enable(void) 49 { 50 vaddr_t va = core_mmu_get_va(CCM_BASE, MEM_AREA_IO_SEC, CCM_SIZE); 51 52 io_setbits32(va + CCM_CCGRx_SET(CCM_CLOCK_DOMAIN_OCOTP), 53 CCM_CCGRx_ALWAYS_ON(0)); 54 } 55 #elif defined(CFG_MX8M) 56 static void ocotp_clock_enable(void) 57 { 58 vaddr_t va = core_mmu_get_va(CCM_BASE, MEM_AREA_IO_SEC, CCM_SIZE); 59 60 io_setbits32(va + CCM_CCGRx_SET(CCM_CCRG_OCOTP), 61 CCM_CCGRx_ALWAYS_ON(0)); 62 } 63 #elif defined(CFG_MX7ULP) 64 /* The i.MX7ULP has the OCOTP always powered on */ 65 static inline void ocotp_clock_enable(void) { } 66 #else 67 #error "Platform not supported" 68 #endif 69 70 static TEE_Result ocotp_ctrl_wait_for(uint32_t mask) 71 { 72 unsigned int loop = 0; 73 uint32_t reg = 0; 74 75 assert(g_base_addr); 76 77 /* 20us delay assuming the CPU clock running at 500MHz */ 78 for (loop = 10000; loop > 0; loop--) { 79 reg = io_read32(g_base_addr + OCOTP_CTRL) & mask; 80 if (!reg) 81 return TEE_SUCCESS; 82 dsb(); 83 isb(); 84 } 85 86 return TEE_ERROR_BUSY; 87 } 88 89 TEE_Result imx_ocotp_read(unsigned int bank, unsigned int word, uint32_t *val) 90 { 91 TEE_Result ret = TEE_ERROR_GENERIC; 92 93 if (!val) 94 return TEE_ERROR_BAD_PARAMETERS; 95 96 if (bank > g_ocotp->nb_banks || word > g_ocotp->nb_words) 97 return TEE_ERROR_BAD_PARAMETERS; 98 99 assert(g_base_addr && g_ocotp); 100 101 mutex_lock(&fuse_read); 102 103 ocotp_clock_enable(); 104 105 /* Clear error bit */ 106 io_clrbits32(g_base_addr + OCOTP_CTRL, OCOTP_CTRL_ERROR); 107 108 /* Wait for busy flag to be cleared */ 109 ret = ocotp_ctrl_wait_for(OCOTP_CTRL_BUSY); 110 if (ret) { 111 EMSG("OCOTP is busy"); 112 goto out; 113 } 114 115 /* Read shadow register */ 116 *val = io_read32(g_base_addr + OCOTP_SHADOW_OFFSET(bank, word)); 117 118 DMSG("OCOTP Bank %d Word %d Fuse 0x%" PRIx32, bank, word, *val); 119 out: 120 mutex_unlock(&fuse_read); 121 122 return ret; 123 } 124 125 static TEE_Result ocotp_get_die_id_mx7ulp(uint64_t *ret_uid) 126 { 127 TEE_Result res = TEE_ERROR_GENERIC; 128 uint32_t val = 0; 129 uint64_t uid = 0; 130 131 res = imx_ocotp_read(1, 6, &val); 132 if (res) 133 goto out; 134 uid = val & GENMASK_32(15, 0); 135 136 res = imx_ocotp_read(1, 5, &val); 137 if (res) 138 goto out; 139 uid = SHIFT_U64(uid, 16) | (val & GENMASK_32(15, 0)); 140 141 res = imx_ocotp_read(1, 4, &val); 142 if (res) 143 goto out; 144 uid = SHIFT_U64(uid, 16) | (val & GENMASK_32(15, 0)); 145 146 res = imx_ocotp_read(1, 3, &val); 147 if (res) 148 goto out; 149 uid = SHIFT_U64(uid, 16) | (val & GENMASK_32(15, 0)); 150 151 out: 152 if (res == TEE_SUCCESS) 153 *ret_uid = uid; 154 155 return res; 156 } 157 158 static TEE_Result ocotp_get_die_id_mx(uint64_t *ret_uid) 159 { 160 TEE_Result res = TEE_ERROR_GENERIC; 161 uint32_t val = 0; 162 uint64_t uid = 0; 163 164 res = imx_ocotp_read(0, 2, &val); 165 if (res) 166 goto out; 167 uid = val; 168 169 res = imx_ocotp_read(0, 1, &val); 170 if (res) 171 goto out; 172 uid = SHIFT_U64(uid, 32) | val; 173 174 out: 175 if (res == TEE_SUCCESS) 176 *ret_uid = uid; 177 178 return res; 179 } 180 181 static const struct ocotp_instance ocotp_imx6q = { 182 .nb_banks = 16, 183 .nb_words = 8, 184 .get_die_id = ocotp_get_die_id_mx, 185 }; 186 187 static const struct ocotp_instance ocotp_imx6sl = { 188 .nb_banks = 8, 189 .nb_words = 8, 190 .get_die_id = ocotp_get_die_id_mx, 191 }; 192 193 static const struct ocotp_instance ocotp_imx6sll = { 194 .nb_banks = 16, 195 .nb_words = 8, 196 .get_die_id = ocotp_get_die_id_mx, 197 }; 198 199 static const struct ocotp_instance ocotp_imx6sx = { 200 .nb_banks = 16, 201 .nb_words = 8, 202 .get_die_id = ocotp_get_die_id_mx, 203 }; 204 205 static const struct ocotp_instance ocotp_imx6ul = { 206 .nb_banks = 16, 207 .nb_words = 8, 208 .get_die_id = ocotp_get_die_id_mx, 209 }; 210 211 static const struct ocotp_instance ocotp_imx6ull = { 212 .nb_banks = 8, 213 .nb_words = 8, 214 .get_die_id = ocotp_get_die_id_mx, 215 }; 216 217 static const struct ocotp_instance ocotp_imx7d = { 218 .nb_banks = 8, 219 .nb_words = 8, 220 .get_die_id = ocotp_get_die_id_mx, 221 }; 222 223 static const struct ocotp_instance ocotp_imx7ulp = { 224 .nb_banks = 32, 225 .nb_words = 8, 226 .get_die_id = ocotp_get_die_id_mx7ulp, 227 }; 228 229 static const struct ocotp_instance ocotp_imx8m = { 230 .nb_banks = 32, 231 .nb_words = 8, 232 .get_die_id = ocotp_get_die_id_mx, 233 }; 234 235 static const struct ocotp_instance ocotp_imx8mp = { 236 .nb_banks = 48, 237 .nb_words = 8, 238 .get_die_id = ocotp_get_die_id_mx, 239 }; 240 241 int tee_otp_get_die_id(uint8_t *buffer, size_t len) 242 { 243 size_t max_size_uid = IMX_UID_SIZE; 244 uint64_t uid = 0; 245 246 assert(buffer); 247 assert(g_base_addr && g_ocotp); 248 249 if (g_ocotp->get_die_id(&uid)) 250 goto err; 251 252 memcpy(buffer, &uid, MIN(max_size_uid, len)); 253 return 0; 254 255 err: 256 EMSG("Error while getting die ID"); 257 return -1; 258 } 259 260 register_phys_mem_pgdir(MEM_AREA_IO_SEC, OCOTP_BASE, CORE_MMU_PGDIR_SIZE); 261 static TEE_Result imx_ocotp_init(void) 262 { 263 g_base_addr = core_mmu_get_va(OCOTP_BASE, MEM_AREA_IO_SEC, OCOTP_SIZE); 264 if (!g_base_addr) 265 return TEE_ERROR_GENERIC; 266 267 if (soc_is_imx6sdl() || soc_is_imx6dq() || soc_is_imx6dqp()) { 268 g_ocotp = &ocotp_imx6q; 269 } else if (soc_is_imx6sl()) { 270 g_ocotp = &ocotp_imx6sl; 271 } else if (soc_is_imx6sll()) { 272 g_ocotp = &ocotp_imx6sll; 273 } else if (soc_is_imx6sx()) { 274 g_ocotp = &ocotp_imx6sx; 275 } else if (soc_is_imx6ul()) { 276 g_ocotp = &ocotp_imx6ul; 277 } else if (soc_is_imx6ull()) { 278 g_ocotp = &ocotp_imx6ull; 279 } else if (soc_is_imx7ds()) { 280 g_ocotp = &ocotp_imx7d; 281 } else if (soc_is_imx7ulp()) { 282 g_ocotp = &ocotp_imx7ulp; 283 } else if (soc_is_imx8mm() || soc_is_imx8mn() || soc_is_imx8mq()) { 284 g_ocotp = &ocotp_imx8m; 285 } else if (soc_is_imx8mp()) { 286 g_ocotp = &ocotp_imx8mp; 287 } else { 288 g_ocotp = NULL; 289 return TEE_ERROR_NOT_SUPPORTED; 290 } 291 292 return TEE_SUCCESS; 293 } 294 service_init(imx_ocotp_init); 295