xref: /linux/drivers/misc/issei/issei_dev.h (revision 93e4b3076b5f2d853462b9777d083c77fc0b7b23)
165f0ecb9SAlexander Usyskin /* SPDX-License-Identifier: GPL-2.0 */
265f0ecb9SAlexander Usyskin /* Copyright (C) 2023-2026 Intel Corporation */
365f0ecb9SAlexander Usyskin #ifndef _ISSEI_DEV_H_
465f0ecb9SAlexander Usyskin #define _ISSEI_DEV_H_
565f0ecb9SAlexander Usyskin 
665f0ecb9SAlexander Usyskin #include <linux/device.h>
765f0ecb9SAlexander Usyskin #include <linux/mutex.h>
865f0ecb9SAlexander Usyskin #include <linux/sched.h>
965f0ecb9SAlexander Usyskin #include <linux/time64.h>
1065f0ecb9SAlexander Usyskin #include <linux/types.h>
1165f0ecb9SAlexander Usyskin #include <linux/wait.h>
1265f0ecb9SAlexander Usyskin 
1365f0ecb9SAlexander Usyskin #include "dma.h"
1465f0ecb9SAlexander Usyskin 
1565f0ecb9SAlexander Usyskin struct cdev;
1665f0ecb9SAlexander Usyskin struct kset;
1765f0ecb9SAlexander Usyskin 
1865f0ecb9SAlexander Usyskin struct issei_device;
1965f0ecb9SAlexander Usyskin struct issei_host_client;
2065f0ecb9SAlexander Usyskin 
2165f0ecb9SAlexander Usyskin extern struct class *issei_class;
2265f0ecb9SAlexander Usyskin 
2365f0ecb9SAlexander Usyskin #define ISSEI_HOST_CLIENTS_MAX		255
2465f0ecb9SAlexander Usyskin 
2565f0ecb9SAlexander Usyskin #define ISSEI_SUPPORTED_PROTOCOL_VER	1
2665f0ecb9SAlexander Usyskin 
2765f0ecb9SAlexander Usyskin #define ISSEI_MAX_CONSEC_RESET		3
2865f0ecb9SAlexander Usyskin 
2965f0ecb9SAlexander Usyskin #define ISSEI_RST_HW_READY_TIMEOUT_MSEC (2 * MSEC_PER_SEC)
3065f0ecb9SAlexander Usyskin #define ISSEI_RST_STEP_TIMEOUT_MSEC     (2 * MSEC_PER_SEC)
3165f0ecb9SAlexander Usyskin #define ISSEI_STOP_TIMEOUT_MSEC         500
3265f0ecb9SAlexander Usyskin #define ISSEI_WRITE_TIMEOUT_MSEC        (MSEC_PER_SEC)
3365f0ecb9SAlexander Usyskin 
3465f0ecb9SAlexander Usyskin /**
3565f0ecb9SAlexander Usyskin  * struct issei_write_buf - write buffer object
3665f0ecb9SAlexander Usyskin  * @list: linked list pointer
3765f0ecb9SAlexander Usyskin  * @cl: host client that requested this write
3865f0ecb9SAlexander Usyskin  * @data: data to write
3965f0ecb9SAlexander Usyskin  * @data_size: data size
4065f0ecb9SAlexander Usyskin  */
4165f0ecb9SAlexander Usyskin struct issei_write_buf {
4265f0ecb9SAlexander Usyskin 	struct list_head list;
4365f0ecb9SAlexander Usyskin 	struct issei_host_client *cl;
4465f0ecb9SAlexander Usyskin 	const u8 *data;
4565f0ecb9SAlexander Usyskin 	size_t data_size;
4665f0ecb9SAlexander Usyskin };
4765f0ecb9SAlexander Usyskin 
4865f0ecb9SAlexander Usyskin /**
4965f0ecb9SAlexander Usyskin  * struct issei_hw_ops - callbacks for hardware operations
5065f0ecb9SAlexander Usyskin  * @irq_clear: clear irq
5165f0ecb9SAlexander Usyskin  * @irq_enable: enable irq
5265f0ecb9SAlexander Usyskin  * @irq_disable: disable irq
5365f0ecb9SAlexander Usyskin  * @irq_sync: sync irq
5465f0ecb9SAlexander Usyskin  * @hw_reset: initiate hardware reset
5565f0ecb9SAlexander Usyskin  * @hw_config: initial hardware config
5665f0ecb9SAlexander Usyskin  * @hw_is_ready: check if hardware is ready
5765f0ecb9SAlexander Usyskin  * @hw_reset_release: release hardware from reset
5865f0ecb9SAlexander Usyskin  * @host_set_ready: set host ready indicator
5965f0ecb9SAlexander Usyskin  * @setup_message_send: send setup message
6065f0ecb9SAlexander Usyskin  * @setup_message_recv: receive setup message
6165f0ecb9SAlexander Usyskin  * @irq_write_generate: generate interrupt on write complete
6265f0ecb9SAlexander Usyskin  */
6365f0ecb9SAlexander Usyskin struct issei_hw_ops {
6465f0ecb9SAlexander Usyskin 	void (*irq_clear)(struct issei_device *idev);
6565f0ecb9SAlexander Usyskin 	void (*irq_enable)(struct issei_device *idev);
6665f0ecb9SAlexander Usyskin 	void (*irq_disable)(struct issei_device *idev);
6765f0ecb9SAlexander Usyskin 	void (*irq_sync)(struct issei_device *idev);
6865f0ecb9SAlexander Usyskin 	int (*hw_reset)(struct issei_device *idev, bool enable);
6965f0ecb9SAlexander Usyskin 	int (*hw_config)(struct issei_device *idev);
7065f0ecb9SAlexander Usyskin 	bool (*hw_is_ready)(struct issei_device *idev);
7165f0ecb9SAlexander Usyskin 	void (*hw_reset_release)(struct issei_device *idev);
7265f0ecb9SAlexander Usyskin 	void (*host_set_ready)(struct issei_device *idev);
7365f0ecb9SAlexander Usyskin 	int (*setup_message_send)(struct issei_device *idev);
7465f0ecb9SAlexander Usyskin 	int (*setup_message_recv)(struct issei_device *idev);
7565f0ecb9SAlexander Usyskin 	int (*irq_write_generate)(struct issei_device *idev);
7665f0ecb9SAlexander Usyskin };
7765f0ecb9SAlexander Usyskin 
7865f0ecb9SAlexander Usyskin /**
7965f0ecb9SAlexander Usyskin  * enum issei_rst_state: driver reset flow states
8065f0ecb9SAlexander Usyskin  * @ISSEI_RST_STATE_INIT: initial state
8165f0ecb9SAlexander Usyskin  * @ISSEI_RST_STATE_HW_READY: waiting for HW to be ready
8265f0ecb9SAlexander Usyskin  * @ISSEI_RST_STATE_SETUP: waiting for channel setup completion
8365f0ecb9SAlexander Usyskin  * @ISSEI_RST_STATE_START: waiting for start handshake completion
8465f0ecb9SAlexander Usyskin  * @ISSEI_RST_STATE_CLIENT_ENUM: waiting for client enumeration
8565f0ecb9SAlexander Usyskin  * @ISSEI_RST_STATE_DONE: reset flow is done
8665f0ecb9SAlexander Usyskin  * @ISSEI_RST_STATE_DISABLED: flow is disabled
8765f0ecb9SAlexander Usyskin  */
8865f0ecb9SAlexander Usyskin enum issei_rst_state {
8965f0ecb9SAlexander Usyskin 	ISSEI_RST_STATE_INIT,
9065f0ecb9SAlexander Usyskin 	ISSEI_RST_STATE_HW_READY,
9165f0ecb9SAlexander Usyskin 	ISSEI_RST_STATE_SETUP,
9265f0ecb9SAlexander Usyskin 	ISSEI_RST_STATE_START,
9365f0ecb9SAlexander Usyskin 	ISSEI_RST_STATE_CLIENT_ENUM,
9465f0ecb9SAlexander Usyskin 	ISSEI_RST_STATE_DONE,
9565f0ecb9SAlexander Usyskin 	ISSEI_RST_STATE_DISABLED,
9665f0ecb9SAlexander Usyskin };
9765f0ecb9SAlexander Usyskin 
9865f0ecb9SAlexander Usyskin /**
9965f0ecb9SAlexander Usyskin  * struct issei_device - issei device
10065f0ecb9SAlexander Usyskin  * @parent: parent device object
10165f0ecb9SAlexander Usyskin  * @dev: associated device object
10265f0ecb9SAlexander Usyskin  * @cdev: character device
10365f0ecb9SAlexander Usyskin  * @minor: allocated minor number
10465f0ecb9SAlexander Usyskin  * @wait_has_data: wait queue for data
10565f0ecb9SAlexander Usyskin  * @has_data: there are data to process
10665f0ecb9SAlexander Usyskin  * @power_down: device is powering down
10765f0ecb9SAlexander Usyskin  * @wait_rst_state: waitqueue for reset state processing
10865f0ecb9SAlexander Usyskin  * @rst_state: reset state
10965f0ecb9SAlexander Usyskin  * @fw_protocol_ver: protocol version
11065f0ecb9SAlexander Usyskin  * @fw_version: firmware version
11165f0ecb9SAlexander Usyskin  * @process_thread: worker thread
11265f0ecb9SAlexander Usyskin  * @reset_count: number of consecutive link reset attempts
11365f0ecb9SAlexander Usyskin  * @all_reset_count: cumilative number of link reset attempts
11465f0ecb9SAlexander Usyskin  * @client_lock: mutex to protect client lists and write queue
11565f0ecb9SAlexander Usyskin  * @host_client_list: host clients list
11665f0ecb9SAlexander Usyskin  * @host_client_last_id: last allocated host client id
11765f0ecb9SAlexander Usyskin  * @host_client_count: number of active host clients
11865f0ecb9SAlexander Usyskin  * @fw_client_list: firmware clients list
11965f0ecb9SAlexander Usyskin  * @write_queue: write queue
12065f0ecb9SAlexander Usyskin  * @last_write_ts: last write timestamp
12165f0ecb9SAlexander Usyskin  * @dma: DMA memory configuration
12265f0ecb9SAlexander Usyskin  * @ops: hardware operations
12365f0ecb9SAlexander Usyskin  * @hw: hw-specific data
12465f0ecb9SAlexander Usyskin  */
12565f0ecb9SAlexander Usyskin struct issei_device {
12665f0ecb9SAlexander Usyskin 	struct device *parent;
12765f0ecb9SAlexander Usyskin 	struct device dev;
12865f0ecb9SAlexander Usyskin 	struct cdev *cdev;
12965f0ecb9SAlexander Usyskin 	u32 minor;
13065f0ecb9SAlexander Usyskin 	wait_queue_head_t wait_has_data;
13165f0ecb9SAlexander Usyskin 	bool has_data;
13265f0ecb9SAlexander Usyskin 	bool power_down;
13365f0ecb9SAlexander Usyskin 	wait_queue_head_t wait_rst_state;
13465f0ecb9SAlexander Usyskin 	enum issei_rst_state rst_state;
13565f0ecb9SAlexander Usyskin 	u16 fw_protocol_ver;
13665f0ecb9SAlexander Usyskin 	u16 fw_version[4];
13765f0ecb9SAlexander Usyskin 	/* reset flow */
13865f0ecb9SAlexander Usyskin 	struct task_struct *process_thread;
13965f0ecb9SAlexander Usyskin 	u8 reset_count;
14065f0ecb9SAlexander Usyskin 	u8 all_reset_count;
14165f0ecb9SAlexander Usyskin 	/* clients */
14265f0ecb9SAlexander Usyskin 	struct mutex client_lock;
14365f0ecb9SAlexander Usyskin 	struct list_head host_client_list;
14465f0ecb9SAlexander Usyskin 	u16 host_client_last_id;
14565f0ecb9SAlexander Usyskin 	u8 host_client_count;
14665f0ecb9SAlexander Usyskin 	struct kset *fw_clients;
14765f0ecb9SAlexander Usyskin 	struct list_head fw_client_list;
14865f0ecb9SAlexander Usyskin 	struct list_head write_queue;
14965f0ecb9SAlexander Usyskin 	ktime_t last_write_ts;
15065f0ecb9SAlexander Usyskin 	struct issei_dma dma;
15165f0ecb9SAlexander Usyskin 	const struct issei_hw_ops *ops;
15265f0ecb9SAlexander Usyskin 	char hw[];
15365f0ecb9SAlexander Usyskin };
15465f0ecb9SAlexander Usyskin 
15565f0ecb9SAlexander Usyskin static inline void issei_poke_process_thread(struct issei_device *idev)
15665f0ecb9SAlexander Usyskin {
15765f0ecb9SAlexander Usyskin 	WRITE_ONCE(idev->has_data, true);
15865f0ecb9SAlexander Usyskin 	wake_up_interruptible(&idev->wait_has_data);
15965f0ecb9SAlexander Usyskin }
160*7bd4b999SAlexander Usyskin 
161*7bd4b999SAlexander Usyskin int issei_start(struct issei_device *idev);
162*7bd4b999SAlexander Usyskin void issei_stop(struct issei_device *idev);
16365f0ecb9SAlexander Usyskin #endif /* _ISSEI_DEV_H_ */
164