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 typedef int (*espi_saf_api_flash_unsuccess)(const struct device *dev,
149 struct espi_saf_packet *pckt);
150 /* Callbacks and traffic intercept */
151 typedef int (*espi_saf_api_manage_callback)(const struct device *dev,
152 struct espi_callback *callback,
153 bool set);
154
155 __subsystem struct espi_saf_driver_api {
156 espi_saf_api_config config;
157 espi_saf_api_set_protection_regions set_protection_regions;
158 espi_saf_api_activate activate;
159 espi_saf_api_get_channel_status get_channel_status;
160 espi_saf_api_flash_read flash_read;
161 espi_saf_api_flash_write flash_write;
162 espi_saf_api_flash_erase flash_erase;
163 espi_saf_api_flash_unsuccess flash_unsuccess;
164 espi_saf_api_manage_callback manage_callback;
165 };
166
167 /**
168 * @endcond
169 */
170
171 /**
172 * @brief Configure operation of a eSPI controller.
173 *
174 * This routine provides a generic interface to override eSPI controller
175 * capabilities.
176 *
177 * If this eSPI controller is acting as slave, the values set here
178 * will be discovered as part through the GET_CONFIGURATION command
179 * issued by the eSPI master during initialization.
180 *
181 * If this eSPI controller is acting as master, the values set here
182 * will be used by eSPI master to determine minimum common capabilities with
183 * eSPI slave then send via SET_CONFIGURATION command.
184 *
185 * @code
186 * +--------+ +---------+ +------+ +---------+ +---------+
187 * | eSPI | | eSPI | | eSPI | | eSPI | | eSPI |
188 * | slave | | driver | | bus | | driver | | host |
189 * +--------+ +---------+ +------+ +---------+ +---------+
190 * | | | | |
191 * | espi_config | Set eSPI | Set eSPI | espi_config |
192 * +--------------+ ctrl regs | cap ctrl reg| +-----------+
193 * | +-------+ | +--------+ |
194 * | |<------+ | +------->| |
195 * | | | | |
196 * | | | | |
197 * | | | GET_CONFIGURATION | |
198 * | | +<------------------+ |
199 * | |<-----------| | |
200 * | | eSPI caps | | |
201 * | |----------->+ response | |
202 * | | |------------------>+ |
203 * | | | | |
204 * | | | SET_CONFIGURATION | |
205 * | | +<------------------+ |
206 * | | | accept | |
207 * | | +------------------>+ |
208 * + + + + +
209 * @endcode
210 *
211 * @param dev Pointer to the device structure for the driver instance.
212 * @param cfg the device runtime configuration for the eSPI controller.
213 *
214 * @retval 0 If successful.
215 * @retval -EIO General input / output error, failed to configure device.
216 * @retval -EINVAL invalid capabilities, failed to configure device.
217 * @retval -ENOTSUP capability not supported by eSPI slave.
218 */
219 __syscall int espi_saf_config(const struct device *dev,
220 const struct espi_saf_cfg *cfg);
221
z_impl_espi_saf_config(const struct device * dev,const struct espi_saf_cfg * cfg)222 static inline int z_impl_espi_saf_config(const struct device *dev,
223 const struct espi_saf_cfg *cfg)
224 {
225 const struct espi_saf_driver_api *api =
226 (const struct espi_saf_driver_api *)dev->api;
227
228 return api->config(dev, cfg);
229 }
230
231 /**
232 * @brief Set one or more SAF protection regions
233 *
234 * This routine provides an interface to override the default flash
235 * protection regions of the SAF controller.
236 *
237 * @param dev Pointer to the device structure for the driver instance.
238 * @param pr Pointer to the SAF protection region structure.
239 *
240 * @retval 0 If successful.
241 * @retval -EIO General input / output error, failed to configure device.
242 * @retval -EINVAL invalid capabilities, failed to configure device.
243 * @retval -ENOTSUP capability not supported by eSPI slave.
244 */
245 __syscall int espi_saf_set_protection_regions(
246 const struct device *dev,
247 const struct espi_saf_protection *pr);
248
z_impl_espi_saf_set_protection_regions(const struct device * dev,const struct espi_saf_protection * pr)249 static inline int z_impl_espi_saf_set_protection_regions(
250 const struct device *dev,
251 const struct espi_saf_protection *pr)
252 {
253 const struct espi_saf_driver_api *api =
254 (const struct espi_saf_driver_api *)dev->api;
255
256 return api->set_protection_regions(dev, pr);
257 }
258
259 /**
260 * @brief Activate SAF block
261 *
262 * This routine activates the SAF block and should only be
263 * called after SAF has been configured and the eSPI Master
264 * has enabled the Flash Channel.
265 *
266 * @param dev Pointer to the device structure for the driver instance.
267 *
268 * @retval 0 If successful
269 * @retval -EINVAL if failed to activate SAF.
270 */
271 __syscall int espi_saf_activate(const struct device *dev);
272
z_impl_espi_saf_activate(const struct device * dev)273 static inline int z_impl_espi_saf_activate(const struct device *dev)
274 {
275 const struct espi_saf_driver_api *api =
276 (const struct espi_saf_driver_api *)dev->api;
277
278 return api->activate(dev);
279 }
280
281 /**
282 * @brief Query to see if SAF is ready
283 *
284 * This routine allows to check if SAF is ready before use.
285 *
286 * @param dev Pointer to the device structure for the driver instance.
287 *
288 * @retval true If eSPI SAF is ready.
289 * @retval false otherwise.
290 */
291 __syscall bool espi_saf_get_channel_status(const struct device *dev);
292
z_impl_espi_saf_get_channel_status(const struct device * dev)293 static inline bool z_impl_espi_saf_get_channel_status(
294 const struct device *dev)
295 {
296 const struct espi_saf_driver_api *api =
297 (const struct espi_saf_driver_api *)dev->api;
298
299 return api->get_channel_status(dev);
300 }
301
302 /**
303 * @brief Sends a read request packet for slave attached flash.
304 *
305 * This routines provides an interface to send a request to read the flash
306 * component shared between the eSPI master and eSPI slaves.
307 *
308 * @param dev Pointer to the device structure for the driver instance.
309 * @param pckt Address of the representation of read flash transaction.
310 *
311 * @retval -ENOTSUP eSPI flash logical channel transactions not supported.
312 * @retval -EBUSY eSPI flash channel is not ready or disabled by master.
313 * @retval -EIO General input / output error, failed request to master.
314 */
315 __syscall int espi_saf_flash_read(const struct device *dev,
316 struct espi_saf_packet *pckt);
317
z_impl_espi_saf_flash_read(const struct device * dev,struct espi_saf_packet * pckt)318 static inline int z_impl_espi_saf_flash_read(const struct device *dev,
319 struct espi_saf_packet *pckt)
320 {
321 const struct espi_saf_driver_api *api =
322 (const struct espi_saf_driver_api *)dev->api;
323
324 if (!api->flash_read) {
325 return -ENOTSUP;
326 }
327
328 return api->flash_read(dev, pckt);
329 }
330
331 /**
332 * @brief Sends a write request packet for slave attached flash.
333 *
334 * This routines provides an interface to send a request to write to the flash
335 * components shared between the eSPI master and eSPI slaves.
336 *
337 * @param dev Pointer to the device structure for the driver instance.
338 * @param pckt Address of the representation of write flash transaction.
339 *
340 * @retval -ENOTSUP eSPI flash logical channel transactions not supported.
341 * @retval -EBUSY eSPI flash channel is not ready or disabled by master.
342 * @retval -EIO General input / output error, failed request to master.
343 */
344 __syscall int espi_saf_flash_write(const struct device *dev,
345 struct espi_saf_packet *pckt);
346
z_impl_espi_saf_flash_write(const struct device * dev,struct espi_saf_packet * pckt)347 static inline int z_impl_espi_saf_flash_write(const struct device *dev,
348 struct espi_saf_packet *pckt)
349 {
350 const struct espi_saf_driver_api *api =
351 (const struct espi_saf_driver_api *)dev->api;
352
353 if (!api->flash_write) {
354 return -ENOTSUP;
355 }
356
357 return api->flash_write(dev, pckt);
358 }
359
360 /**
361 * @brief Sends a write request packet for slave attached flash.
362 *
363 * This routines provides an interface to send a request to write to the flash
364 * components shared between the eSPI master and eSPI slaves.
365 *
366 * @param dev Pointer to the device structure for the driver instance.
367 * @param pckt Address of the representation of erase flash transaction.
368 *
369 * @retval -ENOTSUP eSPI flash logical channel transactions not supported.
370 * @retval -EBUSY eSPI flash channel is not ready or disabled by master.
371 * @retval -EIO General input / output error, failed request to master.
372 */
373 __syscall int espi_saf_flash_erase(const struct device *dev,
374 struct espi_saf_packet *pckt);
375
z_impl_espi_saf_flash_erase(const struct device * dev,struct espi_saf_packet * pckt)376 static inline int z_impl_espi_saf_flash_erase(const struct device *dev,
377 struct espi_saf_packet *pckt)
378 {
379 const struct espi_saf_driver_api *api =
380 (const struct espi_saf_driver_api *)dev->api;
381
382 if (!api->flash_erase) {
383 return -ENOTSUP;
384 }
385
386 return api->flash_erase(dev, pckt);
387 }
388
389 /**
390 * @brief Response unsuccessful completion for slave attached flash.
391 *
392 * This routines provides an interface to response that transaction is
393 * invalid and return unsuccessful completion from target to controller.
394 *
395 * @param dev Pointer to the device structure for the driver instance.
396 * @param pckt Address of the representation of flash transaction.
397 *
398 * @retval -ENOTSUP eSPI flash logical channel transactions not supported.
399 * @retval -EBUSY eSPI flash channel is not ready or disabled by master.
400 * @retval -EIO General input / output error, failed request to master.
401 */
402 __syscall int espi_saf_flash_unsuccess(const struct device *dev,
403 struct espi_saf_packet *pckt);
404
z_impl_espi_saf_flash_unsuccess(const struct device * dev,struct espi_saf_packet * pckt)405 static inline int z_impl_espi_saf_flash_unsuccess(const struct device *dev,
406 struct espi_saf_packet *pckt)
407 {
408 const struct espi_saf_driver_api *api =
409 (const struct espi_saf_driver_api *)dev->api;
410
411 if (!api->flash_unsuccess) {
412 return -ENOTSUP;
413 }
414
415 return api->flash_unsuccess(dev, pckt);
416 }
417
418 /**
419 * Callback model
420 *
421 * @code
422 *+-------+ +-------------+ +------+ +---------+
423 *| App | | eSPI driver | | HW | |eSPI Host|
424 *+---+---+ +-------+-----+ +---+--+ +----+----+
425 * | | | |
426 * | espi_init_callback | | |
427 * +----------------------------> | | |
428 * | espi_add_callback | |
429 * +----------------------------->+ |
430 * | | | eSPI reset | eSPI host
431 * | | IRQ +<------------+ resets the
432 * | | <-----------+ | bus
433 * | | | |
434 * | | Processed | |
435 * | | within the | |
436 * | | driver | |
437 * | | | |
438
439 * | | | VW CH ready| eSPI host
440 * | | IRQ +<------------+ enables VW
441 * | | <-----------+ | channel
442 * | | | |
443 * | | Processed | |
444 * | | within the | |
445 * | | driver | |
446 * | | | |
447 * | | | Memory I/O | Peripheral
448 * | | <-------------+ event
449 * | +<------------+ |
450 * +<-----------------------------+ callback | |
451 * | Report peripheral event | | |
452 * | and data for the event | | |
453 * | | | |
454 * | | | SLP_S5 | eSPI host
455 * | | <-------------+ send VWire
456 * | +<------------+ |
457 * +<-----------------------------+ callback | |
458 * | App enables/configures | | |
459 * | discrete regulator | | |
460 * | | | |
461 * | espi_send_vwire_signal | | |
462 * +------------------------------>------------>|------------>|
463 * | | | |
464 * | | | HOST_RST | eSPI host
465 * | | <-------------+ send VWire
466 * | +<------------+ |
467 * +<-----------------------------+ callback | |
468 * | App reset host-related | | |
469 * | data structures | | |
470 * | | | |
471 * | | | C10 | eSPI host
472 * | | +<------------+ send VWire
473 * | <-------------+ |
474 * <------------------------------+ | |
475 * | App executes | | |
476 * + power mgmt policy | | |
477 * @endcode
478 */
479
480 /**
481 * @brief Helper to initialize a struct espi_callback properly.
482 *
483 * @param callback A valid Application's callback structure pointer.
484 * @param handler A valid handler function pointer.
485 * @param evt_type indicates the eSPI event relevant for the handler.
486 * for VWIRE_RECEIVED event the data will indicate the new level asserted
487 */
espi_saf_init_callback(struct espi_callback * callback,espi_callback_handler_t handler,enum espi_bus_event evt_type)488 static inline void espi_saf_init_callback(struct espi_callback *callback,
489 espi_callback_handler_t handler,
490 enum espi_bus_event evt_type)
491 {
492 __ASSERT(callback, "Callback pointer should not be NULL");
493 __ASSERT(handler, "Callback handler pointer should not be NULL");
494
495 callback->handler = handler;
496 callback->evt_type = evt_type;
497 }
498
499 /**
500 * @brief Add an application callback.
501 * @param dev Pointer to the device structure for the driver instance.
502 * @param callback A valid Application's callback structure pointer.
503 * @return 0 if successful, negative errno code on failure.
504 *
505 * @note Callbacks may be added to the device from within a callback
506 * handler invocation, but whether they are invoked for the current
507 * eSPI event is not specified.
508 *
509 * Note: enables to add as many callback as needed on the same device.
510 */
espi_saf_add_callback(const struct device * dev,struct espi_callback * callback)511 static inline int espi_saf_add_callback(const struct device *dev,
512 struct espi_callback *callback)
513 {
514 const struct espi_saf_driver_api *api =
515 (const struct espi_saf_driver_api *)dev->api;
516
517 if (!api->manage_callback) {
518 return -ENOTSUP;
519 }
520
521 return api->manage_callback(dev, callback, true);
522 }
523
524 /**
525 * @brief Remove an application callback.
526 * @param dev Pointer to the device structure for the driver instance.
527 * @param callback A valid application's callback structure pointer.
528 * @return 0 if successful, negative errno code on failure.
529 *
530 * @warning It is explicitly permitted, within a callback handler, to
531 * remove the registration for the callback that is running, i.e. @p
532 * callback. Attempts to remove other registrations on the same
533 * device may result in undefined behavior, including failure to
534 * invoke callbacks that remain registered and unintended invocation
535 * of removed callbacks.
536 *
537 * Note: enables to remove as many callbacks as added through
538 * espi_add_callback().
539 */
espi_saf_remove_callback(const struct device * dev,struct espi_callback * callback)540 static inline int espi_saf_remove_callback(const struct device *dev,
541 struct espi_callback *callback)
542 {
543 const struct espi_saf_driver_api *api =
544 (const struct espi_saf_driver_api *)dev->api;
545
546 if (!api->manage_callback) {
547 return -ENOTSUP;
548 }
549
550 return api->manage_callback(dev, callback, false);
551 }
552
553 #ifdef __cplusplus
554 }
555 #endif
556
557 /**
558 * @}
559 */
560 #include <syscalls/espi_saf.h>
561 #endif /* ZEPHYR_INCLUDE_ESPI_SAF_H_ */
562