1 /*
2  * Copyright (c) 2019 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief Public APIs for eSPI driver
10  */
11 
12 #ifndef ZEPHYR_INCLUDE_ESPI_SAF_H_
13 #define ZEPHYR_INCLUDE_ESPI_SAF_H_
14 
15 #include <zephyr/sys/__assert.h>
16 #include <zephyr/types.h>
17 #include <zephyr/device.h>
18 
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22 
23 /**
24  * @brief eSPI SAF Driver APIs
25  * @defgroup espi_interface ESPI Driver APIs
26  * @ingroup io_interfaces
27  * @{
28  */
29 
30 
31 /**
32  * @code
33  *+----------------------------------------------------------------------+
34  *|                                                                      |
35  *|  eSPI host                           +-------------+                 |
36  *|                      +-----------+   |    Power    |   +----------+  |
37  *|                      |Out of band|   |  management |   |   GPIO   |  |
38  *|   ------------       |processor  |   |  controller |   |  sources |  |
39  *|                      +-----------+   +-------------+   +----------+  |
40  *|                            |                |               |        |
41  *|   ------------             |                |               |        |
42  *|                            +--------+       +---------------+        |
43  *|                                     |               |                |
44  *|            -----+   +--------+   +----------+  +----v-----+          |
45  *|                 |   |  LPC   |   | Tunneled |  | Tunneled |          |
46  *|                 |   | bridge |   |  SMBus   |  |   GPIO   |          |
47  *|                 |   +--------+   +----------+  +----------+          |
48  *|                 |        |             |             |               |
49  *|                 |        ------+       |             |               |
50  *|                 |              |       |             |               |
51  *|          +------v-----+    +---v-------v-------------v----+          |
52  *|          | eSPI Flash |    |    eSPI protocol block       |          |
53  *|          |   access   +--->+                              |          |
54  *|          +------------+    +------------------------------+          |
55  *|                                    |                                 |
56  *|       -----------                  |                                 |
57  *|                                    v                                 |
58  *|               XXXXXXXXXXXXXXXXXXXXXXX                                |
59  *|                XXXXXXXXXXXXXXXXXXXXX                                 |
60  *|                 XXXXXXXXXXXXXXXXXXX                                  |
61  *+----------------------------------------------------------------------+
62  *                          |
63  *                 +-----------------+
64  *  ---------      |  |   |   |   |  |
65  *                 |  |   |   |   |  |
66  *  ---------      |  +   +   +   +  |    eSPI bus
67  *                 | CH0 CH1 CH2 CH3 |    (logical channels)
68  *                 |  +   +   +   +  |
69  *                 |  |   |   |   |  |
70  *                 +-----------------+
71  *                          |
72  *+-----------------------------------------------------------------------+
73  *|  eSPI slave                                                           |
74  *|                                                                       |
75  *|       CH0         |     CH1      |      CH2      |    CH3             |
76  *|   eSPI endpoint   |    VWIRE     |      OOB      |   Flash            |
77  *+-----------------------------------------------------------------------+
78  *   |                                 |
79  *   v                                 |
80  * +---------+                         |
81  * |  Flash  |  Slave Attached Flash   |
82  * +---------+                         |
83  *                                     |
84  * @endcode
85  */
86 
87 
88 /**
89  * @cond INTERNAL_HIDDEN
90  *
91  */
92 
93 
94 /** @endcond */
95 
96 struct espi_saf_hw_cfg;
97 struct espi_saf_flash_cfg;
98 struct espi_saf_pr;
99 
100 /**
101  * @brief eSPI SAF configuration parameters
102  */
103 struct espi_saf_cfg {
104 	uint8_t nflash_devices;
105 	struct espi_saf_hw_cfg hwcfg;
106 	struct espi_saf_flash_cfg *flash_cfgs;
107 };
108 
109 /**
110  * @brief eSPI SAF transaction packet format
111  */
112 struct espi_saf_packet {
113 	uint32_t flash_addr;
114 	uint8_t *buf;
115 	uint32_t len;
116 };
117 
118 /*
119  *defined in espi.h
120  * struct espi_callback
121  * typedef void (*espi_callback_handler_t)()
122  */
123 
124 /**
125  * @cond INTERNAL_HIDDEN
126  *
127  * eSPI driver API definition and system call entry points
128  *
129  * (Internal use only.)
130  */
131 typedef int (*espi_saf_api_config)(const struct device *dev,
132 				   const struct espi_saf_cfg *cfg);
133 
134 typedef int (*espi_saf_api_set_protection_regions)(
135 				const struct device *dev,
136 				const struct espi_saf_protection *pr);
137 
138 typedef int (*espi_saf_api_activate)(const struct device *dev);
139 
140 typedef bool (*espi_saf_api_get_channel_status)(const struct device *dev);
141 
142 typedef int (*espi_saf_api_flash_read)(const struct device *dev,
143 				       struct espi_saf_packet *pckt);
144 typedef int (*espi_saf_api_flash_write)(const struct device *dev,
145 					struct espi_saf_packet *pckt);
146 typedef int (*espi_saf_api_flash_erase)(const struct device *dev,
147 					struct espi_saf_packet *pckt);
148 /* Callbacks and traffic intercept */
149 typedef int (*espi_saf_api_manage_callback)(const struct device *dev,
150 					    struct espi_callback *callback,
151 					    bool set);
152 
153 __subsystem struct espi_saf_driver_api {
154 	espi_saf_api_config config;
155 	espi_saf_api_set_protection_regions set_protection_regions;
156 	espi_saf_api_activate activate;
157 	espi_saf_api_get_channel_status get_channel_status;
158 	espi_saf_api_flash_read flash_read;
159 	espi_saf_api_flash_write flash_write;
160 	espi_saf_api_flash_erase flash_erase;
161 	espi_saf_api_manage_callback manage_callback;
162 };
163 
164 /**
165  * @endcond
166  */
167 
168 /**
169  * @brief Configure operation of a eSPI controller.
170  *
171  * This routine provides a generic interface to override eSPI controller
172  * capabilities.
173  *
174  * If this eSPI controller is acting as slave, the values set here
175  * will be discovered as part through the GET_CONFIGURATION command
176  * issued by the eSPI master during initialization.
177  *
178  * If this eSPI controller is acting as master, the values set here
179  * will be used by eSPI master to determine minimum common capabilities with
180  * eSPI slave then send via SET_CONFIGURATION command.
181  *
182  * @code
183  * +--------+   +---------+     +------+          +---------+   +---------+
184  * |  eSPI  |   |  eSPI   |     | eSPI |          |  eSPI   |   |  eSPI   |
185  * |  slave |   | driver  |     |  bus |          |  driver |   |  host   |
186  * +--------+   +---------+     +------+          +---------+   +---------+
187  *     |              |            |                   |             |
188  *     | espi_config  | Set eSPI   |       Set eSPI    | espi_config |
189  *     +--------------+ ctrl regs  |       cap ctrl reg| +-----------+
190  *     |              +-------+    |          +--------+             |
191  *     |              |<------+    |          +------->|             |
192  *     |              |            |                   |             |
193  *     |              |            |                   |             |
194  *     |              |            | GET_CONFIGURATION |             |
195  *     |              |            +<------------------+             |
196  *     |              |<-----------|                   |             |
197  *     |              | eSPI caps  |                   |             |
198  *     |              |----------->+    response       |             |
199  *     |              |            |------------------>+             |
200  *     |              |            |                   |             |
201  *     |              |            | SET_CONFIGURATION |             |
202  *     |              |            +<------------------+             |
203  *     |              |            |  accept           |             |
204  *     |              |            +------------------>+             |
205  *     +              +            +                   +             +
206  * @endcode
207  *
208  * @param dev Pointer to the device structure for the driver instance.
209  * @param cfg the device runtime configuration for the eSPI controller.
210  *
211  * @retval 0 If successful.
212  * @retval -EIO General input / output error, failed to configure device.
213  * @retval -EINVAL invalid capabilities, failed to configure device.
214  * @retval -ENOTSUP capability not supported by eSPI slave.
215  */
216 __syscall int espi_saf_config(const struct device *dev,
217 			      const struct espi_saf_cfg *cfg);
218 
z_impl_espi_saf_config(const struct device * dev,const struct espi_saf_cfg * cfg)219 static inline int z_impl_espi_saf_config(const struct device *dev,
220 					 const struct espi_saf_cfg *cfg)
221 {
222 	const struct espi_saf_driver_api *api =
223 		(const struct espi_saf_driver_api *)dev->api;
224 
225 	return api->config(dev, cfg);
226 }
227 
228 /**
229  * @brief Set one or more SAF protection regions
230  *
231  * This routine provides an interface to override the default flash
232  * protection regions of the SAF controller.
233  *
234  * @param dev Pointer to the device structure for the driver instance.
235  * @param pr Pointer to the SAF protection region structure.
236  *
237  * @retval 0 If successful.
238  * @retval -EIO General input / output error, failed to configure device.
239  * @retval -EINVAL invalid capabilities, failed to configure device.
240  * @retval -ENOTSUP capability not supported by eSPI slave.
241  */
242 __syscall int espi_saf_set_protection_regions(
243 				const struct device *dev,
244 				const struct espi_saf_protection *pr);
245 
z_impl_espi_saf_set_protection_regions(const struct device * dev,const struct espi_saf_protection * pr)246 static inline int z_impl_espi_saf_set_protection_regions(
247 					const struct device *dev,
248 					const struct espi_saf_protection *pr)
249 {
250 	const struct espi_saf_driver_api *api =
251 		(const struct espi_saf_driver_api *)dev->api;
252 
253 	return api->set_protection_regions(dev, pr);
254 }
255 
256 /**
257  * @brief Activate SAF block
258  *
259  * This routine activates the SAF block and should only be
260  * called after SAF has been configured and the eSPI Master
261  * has enabled the Flash Channel.
262  *
263  * @param dev Pointer to the device structure for the driver instance.
264  *
265  * @retval 0 If successful
266  * @retval -EINVAL if failed to activate SAF.
267  */
268 __syscall int espi_saf_activate(const struct device *dev);
269 
z_impl_espi_saf_activate(const struct device * dev)270 static inline int z_impl_espi_saf_activate(const struct device *dev)
271 {
272 	const struct espi_saf_driver_api *api =
273 		(const struct espi_saf_driver_api *)dev->api;
274 
275 	return api->activate(dev);
276 }
277 
278 /**
279  * @brief Query to see if SAF is ready
280  *
281  * This routine allows to check if SAF is ready before use.
282  *
283  * @param dev Pointer to the device structure for the driver instance.
284  *
285  * @retval true If eSPI SAF is ready.
286  * @retval false otherwise.
287  */
288 __syscall bool espi_saf_get_channel_status(const struct device *dev);
289 
z_impl_espi_saf_get_channel_status(const struct device * dev)290 static inline bool z_impl_espi_saf_get_channel_status(
291 					const struct device *dev)
292 {
293 	const struct espi_saf_driver_api *api =
294 		(const struct espi_saf_driver_api *)dev->api;
295 
296 	return api->get_channel_status(dev);
297 }
298 
299 /**
300  * @brief Sends a read request packet for slave attached flash.
301  *
302  * This routines provides an interface to send a request to read the flash
303  * component shared between the eSPI master and eSPI slaves.
304  *
305  * @param dev Pointer to the device structure for the driver instance.
306  * @param pckt Address of the representation of read flash transaction.
307  *
308  * @retval -ENOTSUP eSPI flash logical channel transactions not supported.
309  * @retval -EBUSY eSPI flash channel is not ready or disabled by master.
310  * @retval -EIO General input / output error, failed request to master.
311  */
312 __syscall int espi_saf_flash_read(const struct device *dev,
313 				  struct espi_saf_packet *pckt);
314 
z_impl_espi_saf_flash_read(const struct device * dev,struct espi_saf_packet * pckt)315 static inline int z_impl_espi_saf_flash_read(const struct device *dev,
316 					     struct espi_saf_packet *pckt)
317 {
318 	const struct espi_saf_driver_api *api =
319 		(const struct espi_saf_driver_api *)dev->api;
320 
321 	if (!api->flash_read) {
322 		return -ENOTSUP;
323 	}
324 
325 	return api->flash_read(dev, pckt);
326 }
327 
328 /**
329  * @brief Sends a write request packet for slave attached flash.
330  *
331  * This routines provides an interface to send a request to write to the flash
332  * components shared between the eSPI master and eSPI slaves.
333  *
334  * @param dev Pointer to the device structure for the driver instance.
335  * @param pckt Address of the representation of write flash transaction.
336  *
337  * @retval -ENOTSUP eSPI flash logical channel transactions not supported.
338  * @retval -EBUSY eSPI flash channel is not ready or disabled by master.
339  * @retval -EIO General input / output error, failed request to master.
340  */
341 __syscall int espi_saf_flash_write(const struct device *dev,
342 				   struct espi_saf_packet *pckt);
343 
z_impl_espi_saf_flash_write(const struct device * dev,struct espi_saf_packet * pckt)344 static inline int z_impl_espi_saf_flash_write(const struct device *dev,
345 					      struct espi_saf_packet *pckt)
346 {
347 	const struct espi_saf_driver_api *api =
348 		(const struct espi_saf_driver_api *)dev->api;
349 
350 	if (!api->flash_write) {
351 		return -ENOTSUP;
352 	}
353 
354 	return api->flash_write(dev, pckt);
355 }
356 
357 /**
358  * @brief Sends a write request packet for slave attached flash.
359  *
360  * This routines provides an interface to send a request to write to the flash
361  * components shared between the eSPI master and eSPI slaves.
362  *
363  * @param dev Pointer to the device structure for the driver instance.
364  * @param pckt Address of the representation of erase flash transaction.
365  *
366  * @retval -ENOTSUP eSPI flash logical channel transactions not supported.
367  * @retval -EBUSY eSPI flash channel is not ready or disabled by master.
368  * @retval -EIO General input / output error, failed request to master.
369  */
370 __syscall int espi_saf_flash_erase(const struct device *dev,
371 				   struct espi_saf_packet *pckt);
372 
z_impl_espi_saf_flash_erase(const struct device * dev,struct espi_saf_packet * pckt)373 static inline int z_impl_espi_saf_flash_erase(const struct device *dev,
374 					      struct espi_saf_packet *pckt)
375 {
376 	const struct espi_saf_driver_api *api =
377 		(const struct espi_saf_driver_api *)dev->api;
378 
379 	if (!api->flash_erase) {
380 		return -ENOTSUP;
381 	}
382 
383 	return api->flash_erase(dev, pckt);
384 }
385 
386 /**
387  * Callback model
388  *
389  * @code
390  *+-------+                  +-------------+   +------+     +---------+
391  *|  App  |                  | eSPI driver |   |  HW  |     |eSPI Host|
392  *+---+---+                  +-------+-----+   +---+--+     +----+----+
393  *    |                              |             |             |
394  *    |   espi_init_callback         |             |             |
395  *    +----------------------------> |             |             |
396  *    |   espi_add_callback          |             |
397  *    +----------------------------->+             |
398  *    |                              |             |  eSPI reset |  eSPI host
399  *    |                              |    IRQ      +<------------+  resets the
400  *    |                              | <-----------+             |  bus
401  *    |                              |             |             |
402  *    |                              | Processed   |             |
403  *    |                              | within the  |             |
404  *    |                              | driver      |             |
405  *    |                              |             |             |
406 
407  *    |                              |             |  VW CH ready|  eSPI host
408  *    |                              |    IRQ      +<------------+  enables VW
409  *    |                              | <-----------+             |  channel
410  *    |                              |             |             |
411  *    |                              | Processed   |             |
412  *    |                              | within the  |             |
413  *    |                              | driver      |             |
414  *    |                              |             |             |
415  *    |                              |             | Memory I/O  |  Peripheral
416  *    |                              |             <-------------+  event
417  *    |                              +<------------+             |
418  *    +<-----------------------------+ callback    |             |
419  *    | Report peripheral event      |             |             |
420  *    | and data for the event       |             |             |
421  *    |                              |             |             |
422  *    |                              |             | SLP_S5      |  eSPI host
423  *    |                              |             <-------------+  send VWire
424  *    |                              +<------------+             |
425  *    +<-----------------------------+ callback    |             |
426  *    | App enables/configures       |             |             |
427  *    | discrete regulator           |             |             |
428  *    |                              |             |             |
429  *    |   espi_send_vwire_signal     |             |             |
430  *    +------------------------------>------------>|------------>|
431  *    |                              |             |             |
432  *    |                              |             | HOST_RST    |  eSPI host
433  *    |                              |             <-------------+  send VWire
434  *    |                              +<------------+             |
435  *    +<-----------------------------+ callback    |             |
436  *    | App reset host-related       |             |             |
437  *    | data structures              |             |             |
438  *    |                              |             |             |
439  *    |                              |             |   C10       |  eSPI host
440  *    |                              |             +<------------+  send VWire
441  *    |                              <-------------+             |
442  *    <------------------------------+             |             |
443  *    | App executes                 |             |             |
444  *    + power mgmt policy            |             |             |
445  * @endcode
446  */
447 
448 /**
449  * @brief Helper to initialize a struct espi_callback properly.
450  *
451  * @param callback A valid Application's callback structure pointer.
452  * @param handler A valid handler function pointer.
453  * @param evt_type indicates the eSPI event relevant for the handler.
454  * for VWIRE_RECEIVED event the data will indicate the new level asserted
455  */
espi_saf_init_callback(struct espi_callback * callback,espi_callback_handler_t handler,enum espi_bus_event evt_type)456 static inline void espi_saf_init_callback(struct espi_callback *callback,
457 					  espi_callback_handler_t handler,
458 					  enum espi_bus_event evt_type)
459 {
460 	__ASSERT(callback, "Callback pointer should not be NULL");
461 	__ASSERT(handler, "Callback handler pointer should not be NULL");
462 
463 	callback->handler = handler;
464 	callback->evt_type = evt_type;
465 }
466 
467 /**
468  * @brief Add an application callback.
469  * @param dev Pointer to the device structure for the driver instance.
470  * @param callback A valid Application's callback structure pointer.
471  * @return 0 if successful, negative errno code on failure.
472  *
473  * @note Callbacks may be added to the device from within a callback
474  * handler invocation, but whether they are invoked for the current
475  * eSPI event is not specified.
476  *
477  * Note: enables to add as many callback as needed on the same device.
478  */
espi_saf_add_callback(const struct device * dev,struct espi_callback * callback)479 static inline int espi_saf_add_callback(const struct device *dev,
480 					struct espi_callback *callback)
481 {
482 	const struct espi_saf_driver_api *api =
483 		(const struct espi_saf_driver_api *)dev->api;
484 
485 	if (!api->manage_callback) {
486 		return -ENOTSUP;
487 	}
488 
489 	return api->manage_callback(dev, callback, true);
490 }
491 
492 /**
493  * @brief Remove an application callback.
494  * @param dev Pointer to the device structure for the driver instance.
495  * @param callback A valid application's callback structure pointer.
496  * @return 0 if successful, negative errno code on failure.
497  *
498  * @warning It is explicitly permitted, within a callback handler, to
499  * remove the registration for the callback that is running, i.e. @p
500  * callback.  Attempts to remove other registrations on the same
501  * device may result in undefined behavior, including failure to
502  * invoke callbacks that remain registered and unintended invocation
503  * of removed callbacks.
504  *
505  * Note: enables to remove as many callbacks as added through
506  *       espi_add_callback().
507  */
espi_saf_remove_callback(const struct device * dev,struct espi_callback * callback)508 static inline int espi_saf_remove_callback(const struct device *dev,
509 					   struct espi_callback *callback)
510 {
511 	const struct espi_saf_driver_api *api =
512 		(const struct espi_saf_driver_api *)dev->api;
513 
514 	if (!api->manage_callback) {
515 		return -ENOTSUP;
516 	}
517 
518 	return api->manage_callback(dev, callback, false);
519 }
520 
521 #ifdef __cplusplus
522 }
523 #endif
524 
525 /**
526  * @}
527  */
528 #include <syscalls/espi_saf.h>
529 #endif /* ZEPHYR_INCLUDE_ESPI_SAF_H_ */
530