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