1 /*
2  * Copyright (c) 2021 Antmicro <www.antmicro.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_DRIVERS_FPGA_H_
8 #define ZEPHYR_INCLUDE_DRIVERS_FPGA_H_
9 
10 #include <errno.h>
11 
12 #include <zephyr/types.h>
13 #include <zephyr/sys/util.h>
14 #include <zephyr/device.h>
15 
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19 
20 enum FPGA_status {
21 	/* Inactive is when the FPGA cannot accept the bitstream
22 	 * and will not be programmed correctly
23 	 */
24 	FPGA_STATUS_INACTIVE,
25 	/* Active is when the FPGA can accept the bitstream and
26 	 * can be programmed correctly
27 	 */
28 	FPGA_STATUS_ACTIVE
29 };
30 
31 typedef enum FPGA_status (*fpga_api_get_status)(const struct device *dev);
32 typedef int (*fpga_api_load)(const struct device *dev, uint32_t *image_ptr,
33 			     uint32_t img_size);
34 typedef int (*fpga_api_reset)(const struct device *dev);
35 typedef int (*fpga_api_on)(const struct device *dev);
36 typedef int (*fpga_api_off)(const struct device *dev);
37 typedef const char *(*fpga_api_get_info)(const struct device *dev);
38 
39 __subsystem struct fpga_driver_api {
40 	fpga_api_get_status get_status;
41 	fpga_api_reset reset;
42 	fpga_api_load load;
43 	fpga_api_on on;
44 	fpga_api_off off;
45 	fpga_api_get_info get_info;
46 };
47 
48 /**
49  * @brief Read the status of FPGA.
50  *
51  * @param dev FPGA device structure.
52  *
53  * @retval 0 if the FPGA is in INACTIVE state.
54  * @retval 1 if the FPGA is in ACTIVE state.
55  */
fpga_get_status(const struct device * dev)56 static inline enum FPGA_status fpga_get_status(const struct device *dev)
57 {
58 	const struct fpga_driver_api *api =
59 		(const struct fpga_driver_api *)dev->api;
60 
61 	if (api->get_status == NULL) {
62 		/* assume it can never be reprogrammed if it
63 		 * doesn't support the get_status callback
64 		 */
65 		return FPGA_STATUS_INACTIVE;
66 	}
67 
68 	return api->get_status(dev);
69 }
70 
71 /**
72  * @brief Reset the FPGA.
73  *
74  * @param dev FPGA device structure.
75  *
76  * @retval 0 if successful.
77  * @retval Failed Otherwise.
78  */
fpga_reset(const struct device * dev)79 static inline int fpga_reset(const struct device *dev)
80 {
81 	const struct fpga_driver_api *api =
82 		(const struct fpga_driver_api *)dev->api;
83 
84 	if (api->reset == NULL) {
85 		return -ENOTSUP;
86 	}
87 
88 	return api->reset(dev);
89 }
90 
91 /**
92  * @brief Load the bitstream and program the FPGA
93  *
94  * @param dev FPGA device structure.
95  * @param image_ptr Pointer to bitstream.
96  * @param img_size Bitstream size in bytes.
97  *
98  * @retval 0 if successful.
99  * @retval Failed Otherwise.
100  */
fpga_load(const struct device * dev,uint32_t * image_ptr,uint32_t img_size)101 static inline int fpga_load(const struct device *dev, uint32_t *image_ptr,
102 			    uint32_t img_size)
103 {
104 	const struct fpga_driver_api *api =
105 		(const struct fpga_driver_api *)dev->api;
106 
107 	if (api->load == NULL) {
108 		return -ENOTSUP;
109 	}
110 
111 	return api->load(dev, image_ptr, img_size);
112 }
113 
114 /**
115  * @brief Turns on the FPGA.
116  *
117  * @param dev FPGA device structure.
118  *
119  * @retval 0 if successful.
120  * @retval negative errno code on failure.
121  */
fpga_on(const struct device * dev)122 static inline int fpga_on(const struct device *dev)
123 {
124 	const struct fpga_driver_api *api =
125 		(const struct fpga_driver_api *)dev->api;
126 
127 	if (api->on == NULL) {
128 		return -ENOTSUP;
129 	}
130 
131 	return api->on(dev);
132 }
133 
134 #define FPGA_GET_INFO_DEFAULT "n/a"
135 
136 /**
137  * @brief Returns information about the FPGA.
138  *
139  * @param dev FPGA device structure.
140  *
141  * @return String containing information.
142  */
fpga_get_info(const struct device * dev)143 static inline const char *fpga_get_info(const struct device *dev)
144 {
145 	const struct fpga_driver_api *api =
146 		(const struct fpga_driver_api *)dev->api;
147 
148 	if (api->get_info == NULL) {
149 		return FPGA_GET_INFO_DEFAULT;
150 	}
151 
152 	return api->get_info(dev);
153 }
154 
155 /**
156  * @brief Turns off the FPGA.
157  *
158  * @param dev FPGA device structure.
159  *
160  * @retval 0 if successful.
161  * @retval negative errno code on failure.
162  */
fpga_off(const struct device * dev)163 static inline int fpga_off(const struct device *dev)
164 {
165 	const struct fpga_driver_api *api =
166 		(const struct fpga_driver_api *)dev->api;
167 
168 	if (api->off == NULL) {
169 		return -ENOTSUP;
170 	}
171 
172 	return api->off(dev);
173 }
174 
175 #ifdef __cplusplus
176 }
177 #endif
178 
179 #endif /* ZEPHYR_INCLUDE_DRIVERS_FPGA_H_ */
180