| /* SPDX-License-Identifier: GPL-2.0-only */ |
| /* |
| * Most ISHTP provider device and ISHTP logic declarations |
| * |
| * Copyright (c) 2003-2016, Intel Corporation. |
| */ |
| |
| #ifndef _ISHTP_DEV_H_ |
| #define _ISHTP_DEV_H_ |
| |
| #include <linux/types.h> |
| #include <linux/spinlock.h> |
| #include <linux/intel-ish-client-if.h> |
| #include "bus.h" |
| #include "hbm.h" |
| |
| #define IPC_PAYLOAD_SIZE 128 |
| #define ISHTP_RD_MSG_BUF_SIZE IPC_PAYLOAD_SIZE |
| #define IPC_FULL_MSG_SIZE 132 |
| |
| /* Number of messages to be held in ISR->BH FIFO */ |
| #define RD_INT_FIFO_SIZE 64 |
| |
| /* |
| * Number of IPC messages to be held in Tx FIFO, to be sent by ISR - |
| * Tx complete interrupt or RX_COMPLETE handler |
| */ |
| #define IPC_TX_FIFO_SIZE 512 |
| |
| /* |
| * Number of Maximum ISHTP Clients |
| */ |
| #define ISHTP_CLIENTS_MAX 256 |
| |
| /* |
| * Number of File descriptors/handles |
| * that can be opened to the driver. |
| * |
| * Limit to 255: 256 Total Clients |
| * minus internal client for ISHTP Bus Messages |
| */ |
| #define ISHTP_MAX_OPEN_HANDLE_COUNT (ISHTP_CLIENTS_MAX - 1) |
| |
| /* Internal Clients Number */ |
| #define ISHTP_HOST_CLIENT_ID_ANY (-1) |
| #define ISHTP_HBM_HOST_CLIENT_ID 0 |
| |
| #define MAX_DMA_DELAY 20 |
| |
| /* ISHTP device states */ |
| enum ishtp_dev_state { |
| ISHTP_DEV_INITIALIZING = 0, |
| ISHTP_DEV_INIT_CLIENTS, |
| ISHTP_DEV_ENABLED, |
| ISHTP_DEV_RESETTING, |
| ISHTP_DEV_DISABLED, |
| ISHTP_DEV_POWER_DOWN, |
| ISHTP_DEV_POWER_UP |
| }; |
| const char *ishtp_dev_state_str(int state); |
| |
| struct ishtp_cl; |
| |
| /** |
| * struct ishtp_fw_client - representation of fw client |
| * |
| * @props - client properties |
| * @client_id - fw client id |
| */ |
| struct ishtp_fw_client { |
| struct ishtp_client_properties props; |
| uint8_t client_id; |
| }; |
| |
| /* |
| * Control info for IPC messages ISHTP/IPC sending FIFO - |
| * list with inline data buffer |
| * This structure will be filled with parameters submitted |
| * by the caller glue layer |
| * 'buf' may be pointing to the external buffer or to 'inline_data' |
| * 'offset' will be initialized to 0 by submitting |
| * |
| * 'ipc_send_compl' is intended for use by clients that send fragmented |
| * messages. When a fragment is sent down to IPC msg regs, |
| * it will be called. |
| * If it has more fragments to send, it will do it. With last fragment |
| * it will send appropriate ISHTP "message-complete" flag. |
| * It will remove the outstanding message |
| * (mark outstanding buffer as available). |
| * If counting flow control is in work and there are more flow control |
| * credits, it can put the next client message queued in cl. |
| * structure for IPC processing. |
| * |
| */ |
| struct wr_msg_ctl_info { |
| /* Will be called with 'ipc_send_compl_prm' as parameter */ |
| void (*ipc_send_compl)(void *); |
| |
| void *ipc_send_compl_prm; |
| size_t length; |
| struct list_head link; |
| unsigned char inline_data[IPC_FULL_MSG_SIZE]; |
| }; |
| |
| /* |
| * The ISHTP layer talks to hardware IPC message using the following |
| * callbacks |
| */ |
| struct ishtp_hw_ops { |
| int (*hw_reset)(struct ishtp_device *dev); |
| int (*ipc_reset)(struct ishtp_device *dev); |
| uint32_t (*ipc_get_header)(struct ishtp_device *dev, int length, |
| int busy); |
| int (*write)(struct ishtp_device *dev, |
| void (*ipc_send_compl)(void *), void *ipc_send_compl_prm, |
| unsigned char *msg, int length); |
| uint32_t (*ishtp_read_hdr)(const struct ishtp_device *dev); |
| int (*ishtp_read)(struct ishtp_device *dev, unsigned char *buffer, |
| unsigned long buffer_length); |
| uint32_t (*get_fw_status)(struct ishtp_device *dev); |
| void (*sync_fw_clock)(struct ishtp_device *dev); |
| bool (*dma_no_cache_snooping)(struct ishtp_device *dev); |
| }; |
| |
| /** |
| * struct ishtp_driver_data - Driver-specific data for ISHTP devices |
| * |
| * This structure holds driver-specific data that can be associated with each |
| * ISHTP device instance. It allows for the storage of data that is unique to |
| * a particular driver or hardware variant. |
| * |
| * @fw_generation: The generation name associated with a specific hardware |
| * variant of the Intel Integrated Sensor Hub (ISH). This allows |
| * the driver to load the correct firmware based on the device's |
| * hardware variant. For example, "lnlm" for the Lunar Lake-M |
| * platform. The generation name must not exceed 8 characters |
| * in length. |
| */ |
| struct ishtp_driver_data { |
| char *fw_generation; |
| }; |
| |
| /** |
| * struct ishtp_device - ISHTP private device struct |
| */ |
| struct ishtp_device { |
| struct device *devc; /* pointer to lowest device */ |
| struct pci_dev *pdev; /* PCI device to get device ids */ |
| struct ishtp_driver_data *driver_data; /* pointer to driver-specific data */ |
| |
| /* waitq for waiting for suspend response */ |
| wait_queue_head_t suspend_wait; |
| bool suspend_flag; /* Suspend is active */ |
| |
| /* waitq for waiting for resume response */ |
| wait_queue_head_t resume_wait; |
| bool resume_flag; /*Resume is active */ |
| |
| /* |
| * lock for the device, for everything that doesn't have |
| * a dedicated spinlock |
| */ |
| spinlock_t device_lock; |
| |
| bool recvd_hw_ready; |
| struct hbm_version version; |
| int transfer_path; /* Choice of transfer path: IPC or DMA */ |
| |
| /* work structure for scheduling firmware loading tasks */ |
| struct work_struct work_fw_loader; |
| /* waitq for waiting for command response from the firmware loader */ |
| wait_queue_head_t wait_loader_recvd_msg; |
| /* indicating whether a message from the firmware loader has been received */ |
| bool fw_loader_received; |
| /* pointer to a buffer for receiving messages from the firmware loader */ |
| void *fw_loader_rx_buf; |
| /* size of the buffer pointed to by fw_loader_rx_buf */ |
| int fw_loader_rx_size; |
| |
| /* ishtp device states */ |
| enum ishtp_dev_state dev_state; |
| enum ishtp_hbm_state hbm_state; |
| |
| /* driver read queue */ |
| struct ishtp_cl_rb read_list; |
| spinlock_t read_list_spinlock; |
| |
| /* list of ishtp_cl's */ |
| struct list_head cl_list; |
| spinlock_t cl_list_lock; |
| long open_handle_count; |
| |
| /* List of bus devices */ |
| struct list_head device_list; |
| spinlock_t device_list_lock; |
| |
| /* waiting queues for receive message from FW */ |
| wait_queue_head_t wait_hw_ready; |
| wait_queue_head_t wait_hbm_recvd_msg; |
| |
| /* FIFO for input messages for BH processing */ |
| unsigned char rd_msg_fifo[RD_INT_FIFO_SIZE * IPC_PAYLOAD_SIZE]; |
| unsigned int rd_msg_fifo_head, rd_msg_fifo_tail; |
| spinlock_t rd_msg_spinlock; |
| struct work_struct bh_hbm_work; |
| |
| /* IPC write queue */ |
| struct list_head wr_processing_list, wr_free_list; |
| /* For both processing list and free list */ |
| spinlock_t wr_processing_spinlock; |
| |
| struct ishtp_fw_client *fw_clients; /*Note:memory has to be allocated*/ |
| DECLARE_BITMAP(fw_clients_map, ISHTP_CLIENTS_MAX); |
| DECLARE_BITMAP(host_clients_map, ISHTP_CLIENTS_MAX); |
| uint8_t fw_clients_num; |
| uint8_t fw_client_presentation_num; |
| uint8_t fw_client_index; |
| spinlock_t fw_clients_lock; |
| |
| /* TX DMA buffers and slots */ |
| int ishtp_host_dma_enabled; |
| void *ishtp_host_dma_tx_buf; |
| unsigned int ishtp_host_dma_tx_buf_size; |
| uint64_t ishtp_host_dma_tx_buf_phys; |
| int ishtp_dma_num_slots; |
| |
| /* map of 4k blocks in Tx dma buf: 0-free, 1-used */ |
| uint8_t *ishtp_dma_tx_map; |
| spinlock_t ishtp_dma_tx_lock; |
| |
| /* RX DMA buffers and slots */ |
| void *ishtp_host_dma_rx_buf; |
| unsigned int ishtp_host_dma_rx_buf_size; |
| uint64_t ishtp_host_dma_rx_buf_phys; |
| |
| /* Dump to trace buffers if enabled*/ |
| ishtp_print_log print_log; |
| |
| /* Debug stats */ |
| unsigned int ipc_rx_cnt; |
| unsigned long long ipc_rx_bytes_cnt; |
| unsigned int ipc_tx_cnt; |
| unsigned long long ipc_tx_bytes_cnt; |
| |
| const struct ishtp_hw_ops *ops; |
| size_t mtu; |
| uint32_t ishtp_msg_hdr; |
| char hw[] __aligned(sizeof(void *)); |
| }; |
| |
| static inline unsigned long ishtp_secs_to_jiffies(unsigned long sec) |
| { |
| return msecs_to_jiffies(sec * MSEC_PER_SEC); |
| } |
| |
| /* |
| * Register Access Function |
| */ |
| static inline int ish_ipc_reset(struct ishtp_device *dev) |
| { |
| return dev->ops->ipc_reset(dev); |
| } |
| |
| /* Exported function */ |
| void ishtp_device_init(struct ishtp_device *dev); |
| int ishtp_start(struct ishtp_device *dev); |
| |
| #endif /*_ISHTP_DEV_H_*/ |