19fff0425STomas Winkler /* SPDX-License-Identifier: GPL-2.0 */
2ffc2825cSGreg Kroah-Hartman /*
395953618SAlexander Usyskin * Copyright (c) 2003-2022, Intel Corporation. All rights reserved.
4ffc2825cSGreg Kroah-Hartman * Intel Management Engine Interface (Intel MEI) Linux driver
5ffc2825cSGreg Kroah-Hartman */
6ffc2825cSGreg Kroah-Hartman
7ffc2825cSGreg Kroah-Hartman #ifndef _MEI_DEV_H_
8ffc2825cSGreg Kroah-Hartman #define _MEI_DEV_H_
9ffc2825cSGreg Kroah-Hartman
10ffc2825cSGreg Kroah-Hartman #include <linux/types.h>
11fdd9b865SAlexander Usyskin #include <linux/cdev.h>
12744f0f2fSTomas Winkler #include <linux/poll.h>
134f3afe1dSTomas Winkler #include <linux/mei.h>
14e5354107SSamuel Ortiz #include <linux/mei_cl_bus.h>
1566ef5ea9STomas Winkler
uuid_le_cmp(const uuid_le u1,const uuid_le u2)16f5b3c341SAndy Shevchenko static inline int uuid_le_cmp(const uuid_le u1, const uuid_le u2)
17f5b3c341SAndy Shevchenko {
18f5b3c341SAndy Shevchenko return memcmp(&u1, &u2, sizeof(uuid_le));
19f5b3c341SAndy Shevchenko }
20f5b3c341SAndy Shevchenko
21ffc2825cSGreg Kroah-Hartman #include "hw.h"
229b0d5efcSTomas Winkler #include "hbm.h"
23ffc2825cSGreg Kroah-Hartman
249fc5f0f8STomas Winkler #define MEI_SLOT_SIZE sizeof(u32)
259fc5f0f8STomas Winkler #define MEI_RD_MSG_BUF_SIZE (128 * MEI_SLOT_SIZE)
269fc5f0f8STomas Winkler
27ffc2825cSGreg Kroah-Hartman /*
281e2776c3STomas Winkler * Number of Maximum MEI Clients
291e2776c3STomas Winkler */
301e2776c3STomas Winkler #define MEI_CLIENTS_MAX 256
311e2776c3STomas Winkler
321e2776c3STomas Winkler /*
336adb8efbSTomas Winkler * maximum number of consecutive resets
346adb8efbSTomas Winkler */
356adb8efbSTomas Winkler #define MEI_MAX_CONSEC_RESET 3
366adb8efbSTomas Winkler
376adb8efbSTomas Winkler /*
38ffc2825cSGreg Kroah-Hartman * Number of File descriptors/handles
39ffc2825cSGreg Kroah-Hartman * that can be opened to the driver.
40ffc2825cSGreg Kroah-Hartman *
41781d0d89STomas Winkler * Limit to 255: 256 Total Clients
4283ce0741SAlexander Usyskin * minus internal client for MEI Bus Messages
43ffc2825cSGreg Kroah-Hartman */
44781d0d89STomas Winkler #define MEI_MAX_OPEN_HANDLE_COUNT (MEI_CLIENTS_MAX - 1)
45ffc2825cSGreg Kroah-Hartman
46ffc2825cSGreg Kroah-Hartman /* File state */
47ffc2825cSGreg Kroah-Hartman enum file_state {
48bd47b526SAlexander Usyskin MEI_FILE_UNINITIALIZED = 0,
49bd47b526SAlexander Usyskin MEI_FILE_INITIALIZING,
50ffc2825cSGreg Kroah-Hartman MEI_FILE_CONNECTING,
51ffc2825cSGreg Kroah-Hartman MEI_FILE_CONNECTED,
52ffc2825cSGreg Kroah-Hartman MEI_FILE_DISCONNECTING,
533c666182STomas Winkler MEI_FILE_DISCONNECT_REPLY,
5418901357SAlexander Usyskin MEI_FILE_DISCONNECT_REQUIRED,
553c666182STomas Winkler MEI_FILE_DISCONNECTED,
56ffc2825cSGreg Kroah-Hartman };
57ffc2825cSGreg Kroah-Hartman
58ffc2825cSGreg Kroah-Hartman /* MEI device states */
59b210d750STomas Winkler enum mei_dev_state {
60b210d750STomas Winkler MEI_DEV_INITIALIZING = 0,
61b210d750STomas Winkler MEI_DEV_INIT_CLIENTS,
62b210d750STomas Winkler MEI_DEV_ENABLED,
630cfee51cSBill Nottingham MEI_DEV_RESETTING,
64b210d750STomas Winkler MEI_DEV_DISABLED,
6536edb140SAlexander Usyskin MEI_DEV_POWERING_DOWN,
66b210d750STomas Winkler MEI_DEV_POWER_DOWN,
67b210d750STomas Winkler MEI_DEV_POWER_UP
68ffc2825cSGreg Kroah-Hartman };
69ffc2825cSGreg Kroah-Hartman
70342e4c7eSTomas Winkler /**
71342e4c7eSTomas Winkler * enum mei_dev_pxp_mode - MEI PXP mode state
72342e4c7eSTomas Winkler *
73342e4c7eSTomas Winkler * @MEI_DEV_PXP_DEFAULT: PCH based device, no initailization required
74342e4c7eSTomas Winkler * @MEI_DEV_PXP_INIT: device requires initialization, send setup message to firmware
75342e4c7eSTomas Winkler * @MEI_DEV_PXP_SETUP: device is in setup stage, waiting for firmware repsonse
76342e4c7eSTomas Winkler * @MEI_DEV_PXP_READY: device initialized
77342e4c7eSTomas Winkler */
78342e4c7eSTomas Winkler enum mei_dev_pxp_mode {
79342e4c7eSTomas Winkler MEI_DEV_PXP_DEFAULT = 0,
80342e4c7eSTomas Winkler MEI_DEV_PXP_INIT = 1,
81342e4c7eSTomas Winkler MEI_DEV_PXP_SETUP = 2,
82342e4c7eSTomas Winkler MEI_DEV_PXP_READY = 3,
83342e4c7eSTomas Winkler };
84342e4c7eSTomas Winkler
85b210d750STomas Winkler const char *mei_dev_state_str(int state);
86b210d750STomas Winkler
87ffc2825cSGreg Kroah-Hartman enum mei_file_transaction_states {
88ffc2825cSGreg Kroah-Hartman MEI_IDLE,
89ffc2825cSGreg Kroah-Hartman MEI_WRITING,
90ffc2825cSGreg Kroah-Hartman MEI_WRITE_COMPLETE,
91ffc2825cSGreg Kroah-Hartman };
92ffc2825cSGreg Kroah-Hartman
934b8960b4STomas Winkler /**
944b8960b4STomas Winkler * enum mei_cb_file_ops - file operation associated with the callback
95ce23139cSAlexander Usyskin * @MEI_FOP_READ: read
96ce23139cSAlexander Usyskin * @MEI_FOP_WRITE: write
97ce23139cSAlexander Usyskin * @MEI_FOP_CONNECT: connect
98ce23139cSAlexander Usyskin * @MEI_FOP_DISCONNECT: disconnect
99ce23139cSAlexander Usyskin * @MEI_FOP_DISCONNECT_RSP: disconnect response
100965ae37aSTomas Winkler * @MEI_FOP_NOTIFY_START: start notification
101965ae37aSTomas Winkler * @MEI_FOP_NOTIFY_STOP: stop notification
102369aea84SAlexander Usyskin * @MEI_FOP_DMA_MAP: request client dma map
103369aea84SAlexander Usyskin * @MEI_FOP_DMA_UNMAP: request client dma unmap
1044b8960b4STomas Winkler */
1054b8960b4STomas Winkler enum mei_cb_file_ops {
1064b8960b4STomas Winkler MEI_FOP_READ = 0,
1074b8960b4STomas Winkler MEI_FOP_WRITE,
10802a7eeccSTomas Winkler MEI_FOP_CONNECT,
1095a8373fbSTomas Winkler MEI_FOP_DISCONNECT,
1106bb948c9STomas Winkler MEI_FOP_DISCONNECT_RSP,
111965ae37aSTomas Winkler MEI_FOP_NOTIFY_START,
112965ae37aSTomas Winkler MEI_FOP_NOTIFY_STOP,
113369aea84SAlexander Usyskin MEI_FOP_DMA_MAP,
114369aea84SAlexander Usyskin MEI_FOP_DMA_UNMAP,
115ffc2825cSGreg Kroah-Hartman };
116ffc2825cSGreg Kroah-Hartman
117e0cb6b2fSAlexander Usyskin /**
118e0cb6b2fSAlexander Usyskin * enum mei_cl_io_mode - io mode between driver and fw
119e0cb6b2fSAlexander Usyskin *
120e0cb6b2fSAlexander Usyskin * @MEI_CL_IO_TX_BLOCKING: send is blocking
121e0cb6b2fSAlexander Usyskin * @MEI_CL_IO_TX_INTERNAL: internal communication between driver and FW
122076802d0SAlexander Usyskin *
123076802d0SAlexander Usyskin * @MEI_CL_IO_RX_NONBLOCK: recv is non-blocking
1245d5bc189STomas Winkler *
1255d5bc189STomas Winkler * @MEI_CL_IO_SGL: send command with sgl list.
126e0cb6b2fSAlexander Usyskin */
127e0cb6b2fSAlexander Usyskin enum mei_cl_io_mode {
128e0cb6b2fSAlexander Usyskin MEI_CL_IO_TX_BLOCKING = BIT(0),
129e0cb6b2fSAlexander Usyskin MEI_CL_IO_TX_INTERNAL = BIT(1),
130076802d0SAlexander Usyskin
131076802d0SAlexander Usyskin MEI_CL_IO_RX_NONBLOCK = BIT(2),
1325d5bc189STomas Winkler
1335d5bc189STomas Winkler MEI_CL_IO_SGL = BIT(3),
134e0cb6b2fSAlexander Usyskin };
135e0cb6b2fSAlexander Usyskin
136ffc2825cSGreg Kroah-Hartman /*
137ffc2825cSGreg Kroah-Hartman * Intel MEI message data struct
138ffc2825cSGreg Kroah-Hartman */
1394234a6deSTomas Winkler struct mei_msg_data {
140f862b6b2STomas Winkler size_t size;
141ffc2825cSGreg Kroah-Hartman unsigned char *data;
142f060939dSTomas Winkler };
143ffc2825cSGreg Kroah-Hartman
144369aea84SAlexander Usyskin struct mei_dma_data {
145369aea84SAlexander Usyskin u8 buffer_id;
146369aea84SAlexander Usyskin void *vaddr;
147369aea84SAlexander Usyskin dma_addr_t daddr;
148369aea84SAlexander Usyskin size_t size;
149369aea84SAlexander Usyskin };
150369aea84SAlexander Usyskin
151ce0925e8STomas Winkler /**
152ce0925e8STomas Winkler * struct mei_dma_dscr - dma address descriptor
153ce0925e8STomas Winkler *
154ce0925e8STomas Winkler * @vaddr: dma buffer virtual address
155ce0925e8STomas Winkler * @daddr: dma buffer physical address
156ce0925e8STomas Winkler * @size : dma buffer size
157ce0925e8STomas Winkler */
158ce0925e8STomas Winkler struct mei_dma_dscr {
159ce0925e8STomas Winkler void *vaddr;
160ce0925e8STomas Winkler dma_addr_t daddr;
161ce0925e8STomas Winkler size_t size;
162ce0925e8STomas Winkler };
163ce0925e8STomas Winkler
16404dd3661SAlexander Usyskin /* Maximum number of processed FW status registers */
165edca5ea3SAlexander Usyskin #define MEI_FW_STATUS_MAX 6
166edca5ea3SAlexander Usyskin /* Minimal buffer for FW status string (8 bytes in dw + space or '\0') */
167edca5ea3SAlexander Usyskin #define MEI_FW_STATUS_STR_SZ (MEI_FW_STATUS_MAX * (8 + 1))
168edca5ea3SAlexander Usyskin
16904dd3661SAlexander Usyskin
17004dd3661SAlexander Usyskin /*
17104dd3661SAlexander Usyskin * struct mei_fw_status - storage of FW status data
17204dd3661SAlexander Usyskin *
173a8605ea2SAlexander Usyskin * @count: number of actually available elements in array
174a8605ea2SAlexander Usyskin * @status: FW status registers
17504dd3661SAlexander Usyskin */
17604dd3661SAlexander Usyskin struct mei_fw_status {
17704dd3661SAlexander Usyskin int count;
17804dd3661SAlexander Usyskin u32 status[MEI_FW_STATUS_MAX];
17904dd3661SAlexander Usyskin };
18004dd3661SAlexander Usyskin
181db7da79dSTomas Winkler /**
182db7da79dSTomas Winkler * struct mei_me_client - representation of me (fw) client
183db7da79dSTomas Winkler *
184a8605ea2SAlexander Usyskin * @list: link in me client list
18579563db9STomas Winkler * @refcnt: struct reference count
186a8605ea2SAlexander Usyskin * @props: client properties
187a8605ea2SAlexander Usyskin * @client_id: me client id
1884034b81bSTomas Winkler * @tx_flow_ctrl_creds: flow control credits
189a03d77f6SAlexander Usyskin * @connect_count: number connections to this client
1900ff0a8d8STomas Winkler * @bus_added: added to bus
191db7da79dSTomas Winkler */
192db7da79dSTomas Winkler struct mei_me_client {
1935ca2d388STomas Winkler struct list_head list;
19479563db9STomas Winkler struct kref refcnt;
195db7da79dSTomas Winkler struct mei_client_properties props;
196db7da79dSTomas Winkler u8 client_id;
1974034b81bSTomas Winkler u8 tx_flow_ctrl_creds;
198a03d77f6SAlexander Usyskin u8 connect_count;
1990ff0a8d8STomas Winkler u8 bus_added;
200db7da79dSTomas Winkler };
201db7da79dSTomas Winkler
202ffc2825cSGreg Kroah-Hartman
203db3ed431STomas Winkler struct mei_cl;
204db3ed431STomas Winkler
2054b8960b4STomas Winkler /**
206db3ed431STomas Winkler * struct mei_cl_cb - file operation callback structure
207db3ed431STomas Winkler *
208a8605ea2SAlexander Usyskin * @list: link in callback queue
209a8605ea2SAlexander Usyskin * @cl: file client who is running this operation
210a8605ea2SAlexander Usyskin * @fop_type: file operation type
2115db7514dSTomas Winkler * @buf: buffer for data associated with the callback
212ce23139cSAlexander Usyskin * @buf_idx: last read index
2130cd7c01aSTomas Winkler * @vtag: virtual tag
21462e8e6adSTomas Winkler * @fp: pointer to file structure
2153d33ff24STomas Winkler * @status: io status of the cb
216ce23139cSAlexander Usyskin * @internal: communication between driver and FW flag
217e0cb6b2fSAlexander Usyskin * @blocking: transmission blocking mode
2184ed1cc99STomas Winkler * @ext_hdr: extended header
219db3ed431STomas Winkler */
220ffc2825cSGreg Kroah-Hartman struct mei_cl_cb {
221fb601adbSTomas Winkler struct list_head list;
222db3ed431STomas Winkler struct mei_cl *cl;
2234b8960b4STomas Winkler enum mei_cb_file_ops fop_type;
2245db7514dSTomas Winkler struct mei_msg_data buf;
225f862b6b2STomas Winkler size_t buf_idx;
2260cd7c01aSTomas Winkler u8 vtag;
22762e8e6adSTomas Winkler const struct file *fp;
2283d33ff24STomas Winkler int status;
229479327fcSTomas Winkler u32 internal:1;
230e0cb6b2fSAlexander Usyskin u32 blocking:1;
2314ed1cc99STomas Winkler struct mei_ext_hdr *ext_hdr;
232ffc2825cSGreg Kroah-Hartman };
233ffc2825cSGreg Kroah-Hartman
234ce23139cSAlexander Usyskin /**
235f35fe5f4SAlexander Usyskin * struct mei_cl_vtag - file pointer to vtag mapping structure
236f35fe5f4SAlexander Usyskin *
237f35fe5f4SAlexander Usyskin * @list: link in map queue
238f35fe5f4SAlexander Usyskin * @fp: file pointer
239f35fe5f4SAlexander Usyskin * @vtag: corresponding vtag
240f35fe5f4SAlexander Usyskin * @pending_read: the read is pending on this file
241f35fe5f4SAlexander Usyskin */
242f35fe5f4SAlexander Usyskin struct mei_cl_vtag {
243f35fe5f4SAlexander Usyskin struct list_head list;
244f35fe5f4SAlexander Usyskin const struct file *fp;
245f35fe5f4SAlexander Usyskin u8 vtag;
246f35fe5f4SAlexander Usyskin u8 pending_read:1;
247f35fe5f4SAlexander Usyskin };
248f35fe5f4SAlexander Usyskin
249f35fe5f4SAlexander Usyskin /**
250ce23139cSAlexander Usyskin * struct mei_cl - me client host representation
251ce23139cSAlexander Usyskin * carried in file->private_data
252ce23139cSAlexander Usyskin *
253ce23139cSAlexander Usyskin * @link: link in the clients list
254ce23139cSAlexander Usyskin * @dev: mei parent device
255ce23139cSAlexander Usyskin * @state: file operation state
256ce23139cSAlexander Usyskin * @tx_wait: wait queue for tx completion
257ce23139cSAlexander Usyskin * @rx_wait: wait queue for rx completion
258ce23139cSAlexander Usyskin * @wait: wait queue for management operation
259b38a362fSTomas Winkler * @ev_wait: notification wait queue
260237092bfSTomas Winkler * @ev_async: event async notification
261ce23139cSAlexander Usyskin * @status: connection status
262d49ed64aSAlexander Usyskin * @me_cl: fw client connected
26397d549b4SAlexander Usyskin * @fp: file associated with client
264ce23139cSAlexander Usyskin * @host_client_id: host id
265f35fe5f4SAlexander Usyskin * @vtag_map: vtag map
2664034b81bSTomas Winkler * @tx_flow_ctrl_creds: transmit flow credentials
26746978adaSAlexander Usyskin * @rx_flow_ctrl_creds: receive flow credentials
268ce23139cSAlexander Usyskin * @timer_count: watchdog timer for operation completion
269965ae37aSTomas Winkler * @notify_en: notification - enabled/disabled
270965ae37aSTomas Winkler * @notify_ev: pending notification event
271af336cabSAlexander Usyskin * @tx_cb_queued: number of tx callbacks in queue
272ce23139cSAlexander Usyskin * @writing_state: state of the tx
273a9bed610STomas Winkler * @rd_pending: pending read credits
274d1376f3dSAlexander Usyskin * @rd_completed_lock: protects rd_completed queue
275a9bed610STomas Winkler * @rd_completed: completed read
276369aea84SAlexander Usyskin * @dma: dma settings
277369aea84SAlexander Usyskin * @dma_mapped: dma buffer is currently mapped.
278ce23139cSAlexander Usyskin *
279b37719c3STomas Winkler * @cldev: device on the mei client bus
280ce23139cSAlexander Usyskin */
281ffc2825cSGreg Kroah-Hartman struct mei_cl {
282ffc2825cSGreg Kroah-Hartman struct list_head link;
283ffc2825cSGreg Kroah-Hartman struct mei_device *dev;
284ffc2825cSGreg Kroah-Hartman enum file_state state;
285ffc2825cSGreg Kroah-Hartman wait_queue_head_t tx_wait;
286ffc2825cSGreg Kroah-Hartman wait_queue_head_t rx_wait;
287ffc2825cSGreg Kroah-Hartman wait_queue_head_t wait;
288b38a362fSTomas Winkler wait_queue_head_t ev_wait;
289237092bfSTomas Winkler struct fasync_struct *ev_async;
290ffc2825cSGreg Kroah-Hartman int status;
291d49ed64aSAlexander Usyskin struct mei_me_client *me_cl;
29297d549b4SAlexander Usyskin const struct file *fp;
293ffc2825cSGreg Kroah-Hartman u8 host_client_id;
294f35fe5f4SAlexander Usyskin struct list_head vtag_map;
2954034b81bSTomas Winkler u8 tx_flow_ctrl_creds;
29646978adaSAlexander Usyskin u8 rx_flow_ctrl_creds;
297ffc2825cSGreg Kroah-Hartman u8 timer_count;
298965ae37aSTomas Winkler u8 notify_en;
299965ae37aSTomas Winkler u8 notify_ev;
300af336cabSAlexander Usyskin u8 tx_cb_queued;
301ffc2825cSGreg Kroah-Hartman enum mei_file_transaction_states writing_state;
302a9bed610STomas Winkler struct list_head rd_pending;
303d1376f3dSAlexander Usyskin spinlock_t rd_completed_lock; /* protects rd_completed queue */
304a9bed610STomas Winkler struct list_head rd_completed;
305369aea84SAlexander Usyskin struct mei_dma_data dma;
306369aea84SAlexander Usyskin u8 dma_mapped;
307a7b71bc0SSamuel Ortiz
308b37719c3STomas Winkler struct mei_cl_device *cldev;
309ffc2825cSGreg Kroah-Hartman };
310ffc2825cSGreg Kroah-Hartman
311af336cabSAlexander Usyskin #define MEI_TX_QUEUE_LIMIT_DEFAULT 50
312af336cabSAlexander Usyskin #define MEI_TX_QUEUE_LIMIT_MAX 255
313af336cabSAlexander Usyskin #define MEI_TX_QUEUE_LIMIT_MIN 30
314af336cabSAlexander Usyskin
31599c2658fSAlexander Usyskin /**
31699c2658fSAlexander Usyskin * struct mei_hw_ops - hw specific ops
317827eef51STomas Winkler *
318a8605ea2SAlexander Usyskin * @host_is_ready : query for host readiness
31999c2658fSAlexander Usyskin *
320a8605ea2SAlexander Usyskin * @hw_is_ready : query if hw is ready
321a8605ea2SAlexander Usyskin * @hw_reset : reset hw
322a8605ea2SAlexander Usyskin * @hw_start : start hw after reset
323a8605ea2SAlexander Usyskin * @hw_config : configure hw
32499c2658fSAlexander Usyskin *
325a8605ea2SAlexander Usyskin * @fw_status : get fw status registers
32652f6efdfSAlexander Usyskin * @trc_status : get trc status register
327a8605ea2SAlexander Usyskin * @pg_state : power gating state of the device
3283dc196eaSAlexander Usyskin * @pg_in_transition : is device now in pg transition
329a8605ea2SAlexander Usyskin * @pg_is_enabled : is power gating enabled
33099c2658fSAlexander Usyskin *
331a8605ea2SAlexander Usyskin * @intr_clear : clear pending interrupts
332a8605ea2SAlexander Usyskin * @intr_enable : enable interrupts
333a8605ea2SAlexander Usyskin * @intr_disable : disable interrupts
3344a8efd4aSTomas Winkler * @synchronize_irq : synchronize irqs
33599c2658fSAlexander Usyskin *
336a8605ea2SAlexander Usyskin * @hbuf_free_slots : query for write buffer empty slots
337a8605ea2SAlexander Usyskin * @hbuf_is_ready : query if write buffer is empty
3388c8d964cSTomas Winkler * @hbuf_depth : query for write buffer depth
33999c2658fSAlexander Usyskin *
340a8605ea2SAlexander Usyskin * @write : write a message to FW
34199c2658fSAlexander Usyskin *
342a8605ea2SAlexander Usyskin * @rdbuf_full_slots : query how many slots are filled
34399c2658fSAlexander Usyskin *
344a8605ea2SAlexander Usyskin * @read_hdr : get first 4 bytes (header)
345a8605ea2SAlexander Usyskin * @read : read a buffer from the FW
346827eef51STomas Winkler */
347827eef51STomas Winkler struct mei_hw_ops {
348827eef51STomas Winkler
349827eef51STomas Winkler bool (*host_is_ready)(struct mei_device *dev);
350827eef51STomas Winkler
351827eef51STomas Winkler bool (*hw_is_ready)(struct mei_device *dev);
352c20c68d5STomas Winkler int (*hw_reset)(struct mei_device *dev, bool enable);
353aafae7ecSTomas Winkler int (*hw_start)(struct mei_device *dev);
354261e071aSTomas Winkler int (*hw_config)(struct mei_device *dev);
355827eef51STomas Winkler
3561bd30b6aSTomas Winkler int (*fw_status)(struct mei_device *dev, struct mei_fw_status *fw_sts);
35752f6efdfSAlexander Usyskin int (*trc_status)(struct mei_device *dev, u32 *trc);
35852f6efdfSAlexander Usyskin
359964a2331STomas Winkler enum mei_pg_state (*pg_state)(struct mei_device *dev);
3603dc196eaSAlexander Usyskin bool (*pg_in_transition)(struct mei_device *dev);
361ee7e5afdSTomas Winkler bool (*pg_is_enabled)(struct mei_device *dev);
362ee7e5afdSTomas Winkler
363827eef51STomas Winkler void (*intr_clear)(struct mei_device *dev);
364827eef51STomas Winkler void (*intr_enable)(struct mei_device *dev);
365827eef51STomas Winkler void (*intr_disable)(struct mei_device *dev);
3664a8efd4aSTomas Winkler void (*synchronize_irq)(struct mei_device *dev);
367827eef51STomas Winkler
368827eef51STomas Winkler int (*hbuf_free_slots)(struct mei_device *dev);
369827eef51STomas Winkler bool (*hbuf_is_ready)(struct mei_device *dev);
3708c8d964cSTomas Winkler u32 (*hbuf_depth)(const struct mei_device *dev);
371827eef51STomas Winkler int (*write)(struct mei_device *dev,
37298e70866STomas Winkler const void *hdr, size_t hdr_len,
37398e70866STomas Winkler const void *data, size_t data_len);
374827eef51STomas Winkler
375827eef51STomas Winkler int (*rdbuf_full_slots)(struct mei_device *dev);
376827eef51STomas Winkler
377827eef51STomas Winkler u32 (*read_hdr)(const struct mei_device *dev);
378827eef51STomas Winkler int (*read)(struct mei_device *dev,
379827eef51STomas Winkler unsigned char *buf, unsigned long len);
380827eef51STomas Winkler };
381827eef51STomas Winkler
382e5354107SSamuel Ortiz /* MEI bus API*/
383a816a00eSAlexander Usyskin void mei_cl_bus_rescan_work(struct work_struct *work);
384ae48d74dSTomas Winkler void mei_cl_bus_dev_fixup(struct mei_cl_device *dev);
3850912ef48SKrzysztof Kozlowski ssize_t __mei_cl_send(struct mei_cl *cl, const u8 *buf, size_t length, u8 vtag,
386e0cb6b2fSAlexander Usyskin unsigned int mode);
38783f47eeaSAlexander Usyskin ssize_t __mei_cl_send_timeout(struct mei_cl *cl, const u8 *buf, size_t length, u8 vtag,
38883f47eeaSAlexander Usyskin unsigned int mode, unsigned long timeout);
38985261c1fSAlexander Usyskin ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length, u8 *vtag,
3909a7c0b69SAlexander Usyskin unsigned int mode, unsigned long timeout);
391a1f9ae2bSTomas Winkler bool mei_cl_bus_rx_event(struct mei_cl *cl);
392850f8940STomas Winkler bool mei_cl_bus_notify_event(struct mei_cl *cl);
393b37719c3STomas Winkler void mei_cl_bus_remove_devices(struct mei_device *bus);
394cf3baefbSSamuel Ortiz int mei_cl_bus_init(void);
395cf3baefbSSamuel Ortiz void mei_cl_bus_exit(void);
396cf3baefbSSamuel Ortiz
397964a2331STomas Winkler /**
398964a2331STomas Winkler * enum mei_pg_event - power gating transition events
399964a2331STomas Winkler *
400964a2331STomas Winkler * @MEI_PG_EVENT_IDLE: the driver is not in power gating transition
401964a2331STomas Winkler * @MEI_PG_EVENT_WAIT: the driver is waiting for a pg event to complete
402964a2331STomas Winkler * @MEI_PG_EVENT_RECEIVED: the driver received pg event
4033dc196eaSAlexander Usyskin * @MEI_PG_EVENT_INTR_WAIT: the driver is waiting for a pg event interrupt
4043dc196eaSAlexander Usyskin * @MEI_PG_EVENT_INTR_RECEIVED: the driver received pg event interrupt
405964a2331STomas Winkler */
406964a2331STomas Winkler enum mei_pg_event {
407964a2331STomas Winkler MEI_PG_EVENT_IDLE,
408964a2331STomas Winkler MEI_PG_EVENT_WAIT,
409964a2331STomas Winkler MEI_PG_EVENT_RECEIVED,
4103dc196eaSAlexander Usyskin MEI_PG_EVENT_INTR_WAIT,
4113dc196eaSAlexander Usyskin MEI_PG_EVENT_INTR_RECEIVED,
412964a2331STomas Winkler };
413964a2331STomas Winkler
414964a2331STomas Winkler /**
415964a2331STomas Winkler * enum mei_pg_state - device internal power gating state
416964a2331STomas Winkler *
417964a2331STomas Winkler * @MEI_PG_OFF: device is not power gated - it is active
418964a2331STomas Winkler * @MEI_PG_ON: device is power gated - it is in lower power state
419964a2331STomas Winkler */
420964a2331STomas Winkler enum mei_pg_state {
421964a2331STomas Winkler MEI_PG_OFF = 0,
422964a2331STomas Winkler MEI_PG_ON = 1,
423964a2331STomas Winkler };
424964a2331STomas Winkler
4251beeb4b9SAlexander Usyskin const char *mei_pg_state_str(enum mei_pg_state state);
4261beeb4b9SAlexander Usyskin
42724aadc80STomas Winkler /**
4283cfaeb33SAlexander Usyskin * struct mei_fw_version - MEI FW version struct
4293cfaeb33SAlexander Usyskin *
4303cfaeb33SAlexander Usyskin * @platform: platform identifier
4313cfaeb33SAlexander Usyskin * @major: major version field
4323cfaeb33SAlexander Usyskin * @minor: minor version field
4333cfaeb33SAlexander Usyskin * @buildno: build number version field
4343cfaeb33SAlexander Usyskin * @hotfix: hotfix number version field
4353cfaeb33SAlexander Usyskin */
4363cfaeb33SAlexander Usyskin struct mei_fw_version {
4373cfaeb33SAlexander Usyskin u8 platform;
4383cfaeb33SAlexander Usyskin u8 major;
4393cfaeb33SAlexander Usyskin u16 minor;
4403cfaeb33SAlexander Usyskin u16 buildno;
4413cfaeb33SAlexander Usyskin u16 hotfix;
4423cfaeb33SAlexander Usyskin };
4433cfaeb33SAlexander Usyskin
4443cfaeb33SAlexander Usyskin #define MEI_MAX_FW_VER_BLOCKS 3
4453cfaeb33SAlexander Usyskin
44695953618SAlexander Usyskin struct mei_dev_timeouts {
44795953618SAlexander Usyskin unsigned long hw_ready; /* Timeout on ready message, in jiffies */
44895953618SAlexander Usyskin int connect; /* HPS: at least 2 seconds, in seconds */
44995953618SAlexander Usyskin unsigned long cl_connect; /* HPS: Client Connect Timeout, in jiffies */
45095953618SAlexander Usyskin int client_init; /* HPS: Clients Enumeration Timeout, in seconds */
45195953618SAlexander Usyskin unsigned long pgi; /* PG Isolation time response, in jiffies */
45295953618SAlexander Usyskin unsigned int d0i3; /* D0i3 set/unset max response time, in jiffies */
45395953618SAlexander Usyskin unsigned long hbm; /* HBM operation timeout, in jiffies */
45495953618SAlexander Usyskin unsigned long mkhi_recv; /* receive timeout, in jiffies */
45595953618SAlexander Usyskin };
45695953618SAlexander Usyskin
4573cfaeb33SAlexander Usyskin /**
4585fb54fb4STomas Winkler * struct mei_device - MEI private device struct
459ce23139cSAlexander Usyskin *
460a8605ea2SAlexander Usyskin * @dev : device on a bus
461a8605ea2SAlexander Usyskin * @cdev : character device
462a8605ea2SAlexander Usyskin * @minor : minor number allocated for device
463f3d8e878SAlexander Usyskin *
464ce23139cSAlexander Usyskin * @write_list : write pending list
465ce23139cSAlexander Usyskin * @write_waiting_list : write completion list
466ce23139cSAlexander Usyskin * @ctrl_wr_list : pending control write list
467ce23139cSAlexander Usyskin * @ctrl_rd_list : pending control read list
468af336cabSAlexander Usyskin * @tx_queue_limit: tx queues per client linit
469bae1cc7dSTomas Winkler *
470ce23139cSAlexander Usyskin * @file_list : list of opened handles
471ce23139cSAlexander Usyskin * @open_handle_count: number of opened handles
472ce23139cSAlexander Usyskin *
473ce23139cSAlexander Usyskin * @device_lock : big device lock
474ce23139cSAlexander Usyskin * @timer_work : MEI timer delayed work (timeouts)
475ce23139cSAlexander Usyskin *
476ce23139cSAlexander Usyskin * @recvd_hw_ready : hw ready message received flag
477ce23139cSAlexander Usyskin *
478ce23139cSAlexander Usyskin * @wait_hw_ready : wait queue for receive HW ready message form FW
479ce23139cSAlexander Usyskin * @wait_pg : wait queue for receive PG message from FW
480ce23139cSAlexander Usyskin * @wait_hbm_start : wait queue for receive HBM start message from FW
481ce23139cSAlexander Usyskin *
482ce23139cSAlexander Usyskin * @reset_count : number of consecutive resets
483ce23139cSAlexander Usyskin * @dev_state : device state
484ce23139cSAlexander Usyskin * @hbm_state : state of host bus message protocol
485342e4c7eSTomas Winkler * @pxp_mode : PXP device mode
486ce23139cSAlexander Usyskin * @init_clients_timer : HBM init handshake timeout
487bae1cc7dSTomas Winkler *
488a8605ea2SAlexander Usyskin * @pg_event : power gating event
489ce23139cSAlexander Usyskin * @pg_domain : runtime PM domain
490ce23139cSAlexander Usyskin *
491ce23139cSAlexander Usyskin * @rd_msg_buf : control messages buffer
492ce23139cSAlexander Usyskin * @rd_msg_hdr : read message header storage
4930cd7c01aSTomas Winkler * @rd_msg_hdr_count : how many dwords were already read from header
494ce23139cSAlexander Usyskin *
495a8605ea2SAlexander Usyskin * @hbuf_is_ready : query if the host host/write buffer is ready
496ce0925e8STomas Winkler * @dr_dscr: DMA ring descriptors: TX, RX, and CTRL
497ce23139cSAlexander Usyskin *
498ce23139cSAlexander Usyskin * @version : HBM protocol version in use
499ce23139cSAlexander Usyskin * @hbm_f_pg_supported : hbm feature pgi protocol
50070ef835cSTomas Winkler * @hbm_f_dc_supported : hbm feature dynamic clients
50118901357SAlexander Usyskin * @hbm_f_dot_supported : hbm feature disconnect on timeout
5024d99877dSTomas Winkler * @hbm_f_ev_supported : hbm feature event notification
503f4e06246SAlexander Usyskin * @hbm_f_fa_supported : hbm feature fixed address client
50427f476eaSAlexander Usyskin * @hbm_f_ie_supported : hbm feature immediate reply to enum request
5057ee7f45aSAlexander Usyskin * @hbm_f_os_supported : hbm feature support OS ver message
506c2bd9fc1STomas Winkler * @hbm_f_dr_supported : hbm feature dma ring supported
507beb4e1e5SAlexander Usyskin * @hbm_f_vt_supported : hbm feature vtag supported
508e5cab1f9SAlexander Usyskin * @hbm_f_cap_supported : hbm feature capabilities message supported
509b7a48041SAlexander Usyskin * @hbm_f_cd_supported : hbm feature client dma supported
5104ed1cc99STomas Winkler * @hbm_f_gsc_supported : hbm feature gsc supported
511ce23139cSAlexander Usyskin *
5123cfaeb33SAlexander Usyskin * @fw_ver : FW versions
5133cfaeb33SAlexander Usyskin *
514f8204f0dSAlexander Usyskin * @fw_f_fw_ver_supported : fw feature: fw version supported
515*6549b2b7SAlexander Usyskin * @fw_ver_received : fw version received
516f8204f0dSAlexander Usyskin *
517b7d88514STomas Winkler * @me_clients_rwsem: rw lock over me_clients list
518ce23139cSAlexander Usyskin * @me_clients : list of FW clients
519ce23139cSAlexander Usyskin * @me_clients_map : FW clients bit map
520ce23139cSAlexander Usyskin * @host_clients_map : host clients id pool
521ce23139cSAlexander Usyskin *
522eeabfcf5SAlexander Usyskin * @allow_fixed_address: allow user space to connect a fixed client
523f4e06246SAlexander Usyskin * @override_fixed_address: force allow fixed address behavior
524eeabfcf5SAlexander Usyskin *
52595953618SAlexander Usyskin * @timeouts: actual timeout values
52695953618SAlexander Usyskin *
527ce23139cSAlexander Usyskin * @reset_work : work item for the device reset
528a816a00eSAlexander Usyskin * @bus_rescan_work : work item for the bus rescan
529ce23139cSAlexander Usyskin *
530ce23139cSAlexander Usyskin * @device_list : mei client bus list
5310ff0a8d8STomas Winkler * @cl_bus_lock : client bus list lock
532ce23139cSAlexander Usyskin *
5332f79d3d1SAlexander Usyskin * @kind : kind of mei device
5342f79d3d1SAlexander Usyskin *
535ce23139cSAlexander Usyskin * @dbgfs_dir : debugfs mei root directory
536ce23139cSAlexander Usyskin *
537ce23139cSAlexander Usyskin * @ops: : hw specific operations
538ce23139cSAlexander Usyskin * @hw : hw specific data
53924aadc80STomas Winkler */
540ffc2825cSGreg Kroah-Hartman struct mei_device {
5413a7e9b6cSTomas Winkler struct device *dev;
542f3d8e878SAlexander Usyskin struct cdev cdev;
543f3d8e878SAlexander Usyskin int minor;
544f3d8e878SAlexander Usyskin
545962ff7bcSAlexander Usyskin struct list_head write_list;
546962ff7bcSAlexander Usyskin struct list_head write_waiting_list;
547962ff7bcSAlexander Usyskin struct list_head ctrl_wr_list;
548962ff7bcSAlexander Usyskin struct list_head ctrl_rd_list;
549af336cabSAlexander Usyskin u8 tx_queue_limit;
550ffc2825cSGreg Kroah-Hartman
551ffc2825cSGreg Kroah-Hartman struct list_head file_list;
552ffc2825cSGreg Kroah-Hartman long open_handle_count;
553fecb0d58STomas Winkler
554ce23139cSAlexander Usyskin struct mutex device_lock;
555ce23139cSAlexander Usyskin struct delayed_work timer_work;
556aafae7ecSTomas Winkler
557aafae7ecSTomas Winkler bool recvd_hw_ready;
558ffc2825cSGreg Kroah-Hartman /*
559ffc2825cSGreg Kroah-Hartman * waiting queue for receive message from FW
560ffc2825cSGreg Kroah-Hartman */
561aafae7ecSTomas Winkler wait_queue_head_t wait_hw_ready;
5624fcbc99bSTomas Winkler wait_queue_head_t wait_pg;
563cb02efc3SAlexander Usyskin wait_queue_head_t wait_hbm_start;
564ffc2825cSGreg Kroah-Hartman
565ffc2825cSGreg Kroah-Hartman /*
566ffc2825cSGreg Kroah-Hartman * mei device states
567ffc2825cSGreg Kroah-Hartman */
5686adb8efbSTomas Winkler unsigned long reset_count;
569b210d750STomas Winkler enum mei_dev_state dev_state;
5709b0d5efcSTomas Winkler enum mei_hbm_state hbm_state;
571342e4c7eSTomas Winkler enum mei_dev_pxp_mode pxp_mode;
572ffc2825cSGreg Kroah-Hartman u16 init_clients_timer;
573ffc2825cSGreg Kroah-Hartman
574964a2331STomas Winkler /*
575964a2331STomas Winkler * Power Gating support
576964a2331STomas Winkler */
577964a2331STomas Winkler enum mei_pg_event pg_event;
578bbd6d050SRafael J. Wysocki #ifdef CONFIG_PM
579e13fa90cSTomas Winkler struct dev_pm_domain pg_domain;
580bbd6d050SRafael J. Wysocki #endif /* CONFIG_PM */
581964a2331STomas Winkler
582ce23139cSAlexander Usyskin unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE];
5830cd7c01aSTomas Winkler u32 rd_msg_hdr[MEI_RD_MSG_BUF_SIZE];
5840cd7c01aSTomas Winkler int rd_msg_hdr_count;
585e46f1874STomas Winkler
586330dd7daSTomas Winkler /* write buffer */
587330dd7daSTomas Winkler bool hbuf_is_ready;
588330dd7daSTomas Winkler
589ce0925e8STomas Winkler struct mei_dma_dscr dr_dscr[DMA_DSCR_NUM];
590ce0925e8STomas Winkler
591ffc2825cSGreg Kroah-Hartman struct hbm_version version;
592bae1cc7dSTomas Winkler unsigned int hbm_f_pg_supported:1;
59370ef835cSTomas Winkler unsigned int hbm_f_dc_supported:1;
59418901357SAlexander Usyskin unsigned int hbm_f_dot_supported:1;
5954d99877dSTomas Winkler unsigned int hbm_f_ev_supported:1;
596f4e06246SAlexander Usyskin unsigned int hbm_f_fa_supported:1;
59727f476eaSAlexander Usyskin unsigned int hbm_f_ie_supported:1;
5987ee7f45aSAlexander Usyskin unsigned int hbm_f_os_supported:1;
599c2bd9fc1STomas Winkler unsigned int hbm_f_dr_supported:1;
600beb4e1e5SAlexander Usyskin unsigned int hbm_f_vt_supported:1;
601e5cab1f9SAlexander Usyskin unsigned int hbm_f_cap_supported:1;
602b7a48041SAlexander Usyskin unsigned int hbm_f_cd_supported:1;
6034ed1cc99STomas Winkler unsigned int hbm_f_gsc_supported:1;
604ffc2825cSGreg Kroah-Hartman
6053cfaeb33SAlexander Usyskin struct mei_fw_version fw_ver[MEI_MAX_FW_VER_BLOCKS];
6063cfaeb33SAlexander Usyskin
607f8204f0dSAlexander Usyskin unsigned int fw_f_fw_ver_supported:1;
608*6549b2b7SAlexander Usyskin unsigned int fw_ver_received:1;
609f8204f0dSAlexander Usyskin
610b7d88514STomas Winkler struct rw_semaphore me_clients_rwsem;
6115ca2d388STomas Winkler struct list_head me_clients;
612ffc2825cSGreg Kroah-Hartman DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX);
613ffc2825cSGreg Kroah-Hartman DECLARE_BITMAP(host_clients_map, MEI_CLIENTS_MAX);
614ffc2825cSGreg Kroah-Hartman
615621a5f7aSViresh Kumar bool allow_fixed_address;
616f4e06246SAlexander Usyskin bool override_fixed_address;
617eeabfcf5SAlexander Usyskin
61895953618SAlexander Usyskin struct mei_dev_timeouts timeouts;
61995953618SAlexander Usyskin
620544f9460STomas Winkler struct work_struct reset_work;
621a816a00eSAlexander Usyskin struct work_struct bus_rescan_work;
622827eef51STomas Winkler
623a7b71bc0SSamuel Ortiz /* List of bus devices */
624a7b71bc0SSamuel Ortiz struct list_head device_list;
6250ff0a8d8STomas Winkler struct mutex cl_bus_lock;
626a7b71bc0SSamuel Ortiz
6272f79d3d1SAlexander Usyskin const char *kind;
6282f79d3d1SAlexander Usyskin
62930e53bb8STomas Winkler #if IS_ENABLED(CONFIG_DEBUG_FS)
63030e53bb8STomas Winkler struct dentry *dbgfs_dir;
63130e53bb8STomas Winkler #endif /* CONFIG_DEBUG_FS */
63230e53bb8STomas Winkler
633827eef51STomas Winkler const struct mei_hw_ops *ops;
634f490e8aeSGustavo A. R. Silva char hw[] __aligned(sizeof(void *));
635ffc2825cSGreg Kroah-Hartman };
636ffc2825cSGreg Kroah-Hartman
mei_secs_to_jiffies(unsigned long sec)6373870c320STomas Winkler static inline unsigned long mei_secs_to_jiffies(unsigned long sec)
6383870c320STomas Winkler {
6393870c320STomas Winkler return msecs_to_jiffies(sec * MSEC_PER_SEC);
6403870c320STomas Winkler }
6413870c320STomas Winkler
642c8c8d080STomas Winkler /**
64398e70866STomas Winkler * mei_data2slots - get slots number from a message length
644ce23139cSAlexander Usyskin *
645a8605ea2SAlexander Usyskin * @length: size of the messages in bytes
646a8605ea2SAlexander Usyskin *
647a8605ea2SAlexander Usyskin * Return: number of slots
648c8c8d080STomas Winkler */
mei_data2slots(size_t length)649c8c8d080STomas Winkler static inline u32 mei_data2slots(size_t length)
650c8c8d080STomas Winkler {
65198e70866STomas Winkler return DIV_ROUND_UP(length, MEI_SLOT_SIZE);
65298e70866STomas Winkler }
65398e70866STomas Winkler
65498e70866STomas Winkler /**
65598e70866STomas Winkler * mei_hbm2slots - get slots number from a hbm message length
65698e70866STomas Winkler * length + size of the mei message header
65798e70866STomas Winkler *
65898e70866STomas Winkler * @length: size of the messages in bytes
65998e70866STomas Winkler *
66098e70866STomas Winkler * Return: number of slots
66198e70866STomas Winkler */
mei_hbm2slots(size_t length)66298e70866STomas Winkler static inline u32 mei_hbm2slots(size_t length)
66398e70866STomas Winkler {
6649fc5f0f8STomas Winkler return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, MEI_SLOT_SIZE);
665c8c8d080STomas Winkler }
666c8c8d080STomas Winkler
66710ee9074STomas Winkler /**
66810ee9074STomas Winkler * mei_slots2data - get data in slots - bytes from slots
669ce23139cSAlexander Usyskin *
670a8605ea2SAlexander Usyskin * @slots: number of available slots
671ce23139cSAlexander Usyskin *
672a8605ea2SAlexander Usyskin * Return: number of bytes in slots
67310ee9074STomas Winkler */
mei_slots2data(int slots)67410ee9074STomas Winkler static inline u32 mei_slots2data(int slots)
67510ee9074STomas Winkler {
6769fc5f0f8STomas Winkler return slots * MEI_SLOT_SIZE;
67710ee9074STomas Winkler }
67810ee9074STomas Winkler
679ffc2825cSGreg Kroah-Hartman /*
680ffc2825cSGreg Kroah-Hartman * mei init function prototypes
681ffc2825cSGreg Kroah-Hartman */
6823a7e9b6cSTomas Winkler void mei_device_init(struct mei_device *dev,
6833a7e9b6cSTomas Winkler struct device *device,
68495953618SAlexander Usyskin bool slow_fw,
6853a7e9b6cSTomas Winkler const struct mei_hw_ops *hw_ops);
68633ec0826STomas Winkler int mei_reset(struct mei_device *dev);
687c4d589beSTomas Winkler int mei_start(struct mei_device *dev);
68833ec0826STomas Winkler int mei_restart(struct mei_device *dev);
6897cb035d9STomas Winkler void mei_stop(struct mei_device *dev);
690dc844b0dSTomas Winkler void mei_cancel_work(struct mei_device *dev);
691ffc2825cSGreg Kroah-Hartman
69243b8a7edSAlexander Usyskin void mei_set_devstate(struct mei_device *dev, enum mei_dev_state state);
69343b8a7edSAlexander Usyskin
694ce0925e8STomas Winkler int mei_dmam_ring_alloc(struct mei_device *dev);
695ce0925e8STomas Winkler void mei_dmam_ring_free(struct mei_device *dev);
696ce0925e8STomas Winkler bool mei_dma_ring_is_allocated(struct mei_device *dev);
6972513eb0dSTomas Winkler void mei_dma_ring_reset(struct mei_device *dev);
6986316321fSTomas Winkler void mei_dma_ring_read(struct mei_device *dev, unsigned char *buf, u32 len);
699c30362ccSTomas Winkler void mei_dma_ring_write(struct mei_device *dev, unsigned char *buf, u32 len);
700c30362ccSTomas Winkler u32 mei_dma_ring_empty_slots(struct mei_device *dev);
701ce0925e8STomas Winkler
702ffc2825cSGreg Kroah-Hartman /*
703ffc2825cSGreg Kroah-Hartman * MEI interrupt functions prototype
704ffc2825cSGreg Kroah-Hartman */
70506ecd645STomas Winkler
706ffc2825cSGreg Kroah-Hartman void mei_timer(struct work_struct *work);
7071892fc2eSAlexander Usyskin void mei_schedule_stall_timer(struct mei_device *dev);
70806ecd645STomas Winkler int mei_irq_read_handler(struct mei_device *dev,
709962ff7bcSAlexander Usyskin struct list_head *cmpl_list, s32 *slots);
71006ecd645STomas Winkler
711962ff7bcSAlexander Usyskin int mei_irq_write_handler(struct mei_device *dev, struct list_head *cmpl_list);
712962ff7bcSAlexander Usyskin void mei_irq_compl_handler(struct mei_device *dev, struct list_head *cmpl_list);
713ffc2825cSGreg Kroah-Hartman
714ffc2825cSGreg Kroah-Hartman /*
715ffc2825cSGreg Kroah-Hartman * Register Access Function
716ffc2825cSGreg Kroah-Hartman */
717ffc2825cSGreg Kroah-Hartman
7188d929d48SAlexander Usyskin
mei_hw_config(struct mei_device * dev)719261e071aSTomas Winkler static inline int mei_hw_config(struct mei_device *dev)
720827eef51STomas Winkler {
721261e071aSTomas Winkler return dev->ops->hw_config(dev);
722827eef51STomas Winkler }
723ee7e5afdSTomas Winkler
mei_pg_state(struct mei_device * dev)724964a2331STomas Winkler static inline enum mei_pg_state mei_pg_state(struct mei_device *dev)
725964a2331STomas Winkler {
726964a2331STomas Winkler return dev->ops->pg_state(dev);
727964a2331STomas Winkler }
728964a2331STomas Winkler
mei_pg_in_transition(struct mei_device * dev)7293dc196eaSAlexander Usyskin static inline bool mei_pg_in_transition(struct mei_device *dev)
7303dc196eaSAlexander Usyskin {
7313dc196eaSAlexander Usyskin return dev->ops->pg_in_transition(dev);
7323dc196eaSAlexander Usyskin }
7333dc196eaSAlexander Usyskin
mei_pg_is_enabled(struct mei_device * dev)734ee7e5afdSTomas Winkler static inline bool mei_pg_is_enabled(struct mei_device *dev)
735ee7e5afdSTomas Winkler {
736ee7e5afdSTomas Winkler return dev->ops->pg_is_enabled(dev);
737ee7e5afdSTomas Winkler }
738ee7e5afdSTomas Winkler
mei_hw_reset(struct mei_device * dev,bool enable)739c20c68d5STomas Winkler static inline int mei_hw_reset(struct mei_device *dev, bool enable)
740827eef51STomas Winkler {
741c20c68d5STomas Winkler return dev->ops->hw_reset(dev, enable);
742827eef51STomas Winkler }
743ffc2825cSGreg Kroah-Hartman
mei_hw_start(struct mei_device * dev)7449049f793STomas Winkler static inline int mei_hw_start(struct mei_device *dev)
745aafae7ecSTomas Winkler {
7469049f793STomas Winkler return dev->ops->hw_start(dev);
747aafae7ecSTomas Winkler }
748aafae7ecSTomas Winkler
mei_clear_interrupts(struct mei_device * dev)749827eef51STomas Winkler static inline void mei_clear_interrupts(struct mei_device *dev)
750827eef51STomas Winkler {
751827eef51STomas Winkler dev->ops->intr_clear(dev);
752827eef51STomas Winkler }
753ffc2825cSGreg Kroah-Hartman
mei_enable_interrupts(struct mei_device * dev)754827eef51STomas Winkler static inline void mei_enable_interrupts(struct mei_device *dev)
755827eef51STomas Winkler {
756827eef51STomas Winkler dev->ops->intr_enable(dev);
757827eef51STomas Winkler }
758e7e0c231STomas Winkler
mei_disable_interrupts(struct mei_device * dev)759827eef51STomas Winkler static inline void mei_disable_interrupts(struct mei_device *dev)
760827eef51STomas Winkler {
761827eef51STomas Winkler dev->ops->intr_disable(dev);
762827eef51STomas Winkler }
763ffc2825cSGreg Kroah-Hartman
mei_synchronize_irq(struct mei_device * dev)7644a8efd4aSTomas Winkler static inline void mei_synchronize_irq(struct mei_device *dev)
7654a8efd4aSTomas Winkler {
7664a8efd4aSTomas Winkler dev->ops->synchronize_irq(dev);
7674a8efd4aSTomas Winkler }
7684a8efd4aSTomas Winkler
mei_host_is_ready(struct mei_device * dev)769827eef51STomas Winkler static inline bool mei_host_is_ready(struct mei_device *dev)
770827eef51STomas Winkler {
771827eef51STomas Winkler return dev->ops->host_is_ready(dev);
772827eef51STomas Winkler }
mei_hw_is_ready(struct mei_device * dev)773827eef51STomas Winkler static inline bool mei_hw_is_ready(struct mei_device *dev)
774827eef51STomas Winkler {
775827eef51STomas Winkler return dev->ops->hw_is_ready(dev);
776827eef51STomas Winkler }
777115ba28cSTomas Winkler
mei_hbuf_is_ready(struct mei_device * dev)778827eef51STomas Winkler static inline bool mei_hbuf_is_ready(struct mei_device *dev)
779827eef51STomas Winkler {
780827eef51STomas Winkler return dev->ops->hbuf_is_ready(dev);
781827eef51STomas Winkler }
7823a65dd4eSTomas Winkler
mei_hbuf_empty_slots(struct mei_device * dev)783827eef51STomas Winkler static inline int mei_hbuf_empty_slots(struct mei_device *dev)
784827eef51STomas Winkler {
785827eef51STomas Winkler return dev->ops->hbuf_free_slots(dev);
786827eef51STomas Winkler }
787827eef51STomas Winkler
mei_hbuf_depth(const struct mei_device * dev)7888c8d964cSTomas Winkler static inline u32 mei_hbuf_depth(const struct mei_device *dev)
789827eef51STomas Winkler {
7908c8d964cSTomas Winkler return dev->ops->hbuf_depth(dev);
791827eef51STomas Winkler }
792827eef51STomas Winkler
mei_write_message(struct mei_device * dev,const void * hdr,size_t hdr_len,const void * data,size_t data_len)793827eef51STomas Winkler static inline int mei_write_message(struct mei_device *dev,
79498e70866STomas Winkler const void *hdr, size_t hdr_len,
79598e70866STomas Winkler const void *data, size_t data_len)
796827eef51STomas Winkler {
79798e70866STomas Winkler return dev->ops->write(dev, hdr, hdr_len, data, data_len);
798827eef51STomas Winkler }
799827eef51STomas Winkler
mei_read_hdr(const struct mei_device * dev)800827eef51STomas Winkler static inline u32 mei_read_hdr(const struct mei_device *dev)
801827eef51STomas Winkler {
802827eef51STomas Winkler return dev->ops->read_hdr(dev);
803827eef51STomas Winkler }
804827eef51STomas Winkler
mei_read_slots(struct mei_device * dev,unsigned char * buf,unsigned long len)805827eef51STomas Winkler static inline void mei_read_slots(struct mei_device *dev,
806827eef51STomas Winkler unsigned char *buf, unsigned long len)
807827eef51STomas Winkler {
808827eef51STomas Winkler dev->ops->read(dev, buf, len);
809827eef51STomas Winkler }
810827eef51STomas Winkler
mei_count_full_read_slots(struct mei_device * dev)811827eef51STomas Winkler static inline int mei_count_full_read_slots(struct mei_device *dev)
812827eef51STomas Winkler {
813827eef51STomas Winkler return dev->ops->rdbuf_full_slots(dev);
814827eef51STomas Winkler }
8155bd64714STomas Winkler
mei_trc_status(struct mei_device * dev,u32 * trc)81652f6efdfSAlexander Usyskin static inline int mei_trc_status(struct mei_device *dev, u32 *trc)
81752f6efdfSAlexander Usyskin {
81852f6efdfSAlexander Usyskin if (dev->ops->trc_status)
81952f6efdfSAlexander Usyskin return dev->ops->trc_status(dev, trc);
82052f6efdfSAlexander Usyskin return -EOPNOTSUPP;
82152f6efdfSAlexander Usyskin }
82252f6efdfSAlexander Usyskin
mei_fw_status(struct mei_device * dev,struct mei_fw_status * fw_status)8231bd30b6aSTomas Winkler static inline int mei_fw_status(struct mei_device *dev,
8241bd30b6aSTomas Winkler struct mei_fw_status *fw_status)
8251bd30b6aSTomas Winkler {
8261bd30b6aSTomas Winkler return dev->ops->fw_status(dev, fw_status);
8271bd30b6aSTomas Winkler }
82804dd3661SAlexander Usyskin
8296aae48ffSTomas Winkler bool mei_hbuf_acquire(struct mei_device *dev);
8306aae48ffSTomas Winkler
831a532bbedSTomas Winkler bool mei_write_is_idle(struct mei_device *dev);
832a532bbedSTomas Winkler
83330e53bb8STomas Winkler #if IS_ENABLED(CONFIG_DEBUG_FS)
8345666d896SGreg Kroah-Hartman void mei_dbgfs_register(struct mei_device *dev, const char *name);
83530e53bb8STomas Winkler void mei_dbgfs_deregister(struct mei_device *dev);
83630e53bb8STomas Winkler #else
mei_dbgfs_register(struct mei_device * dev,const char * name)8375666d896SGreg Kroah-Hartman static inline void mei_dbgfs_register(struct mei_device *dev, const char *name) {}
mei_dbgfs_deregister(struct mei_device * dev)83830e53bb8STomas Winkler static inline void mei_dbgfs_deregister(struct mei_device *dev) {}
83930e53bb8STomas Winkler #endif /* CONFIG_DEBUG_FS */
84030e53bb8STomas Winkler
841f3d8e878SAlexander Usyskin int mei_register(struct mei_device *dev, struct device *parent);
84230e53bb8STomas Winkler void mei_deregister(struct mei_device *dev);
8432703d4b2STomas Winkler
8440cd7c01aSTomas Winkler #define MEI_HDR_FMT "hdr:host=%02d me=%02d len=%d dma=%1d ext=%1d internal=%1d comp=%1d"
84515d4acc5STomas Winkler #define MEI_HDR_PRM(hdr) \
84615d4acc5STomas Winkler (hdr)->host_addr, (hdr)->me_addr, \
8470cd7c01aSTomas Winkler (hdr)->length, (hdr)->dma_ring, (hdr)->extended, \
8480cd7c01aSTomas Winkler (hdr)->internal, (hdr)->msg_complete
84915d4acc5STomas Winkler
850edca5ea3SAlexander Usyskin ssize_t mei_fw_status2str(struct mei_fw_status *fw_sts, char *buf, size_t len);
851edca5ea3SAlexander Usyskin /**
852edca5ea3SAlexander Usyskin * mei_fw_status_str - fetch and convert fw status registers to printable string
853edca5ea3SAlexander Usyskin *
854edca5ea3SAlexander Usyskin * @dev: the device structure
855edca5ea3SAlexander Usyskin * @buf: string buffer at minimal size MEI_FW_STATUS_STR_SZ
856edca5ea3SAlexander Usyskin * @len: buffer len must be >= MEI_FW_STATUS_STR_SZ
857edca5ea3SAlexander Usyskin *
858edca5ea3SAlexander Usyskin * Return: number of bytes written or < 0 on failure
859edca5ea3SAlexander Usyskin */
mei_fw_status_str(struct mei_device * dev,char * buf,size_t len)860edca5ea3SAlexander Usyskin static inline ssize_t mei_fw_status_str(struct mei_device *dev,
861edca5ea3SAlexander Usyskin char *buf, size_t len)
862edca5ea3SAlexander Usyskin {
863edca5ea3SAlexander Usyskin struct mei_fw_status fw_status;
864edca5ea3SAlexander Usyskin int ret;
865edca5ea3SAlexander Usyskin
866edca5ea3SAlexander Usyskin buf[0] = '\0';
867edca5ea3SAlexander Usyskin
868edca5ea3SAlexander Usyskin ret = mei_fw_status(dev, &fw_status);
869edca5ea3SAlexander Usyskin if (ret)
870edca5ea3SAlexander Usyskin return ret;
871edca5ea3SAlexander Usyskin
872edca5ea3SAlexander Usyskin ret = mei_fw_status2str(&fw_status, buf, MEI_FW_STATUS_STR_SZ);
873edca5ea3SAlexander Usyskin
874edca5ea3SAlexander Usyskin return ret;
875edca5ea3SAlexander Usyskin }
876edca5ea3SAlexander Usyskin
877edca5ea3SAlexander Usyskin
878ffc2825cSGreg Kroah-Hartman #endif
879