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