linux/drivers/hid/intel-ish-hid/ipc/ipc.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * H/W layer of ISHTP provider device (ISH)
 *
 * Copyright (c) 2014-2016, Intel Corporation.
 */

#include <linux/devm-helpers.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
#include "client.h"
#include "hw-ish.h"
#include "hbm.h"

/* For FW reset flow */
static struct work_struct fw_reset_work;
static struct ishtp_device *ishtp_dev;

/**
 * ish_reg_read() - Read register
 * @dev: ISHTP device pointer
 * @offset: Register offset
 *
 * Read 32 bit register at a given offset
 *
 * Return: Read register value
 */
static inline uint32_t ish_reg_read(const struct ishtp_device *dev,
	unsigned long offset)
{}

/**
 * ish_reg_write() - Write register
 * @dev: ISHTP device pointer
 * @offset: Register offset
 * @value: Value to write
 *
 * Writes 32 bit register at a give offset
 */
static inline void ish_reg_write(struct ishtp_device *dev,
				 unsigned long offset,
				 uint32_t value)
{}

/**
 * _ish_read_fw_sts_reg() - Read FW status register
 * @dev: ISHTP device pointer
 *
 * Read FW status register
 *
 * Return: Read register value
 */
static inline uint32_t _ish_read_fw_sts_reg(struct ishtp_device *dev)
{}

/**
 * check_generated_interrupt() - Check if ISH interrupt
 * @dev: ISHTP device pointer
 *
 * Check if an interrupt was generated for ISH
 *
 * Return: Read true or false
 */
static bool check_generated_interrupt(struct ishtp_device *dev)
{}

/**
 * ish_is_input_ready() - Check if FW ready for RX
 * @dev: ISHTP device pointer
 *
 * Check if ISH FW is ready for receiving data
 *
 * Return: Read true or false
 */
static bool ish_is_input_ready(struct ishtp_device *dev)
{}

/**
 * set_host_ready() - Indicate host ready
 * @dev: ISHTP device pointer
 *
 * Set host ready indication to FW
 */
static void set_host_ready(struct ishtp_device *dev)
{}

/**
 * ishtp_fw_is_ready() - Check if FW ready
 * @dev: ISHTP device pointer
 *
 * Check if ISH FW is ready
 *
 * Return: Read true or false
 */
static bool ishtp_fw_is_ready(struct ishtp_device *dev)
{}

/**
 * ish_set_host_rdy() - Indicate host ready
 * @dev: ISHTP device pointer
 *
 * Set host ready indication to FW
 */
static void ish_set_host_rdy(struct ishtp_device *dev)
{}

/**
 * ish_clr_host_rdy() - Indicate host not ready
 * @dev: ISHTP device pointer
 *
 * Send host not ready indication to FW
 */
static void ish_clr_host_rdy(struct ishtp_device *dev)
{}

static bool ish_chk_host_rdy(struct ishtp_device *dev)
{}

/**
 * ish_set_host_ready() - reconfig ipc host registers
 * @dev: ishtp device pointer
 *
 * Set host to ready state
 * This API is called in some case:
 *    fw is still on, but ipc is powered down.
 *    such as OOB case.
 *
 * Return: 0 for success else error fault code
 */
void ish_set_host_ready(struct ishtp_device *dev)
{}

/**
 * _ishtp_read_hdr() - Read message header
 * @dev: ISHTP device pointer
 *
 * Read header of 32bit length
 *
 * Return: Read register value
 */
static uint32_t _ishtp_read_hdr(const struct ishtp_device *dev)
{}

/**
 * _ishtp_read - Read message
 * @dev: ISHTP device pointer
 * @buffer: message buffer
 * @buffer_length: length of message buffer
 *
 * Read message from FW
 *
 * Return: Always 0
 */
static int _ishtp_read(struct ishtp_device *dev, unsigned char *buffer,
	unsigned long buffer_length)
{}

/**
 * write_ipc_from_queue() - try to write ipc msg from Tx queue to device
 * @dev: ishtp device pointer
 *
 * Check if DRBL is cleared. if it is - write the first IPC msg,  then call
 * the callback function (unless it's NULL)
 *
 * Return: 0 for success else failure code
 */
static int write_ipc_from_queue(struct ishtp_device *dev)
{}

/**
 * write_ipc_to_queue() - write ipc msg to Tx queue
 * @dev: ishtp device instance
 * @ipc_send_compl: Send complete callback
 * @ipc_send_compl_prm:	Parameter to send in complete callback
 * @msg: Pointer to message
 * @length: Length of message
 *
 * Recived msg with IPC (and upper protocol) header  and add it to the device
 *  Tx-to-write list then try to send the first IPC waiting msg
 *  (if DRBL is cleared)
 * This function returns negative value for failure (means free list
 *  is empty, or msg too long) and 0 for success.
 *
 * Return: 0 for success else failure code
 */
static int write_ipc_to_queue(struct ishtp_device *dev,
	void (*ipc_send_compl)(void *), void *ipc_send_compl_prm,
	unsigned char *msg, int length)
{}

/**
 * ipc_send_mng_msg() - Send management message
 * @dev: ishtp device instance
 * @msg_code: Message code
 * @msg: Pointer to message
 * @size: Length of message
 *
 * Send management message to FW
 *
 * Return: 0 for success else failure code
 */
static int ipc_send_mng_msg(struct ishtp_device *dev, uint32_t msg_code,
	void *msg, size_t size)
{}

