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