1 /* 2 * Copyright (c) 2022-2024, Arm Limited. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /** 18 * \file lcm_drv.h 19 * \brief Driver for Arm LCM. 20 */ 21 22 #ifndef __LCM_DRV_H__ 23 #define __LCM_DRV_H__ 24 25 #include <stdint.h> 26 #include <stdbool.h> 27 28 #ifdef __cplusplus 29 extern "C" { 30 #endif 31 32 #define LCM_DCU_WIDTH_IN_BYTES (16) 33 #define LCM_OTP_OFFSET 0x1000 34 35 struct lcm_otp_layout_t { 36 volatile uint32_t huk[8]; 37 volatile uint32_t guk[8]; 38 volatile uint32_t kp_cm[8]; 39 volatile uint32_t kce_cm[8]; 40 volatile uint32_t kp_dm[8]; 41 volatile uint32_t kce_dm[8]; 42 volatile uint32_t rotpk[8]; 43 volatile uint32_t tp_mode_config; 44 volatile uint32_t cm_config_1; 45 volatile uint32_t cm_config_2; 46 volatile uint32_t dm_config; 47 volatile uint32_t cm_rma_flag; 48 volatile uint32_t dm_rma_flag; 49 volatile uint32_t user_data[]; 50 }; 51 52 /** 53 * \brief ARM LCM LCS enumeration types 54 * 55 * \note These high hamming-weight constants are required by the hardware. 56 */ 57 enum lcm_lcs_t { 58 LCM_LCS_CM = (0xCCCC3C3Cu), 59 LCM_LCS_DM = (0xDDDD5A5Au), 60 LCM_LCS_SE = (0xEEEEA5A5u), 61 LCM_LCS_RMA = (0xFFFFC3C3u), 62 LCM_LCS_INVALID = (0xDEADBEEFu), 63 }; 64 65 /** 66 * \brief ARM LCM TP mode enumeration types 67 * 68 * \note These high hamming-weight constants are required by the hardware. 69 */ 70 enum lcm_tp_mode_t { 71 LCM_TP_MODE_VIRGIN = (0x000033CCu), 72 LCM_TP_MODE_TCI = (0x111155AAu), 73 LCM_TP_MODE_PCI = (0x2222AA55u), 74 LCM_TP_MODE_INVALID = (0xDEADBEEFu), 75 }; 76 77 /** 78 * \brief ARM LCM SP mode enumeration types 79 * 80 * \note These high hamming-weight constants are required by the hardware. 81 */ 82 enum lcm_bool_t { 83 LCM_FALSE = (0x00000000u), 84 LCM_TRUE = (0xFFFFFFFFu), 85 }; 86 87 /** 88 * \brief ARM LCM error enumeration types 89 */ 90 enum lcm_error_t { 91 LCM_ERROR_NONE = (0x0u), 92 LCM_ERROR_INVALID_KEY, 93 LCM_ERROR_INVALID_ALIGNMENT, 94 LCM_ERROR_INVALID_LENGTH, 95 LCM_ERROR_INVALID_OFFSET, 96 LCM_ERROR_INVALID_WRITE, 97 LCM_ERROR_INVALID_TRANSITION, 98 LCM_ERROR_INVALID_LCS, 99 LCM_ERROR_INVALID_TP_MODE, 100 LCM_ERROR_INVALID_POINTER, 101 LCM_ERROR_INTERNAL_ERROR, 102 LCM_ERROR_WRITE_VERIFY_FAIL, 103 LCM_ERROR_READ_VERIFY_FAIL, 104 LCM_ERR_INVALID_ZERO_COUNT, 105 LCM_ERR_DCU_MASK_MISMATCH, 106 LCM_ERROR_FATAL_ERR, 107 }; 108 109 /** 110 * \brief ARM LCM device configuration structure 111 */ 112 struct lcm_dev_cfg_t { 113 const uint32_t base; /*!< LCM base address */ 114 }; 115 116 /** 117 * \brief ARM LCM device structure 118 */ 119 struct lcm_dev_t { 120 const struct lcm_dev_cfg_t* const cfg; /*!< LCM configuration */ 121 }; 122 123 124 /** 125 * \brief This function initializes the LCM 126 * 127 * \param[in] dev The LCM device structure. 128 * 129 * \return Returns error code as specified in \ref lcm_error_t 130 */ 131 enum lcm_error_t lcm_init(struct lcm_dev_t *dev); 132 133 /** 134 * \brief This function gets the TP mode 135 * 136 * \param[in] dev The LCM device structure. 137 * \param[out] mode The TP mode the device is currently in. 138 * 139 * \return Returns error code as specified in \ref lcm_error_t 140 */ 141 enum lcm_error_t lcm_get_tp_mode(struct lcm_dev_t *dev, enum lcm_tp_mode_t *mode); 142 /** 143 * \brief This function sets the TP mode 144 * 145 * \param[in] dev The LCM device structure. 146 * \param[in] mode The TP mode to transition the device to. 147 * 148 * \return Returns error code as specified in \ref lcm_error_t 149 */ 150 enum lcm_error_t lcm_set_tp_mode(struct lcm_dev_t *dev, enum lcm_tp_mode_t mode); 151 152 /** 153 * \brief This function checks if secure provisioning mode is enabled 154 * 155 * \param[in] dev The LCM device structure. 156 * \param[out] enabled Whether secure provisioning mode is enabled. 157 * 158 * \return Returns error code as specified in \ref lcm_error_t 159 */ 160 enum lcm_error_t lcm_get_sp_enabled(struct lcm_dev_t *dev, enum lcm_bool_t *enabled); 161 /** 162 * \brief This function enables secure provisioning mode. 163 * 164 * \param[in] dev The LCM device structure. 165 * 166 * \note This function may cause some or all device components to be reset, and 167 * may begin executing code from the reset vector. 168 * 169 * \return Returns error code as specified in \ref lcm_error_t 170 */ 171 enum lcm_error_t lcm_set_sp_enabled(struct lcm_dev_t *dev); 172 173 /** 174 * \brief This function checks if fatal error mode is enabled 175 * 176 * \param[in] dev The LCM device structure. 177 * \param[out] error Whether fatal error mode is enabled. 178 * 179 * \return Returns error code as specified in \ref lcm_error_t 180 */ 181 enum lcm_error_t lcm_get_fatal_error(struct lcm_dev_t *dev, enum lcm_bool_t *error); 182 /** 183 * \brief This function enables fatal error mode. 184 * 185 * \param[in] dev The LCM device structure. 186 * 187 * \note This function will cause the LCM to be inoperable until the device is 188 * reset. 189 * 190 * \return Returns error code as specified in \ref lcm_error_t 191 */ 192 enum lcm_error_t lcm_set_fatal_error(struct lcm_dev_t *dev); 193 194 /** 195 * \brief This function gets the General purpose persistent configuration. 196 * 197 * \param[in] dev The LCM device structure. 198 * \param[out] gppc The value of the gppc. 199 * 200 * \return Returns error code as specified in \ref lcm_error_t 201 */ 202 enum lcm_error_t lcm_get_gppc(struct lcm_dev_t *dev, uint32_t *gppc); 203 204 /** 205 * \brief This function gets the size of the OTP managed by the LCM. 206 * 207 * \param[in] dev The LCM device structure. 208 * \param[out] size The size (in bytes) of the OTP. 209 * 210 * \return Returns error code as specified in \ref lcm_error_t 211 */ 212 enum lcm_error_t lcm_get_otp_size(struct lcm_dev_t *dev, uint32_t *size); 213 214 /** 215 * \brief This function gets Lifecycle State the LCM is currently in. 216 * 217 * \param[in] dev The LCM device structure. 218 * \param[out] lcs The LCS the device is currently in. 219 * 220 * \return Returns error code as specified in \ref lcm_error_t 221 */ 222 enum lcm_error_t lcm_get_lcs(struct lcm_dev_t *dev, enum lcm_lcs_t *lcs); 223 /** 224 * \brief This function gets Lifecycle State the LCM is currently in. 225 * 226 * \param[in] dev The LCM device structure. 227 * \param[in] lcs The LCS to transition to. 228 * \param[in] gppc_val The value that the General Purpose Persistent 229 * Configuration should be set to. Mandatory when lcs 230 * parameter == LCM_LCS_DM, unused otherwise. 231 * 232 * \note Some LCS transitions are illegal 233 * \note A cold system reset is required after this function returns for the new 234 * LCS to be entered. 235 * 236 * \return Returns error code as specified in \ref lcm_error_t 237 */ 238 enum lcm_error_t lcm_set_lcs(struct lcm_dev_t *dev, enum lcm_lcs_t lcs, 239 uint16_t gppc_val); 240 241 /** 242 * \brief This function writes the OTP managed by the LCM. 243 * 244 * \param[in] dev The LCM device structure. 245 * \param[in] offset The offset into the OTP to write. Must be 4 byte aligned 246 * \param[in] len The length of the OTP region to write. Must be 4 byte 247 * aligned. 248 * \param[in] buf The buffer containing the data to write into OTP. Must 249 * be 4 byte aligned and of a multiple of 4 bytes in length 250 * 251 * \note This function does not allow writes into OTP words that have already 252 * been written. 253 * 254 * \return Returns error code as specified in \ref lcm_error_t 255 */ 256 enum lcm_error_t lcm_otp_write(struct lcm_dev_t *dev, uint32_t offset, uint32_t len, 257 const uint8_t *buf); 258 259 /** 260 * \brief This function reads the OTP managed by the LCM. 261 * 262 * \param[in] dev The LCM device structure. 263 * \param[in] offset The offset into the OTP to write. Must be 4 byte aligned 264 * \param[in] len The length of the OTP region to write. Must be 4 byte 265 * aligned. 266 * \param[out] buf The buffer that will be filled with the OTP content. 267 * Must be 4 byte aligned and of a multiple of 4 bytes in 268 * length. 269 * 270 * \return Returns error code as specified in \ref lcm_error_t 271 */ 272 enum lcm_error_t lcm_otp_read(struct lcm_dev_t *dev, uint32_t offset, uint32_t len, 273 uint8_t *buf); 274 275 /** 276 * \brief This function gets the state of the Debug Control Unit. 277 * 278 * \param[in] dev The LCM device structure. 279 * \param[out] val The buffer into which to write the value of the DCU. Must 280 * be LCM_DCU_WIDTH_IN_BYTES in size, and 4 byte aligned. 281 * 282 * \return Returns error code as specified in \ref lcm_error_t 283 */ 284 enum lcm_error_t lcm_dcu_get_enabled(struct lcm_dev_t *dev, uint8_t *val); 285 /** 286 * \brief This function sets the state of the Debug Control Unit. 287 * 288 * \param[in] dev The LCM device structure. 289 * \param[in] val The buffer whose value the DCU will be set to. Must 290 * be LCM_DCU_WIDTH_IN_BYTES in size, and 4 byte aligned. 291 * 292 * \return Returns error code as specified in \ref lcm_error_t 293 */ 294 enum lcm_error_t lcm_dcu_set_enabled(struct lcm_dev_t *dev, uint8_t *val); 295 296 /** 297 * \brief This function gets the state of the Debug Control Unit Lock. 298 * 299 * \param[in] dev The LCM device structure. 300 * \param[out] val The buffer into which to write the value of the DCU Lock. 301 * Must be LCM_DCU_WIDTH_IN_BYTES in size, and 4 byte aligned 302 * 303 * \return Returns error code as specified in \ref lcm_error_t 304 */ 305 enum lcm_error_t lcm_dcu_get_locked(struct lcm_dev_t *dev, uint8_t *val); 306 /** 307 * \brief This function sets the state of the Debug Control Unit Lock. 308 * 309 * \param[in] dev The LCM device structure. 310 * \param[in] val The buffer whose value the DCU lock will be set to. Must 311 * be LCM_DCU_WIDTH_IN_BYTES in size, and 4 byte aligned. 312 * 313 * \return Returns error code as specified in \ref lcm_error_t 314 */ 315 enum lcm_error_t lcm_dcu_set_locked(struct lcm_dev_t *dev, uint8_t *val); 316 317 /** 318 * \brief This function gets the state of the Debug Control Unit Secure 319 * Provisioning Disable Mask. This mask controls which DCU bits cannot be 320 * enabled in secure provisioning mode. This mask is set in hardware. 321 * 322 * \param[in] dev The LCM device structure. 323 * \param[out] val The buffer into which to write the value of the DCU Lock. 324 * Must be LCM_DCU_WIDTH_IN_BYTES in size, and 4 byte aligned 325 * 326 * \return Returns error code as specified in \ref lcm_error_t 327 */ 328 enum lcm_error_t lcm_dcu_get_sp_disable_mask(struct lcm_dev_t *dev, uint8_t *val); 329 /** 330 * \brief This function gets the state of the Debug Control Unit Disable Mask. 331 * This mask controls which DCU bits cannot be enabled. This mask is set 332 * in hardware 333 * 334 * \param[in] dev The LCM device structure. 335 * \param[out] val The buffer into which to write the value of the DCU Lock. 336 * Must be LCM_DCU_WIDTH_IN_BYTES in size, and 4 byte aligned 337 * 338 * \return Returns error code as specified in \ref lcm_error_t 339 */ 340 enum lcm_error_t lcm_dcu_get_disable_mask(struct lcm_dev_t *dev, uint8_t *val); 341 342 #ifdef __cplusplus 343 } 344 #endif 345 #endif /* __LCM_DRV_H__ */ 346