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