#define WAIT_FOR_FW_RDY
#define WAIT_FOR_INPUT_RDY

/**
 * timed_wait_for_timeout() - wait special event with timeout
 * @dev: ISHTP device pointer
 * @condition: indicate the condition for waiting
 * @timeinc: time slice for every wait cycle, in ms
 * @timeout: time in ms for timeout
 *
 * This function will check special event to be ready in a loop, the loop
 * period is specificd in timeinc. Wait timeout will causes failure.
 *
 * Return: 0 for success else failure code
 */
static int timed_wait_for_timeout(struct ishtp_device *dev, int condition,
				unsigned int timeinc, unsigned int timeout)
{}

#define TIME_SLICE_FOR_FW_RDY_MS
#define TIME_SLICE_FOR_INPUT_RDY_MS
#define TIMEOUT_FOR_FW_RDY_MS
#define TIMEOUT_FOR_INPUT_RDY_MS

/**
 * ish_fw_reset_handler() - FW reset handler
 * @dev: ishtp device pointer
 *
 * Handle FW reset
 *
 * Return: 0 for success else failure code
 */
static int ish_fw_reset_handler(struct ishtp_device *dev)
{}

#define TIMEOUT_FOR_HW_RDY_MS

/**
 * fw_reset_work_fn() - FW reset worker function
 * @work: Work item
 *
 * Call ish_fw_reset_handler to complete FW reset
 */
static void fw_reset_work_fn(struct work_struct *work)
{}

/**
 * _ish_sync_fw_clock() -Sync FW clock with the OS clock
 * @dev: ishtp device pointer
 *
 * Sync FW and OS time
 */
static void _ish_sync_fw_clock(struct ishtp_device *dev)
{}

/**
 * recv_ipc() - Receive and process IPC management messages
 * @dev: ishtp device instance
 * @doorbell_val: doorbell value
 *
 * This function runs in ISR context.
 * NOTE: Any other mng command than reset_notify and reset_notify_ack
 * won't wake BH handler
 */
static void	recv_ipc(struct ishtp_device *dev, uint32_t doorbell_val)
{}

/**
 * ish_irq_handler() - ISH IRQ handler
 * @irq: irq number
 * @dev_id: ishtp device pointer
 *
 * ISH IRQ handler. If interrupt is generated and is for ISH it will process
 * the interrupt.
 */
irqreturn_t ish_irq_handler(int irq, void *dev_id)
{}

/**
 * ish_disable_dma() - disable dma communication between host and ISHFW
 * @dev: ishtp device pointer
 *
 * Clear the dma enable bit and wait for dma inactive.
 *
 * Return: 0 for success else error code.
 */
int ish_disable_dma(struct ishtp_device *dev)
{}

/**
 * ish_wakeup() - wakeup ishfw from waiting-for-host state
 * @dev: ishtp device pointer
 *
 * Set the dma enable bit and send a void message to FW,
 * it wil wakeup FW from waiting-for-host state.
 */
static void ish_wakeup(struct ishtp_device *dev)
{}

/**
 * _ish_hw_reset() - HW reset
 * @dev: ishtp device pointer
 *
 * Reset ISH HW to recover if any error
 *
 * Return: 0 for success else error fault code
 */
static int _ish_hw_reset(struct ishtp_device *dev)
{}

/**
 * _ish_ipc_reset() - IPC reset
 * @dev: ishtp device pointer
 *
 * Resets host and fw IPC and upper layers
 *
 * Return: 0 for success else error fault code
 */
static int _ish_ipc_reset(struct ishtp_device *dev)
{}

/**
 * ish_hw_start() -Start ISH HW
 * @dev: ishtp device pointer
 *
 * Set host to ready state and wait for FW reset
 *
 * Return: 0 for success else error fault code
 */
int ish_hw_start(struct ishtp_device *dev)
{}

/**
 * ish_ipc_get_header() -Get doorbell value
 * @dev: ishtp device pointer
 * @length: length of message
 * @busy: busy status
 *
 * Get door bell value from message header
 *
 * Return: door bell value
 */
static uint32_t ish_ipc_get_header(struct ishtp_device *dev, int length,
				   int busy)
{}

/**
 * _dma_no_cache_snooping()
 *
 * Check on current platform, DMA supports cache snooping or not.
 * This callback is used to notify uplayer driver if manully cache
 * flush is needed when do DMA operation.
 *
 * Please pay attention to this callback implementation, if declare
 * having cache snooping on a cache snooping not supported platform
 * will cause uplayer driver receiving mismatched data; and if
 * declare no cache snooping on a cache snooping supported platform
 * will cause cache be flushed twice and performance hit.
 *
 * @dev: ishtp device pointer
 *
 * Return: false - has cache snooping capability
 *         true - no cache snooping, need manually cache flush
 */
static bool _dma_no_cache_snooping(struct ishtp_device *dev)
{}

static const struct ishtp_hw_ops ish_hw_ops =;

/**
 * ish_dev_init() -Initialize ISH devoce
 * @pdev: PCI device
 *
 * Allocate ISHTP device and initialize IPC processing
 *
 * Return: ISHTP device instance on success else NULL
 */
struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
{}

/**
 * ish_device_disable() - Disable ISH device
 * @dev: ISHTP device pointer
 *
 * Disable ISH by clearing host ready to inform firmware.
 */
void	ish_device_disable(struct ishtp_device *dev)
{}