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