1 /*
2 * Copyright (c) 2020 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief EDAC API header file
10 */
11
12 #ifndef ZEPHYR_INCLUDE_DRIVERS_EDAC_H_
13 #define ZEPHYR_INCLUDE_DRIVERS_EDAC_H_
14
15 #include <errno.h>
16
17 #include <sys/types.h>
18
19 /**
20 * @defgroup edac EDAC API
21 * @since 2.5
22 * @version 0.8.0
23 * @ingroup io_interfaces
24 * @{
25 */
26
27 /**
28 * @brief EDAC error type
29 */
30 enum edac_error_type {
31 /** Correctable error type */
32 EDAC_ERROR_TYPE_DRAM_COR = BIT(0),
33 /** Uncorrectable error type */
34 EDAC_ERROR_TYPE_DRAM_UC = BIT(1)
35 };
36
37 /**
38 * @cond INTERNAL_HIDDEN
39 *
40 * For internal use only, skip these in public documentation.
41 */
42
43 typedef void (*edac_notify_callback_f)(const struct device *dev, void *data);
44
45 /**
46 * @brief EDAC driver API
47 *
48 * This is the mandatory API any EDAC driver needs to expose.
49 */
50 __subsystem struct edac_driver_api {
51 /* Error Injection API is disabled by default */
52 int (*inject_set_param1)(const struct device *dev, uint64_t value);
53 int (*inject_get_param1)(const struct device *dev, uint64_t *value);
54 int (*inject_set_param2)(const struct device *dev, uint64_t value);
55 int (*inject_get_param2)(const struct device *dev, uint64_t *value);
56 int (*inject_set_error_type)(const struct device *dev, uint32_t value);
57 int (*inject_get_error_type)(const struct device *dev, uint32_t *value);
58 int (*inject_error_trigger)(const struct device *dev);
59
60 /* Error Logging API */
61 int (*ecc_error_log_get)(const struct device *dev, uint64_t *value);
62 int (*ecc_error_log_clear)(const struct device *dev);
63 int (*parity_error_log_get)(const struct device *dev, uint64_t *value);
64 int (*parity_error_log_clear)(const struct device *dev);
65
66 /* Error stats API */
67 int (*errors_cor_get)(const struct device *dev);
68 int (*errors_uc_get)(const struct device *dev);
69
70 /* Notification callback API */
71 int (*notify_cb_set)(const struct device *dev,
72 edac_notify_callback_f cb);
73 };
74
75 /**
76 * INTERNAL_HIDDEN @endcond
77 */
78
79 /**
80 * @name Optional interfaces
81 * @{
82 *
83 * EDAC Optional Interfaces
84 */
85
86 /**
87 * @brief Set injection parameter param1
88 *
89 * Set first error injection parameter value.
90 *
91 * @param dev Pointer to the device structure
92 * @param value First injection parameter
93 *
94 * @retval -ENOSYS if the optional interface is not implemented
95 * @retval 0 on success, other error code otherwise
96 */
edac_inject_set_param1(const struct device * dev,uint64_t value)97 static inline int edac_inject_set_param1(const struct device *dev,
98 uint64_t value)
99 {
100 const struct edac_driver_api *api =
101 (const struct edac_driver_api *)dev->api;
102
103 if (api->inject_set_param1 == NULL) {
104 return -ENOSYS;
105 }
106
107 return api->inject_set_param1(dev, value);
108 }
109
110 /**
111 * @brief Get injection parameter param1
112 *
113 * Get first error injection parameter value.
114 *
115 * @param dev Pointer to the device structure
116 * @param value Pointer to the first injection parameter
117 *
118 * @retval -ENOSYS if the optional interface is not implemented
119 * @retval 0 on success, error code otherwise
120 */
edac_inject_get_param1(const struct device * dev,uint64_t * value)121 static inline int edac_inject_get_param1(const struct device *dev,
122 uint64_t *value)
123 {
124 const struct edac_driver_api *api =
125 (const struct edac_driver_api *)dev->api;
126
127 if (api->inject_get_param1 == NULL) {
128 return -ENOSYS;
129 }
130
131 return api->inject_get_param1(dev, value);
132
133 }
134
135 /**
136 * @brief Set injection parameter param2
137 *
138 * Set second error injection parameter value.
139 *
140 * @param dev Pointer to the device structure
141 * @param value Second injection parameter
142 *
143 * @retval -ENOSYS if the optional interface is not implemented
144 * @retval 0 on success, error code otherwise
145 */
edac_inject_set_param2(const struct device * dev,uint64_t value)146 static inline int edac_inject_set_param2(const struct device *dev,
147 uint64_t value)
148 {
149 const struct edac_driver_api *api =
150 (const struct edac_driver_api *)dev->api;
151
152 if (api->inject_set_param2 == NULL) {
153 return -ENOSYS;
154 }
155
156 return api->inject_set_param2(dev, value);
157 }
158
159 /**
160 * @brief Get injection parameter param2
161 *
162 * @param dev Pointer to the device structure
163 * @param value Pointer to the second injection parameter
164 *
165 * @retval -ENOSYS if the optional interface is not implemented
166 * @retval 0 on success, error code otherwise
167 */
edac_inject_get_param2(const struct device * dev,uint64_t * value)168 static inline int edac_inject_get_param2(const struct device *dev,
169 uint64_t *value)
170 {
171 const struct edac_driver_api *api =
172 (const struct edac_driver_api *)dev->api;
173
174 if (api->inject_get_param2 == NULL) {
175 return -ENOSYS;
176 }
177
178 return api->inject_get_param2(dev, value);
179 }
180
181 /**
182 * @brief Set error type value
183 *
184 * Set the value of error type to be injected
185 *
186 * @param dev Pointer to the device structure
187 * @param error_type Error type value
188 *
189 * @retval -ENOSYS if the optional interface is not implemented
190 * @retval 0 on success, error code otherwise
191 */
edac_inject_set_error_type(const struct device * dev,uint32_t error_type)192 static inline int edac_inject_set_error_type(const struct device *dev,
193 uint32_t error_type)
194 {
195 const struct edac_driver_api *api =
196 (const struct edac_driver_api *)dev->api;
197
198 if (api->inject_set_error_type == NULL) {
199 return -ENOSYS;
200 }
201
202 return api->inject_set_error_type(dev, error_type);
203 }
204
205 /**
206 * @brief Get error type value
207 *
208 * Get the value of error type to be injected
209 *
210 * @param dev Pointer to the device structure
211 * @param error_type Pointer to error type value
212 *
213 * @retval -ENOSYS if the optional interface is not implemented
214 * @retval 0 on success, error code otherwise
215 */
edac_inject_get_error_type(const struct device * dev,uint32_t * error_type)216 static inline int edac_inject_get_error_type(const struct device *dev,
217 uint32_t *error_type)
218 {
219 const struct edac_driver_api *api =
220 (const struct edac_driver_api *)dev->api;
221
222 if (api->inject_get_error_type == NULL) {
223 return -ENOSYS;
224 }
225
226 return api->inject_get_error_type(dev, error_type);
227 }
228
229 /**
230 * @brief Set injection control
231 *
232 * Trigger error injection.
233 *
234 * @param dev Pointer to the device structure
235 *
236 * @retval -ENOSYS if the optional interface is not implemented
237 * @retval 0 on success, error code otherwise
238 */
edac_inject_error_trigger(const struct device * dev)239 static inline int edac_inject_error_trigger(const struct device *dev)
240 {
241 const struct edac_driver_api *api =
242 (const struct edac_driver_api *)dev->api;
243
244 if (api->inject_error_trigger == NULL) {
245 return -ENOSYS;
246 }
247
248 return api->inject_error_trigger(dev);
249 }
250
251 /** @} */ /* End of EDAC Optional Interfaces */
252
253 /**
254 * @name Mandatory interfaces
255 * @{
256 *
257 * EDAC Mandatory Interfaces
258 */
259
260 /**
261 * @brief Get ECC Error Log
262 *
263 * Read value of ECC Error Log.
264 *
265 * @param dev Pointer to the device structure
266 * @param value Pointer to the ECC Error Log value
267 *
268 * @retval 0 on success, error code otherwise
269 * @retval -ENOSYS if the mandatory interface is not implemented
270 */
edac_ecc_error_log_get(const struct device * dev,uint64_t * value)271 static inline int edac_ecc_error_log_get(const struct device *dev,
272 uint64_t *value)
273 {
274 const struct edac_driver_api *api =
275 (const struct edac_driver_api *)dev->api;
276
277 if (api->ecc_error_log_get == NULL) {
278 return -ENOSYS;
279 }
280
281 return api->ecc_error_log_get(dev, value);
282 }
283
284 /**
285 * @brief Clear ECC Error Log
286 *
287 * Clear value of ECC Error Log.
288 *
289 * @param dev Pointer to the device structure
290 *
291 * @retval 0 on success, error code otherwise
292 * @retval -ENOSYS if the mandatory interface is not implemented
293 */
edac_ecc_error_log_clear(const struct device * dev)294 static inline int edac_ecc_error_log_clear(const struct device *dev)
295 {
296 const struct edac_driver_api *api =
297 (const struct edac_driver_api *)dev->api;
298
299 if (api->ecc_error_log_clear == NULL) {
300 return -ENOSYS;
301 }
302
303 return api->ecc_error_log_clear(dev);
304 }
305
306 /**
307 * @brief Get Parity Error Log
308 *
309 * Read value of Parity Error Log.
310 *
311 * @param dev Pointer to the device structure
312 * @param value Pointer to the parity Error Log value
313 *
314 * @retval 0 on success, error code otherwise
315 * @retval -ENOSYS if the mandatory interface is not implemented
316 */
edac_parity_error_log_get(const struct device * dev,uint64_t * value)317 static inline int edac_parity_error_log_get(const struct device *dev,
318 uint64_t *value)
319 {
320 const struct edac_driver_api *api =
321 (const struct edac_driver_api *)dev->api;
322
323 if (api->parity_error_log_get == NULL) {
324 return -ENOSYS;
325 }
326
327 return api->parity_error_log_get(dev, value);
328 }
329
330 /**
331 * @brief Clear Parity Error Log
332 *
333 * Clear value of Parity Error Log.
334 *
335 * @param dev Pointer to the device structure
336 *
337 * @retval 0 on success, error code otherwise
338 * @retval -ENOSYS if the mandatory interface is not implemented
339 */
edac_parity_error_log_clear(const struct device * dev)340 static inline int edac_parity_error_log_clear(const struct device *dev)
341 {
342 const struct edac_driver_api *api =
343 (const struct edac_driver_api *)dev->api;
344
345 if (api->parity_error_log_clear == NULL) {
346 return -ENOSYS;
347 }
348
349 return api->parity_error_log_clear(dev);
350 }
351
352 /**
353 * @brief Get number of correctable errors
354 *
355 * @param dev Pointer to the device structure
356 *
357 * @retval num Number of correctable errors
358 * @retval -ENOSYS if the mandatory interface is not implemented
359 */
edac_errors_cor_get(const struct device * dev)360 static inline int edac_errors_cor_get(const struct device *dev)
361 {
362 const struct edac_driver_api *api =
363 (const struct edac_driver_api *)dev->api;
364
365 if (api->errors_cor_get == NULL) {
366 return -ENOSYS;
367 }
368
369 return api->errors_cor_get(dev);
370 }
371
372 /**
373 * @brief Get number of uncorrectable errors
374 *
375 * @param dev Pointer to the device structure
376 *
377 * @retval num Number of uncorrectable errors
378 * @retval -ENOSYS if the mandatory interface is not implemented
379 */
edac_errors_uc_get(const struct device * dev)380 static inline int edac_errors_uc_get(const struct device *dev)
381 {
382 const struct edac_driver_api *api =
383 (const struct edac_driver_api *)dev->api;
384
385 if (api->errors_uc_get == NULL) {
386 return -ENOSYS;
387 }
388
389 return api->errors_uc_get(dev);
390 }
391
392 /**
393 * Register callback function for memory error exception
394 *
395 * This callback runs in interrupt context
396 *
397 * @param dev EDAC driver device to install callback
398 * @param cb Callback function pointer
399 *
400 * @retval 0 on success, error code otherwise
401 * @retval -ENOSYS if the mandatory interface is not implemented
402 */
edac_notify_callback_set(const struct device * dev,edac_notify_callback_f cb)403 static inline int edac_notify_callback_set(const struct device *dev,
404 edac_notify_callback_f cb)
405 {
406 const struct edac_driver_api *api = (const struct edac_driver_api *)dev->api;
407
408 if (api->notify_cb_set == NULL) {
409 return -ENOSYS;
410 }
411
412 return api->notify_cb_set(dev, cb);
413 }
414
415
416 /** @} */ /* End of EDAC Mandatory Interfaces */
417
418 /** @} */ /* End of EDAC API */
419
420 #endif /* ZEPHYR_INCLUDE_DRIVERS_EDAC_H_ */
421