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