xref: /openbmc/linux/drivers/misc/mei/mei_dev.h (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
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