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