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