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