^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * H/W layer of ISHTP provider device (ISH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2014-2016, Intel Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "client.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "hw-ish.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "hbm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /* For FW reset flow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static struct work_struct fw_reset_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static struct ishtp_device *ishtp_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * ish_reg_read() - Read register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * @dev: ISHTP device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * @offset: Register offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * Read 32 bit register at a given offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * Return: Read register value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static inline uint32_t ish_reg_read(const struct ishtp_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) unsigned long offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct ish_hw *hw = to_ish_hw(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return readl(hw->mem_addr + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * ish_reg_write() - Write register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * @dev: ISHTP device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * @offset: Register offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * @value: Value to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * Writes 32 bit register at a give offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static inline void ish_reg_write(struct ishtp_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) unsigned long offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) uint32_t value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct ish_hw *hw = to_ish_hw(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) writel(value, hw->mem_addr + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * _ish_read_fw_sts_reg() - Read FW status register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * @dev: ISHTP device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * Read FW status register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * Return: Read register value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static inline uint32_t _ish_read_fw_sts_reg(struct ishtp_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * check_generated_interrupt() - Check if ISH interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * @dev: ISHTP device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * Check if an interrupt was generated for ISH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * Return: Read true or false
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static bool check_generated_interrupt(struct ishtp_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) bool interrupt_generated = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) uint32_t pisr_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (dev->pdev->device == CHV_DEVICE_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) pisr_val = ish_reg_read(dev, IPC_REG_PISR_CHV_AB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) interrupt_generated =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) IPC_INT_FROM_ISH_TO_HOST_CHV_AB(pisr_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) pisr_val = ish_reg_read(dev, IPC_REG_PISR_BXT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) interrupt_generated = !!pisr_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* only busy-clear bit is RW, others are RO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (pisr_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) ish_reg_write(dev, IPC_REG_PISR_BXT, pisr_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return interrupt_generated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * ish_is_input_ready() - Check if FW ready for RX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * @dev: ISHTP device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * Check if ISH FW is ready for receiving data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * Return: Read true or false
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static bool ish_is_input_ready(struct ishtp_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) uint32_t doorbell_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) doorbell_val = ish_reg_read(dev, IPC_REG_HOST2ISH_DRBL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return !IPC_IS_BUSY(doorbell_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * set_host_ready() - Indicate host ready
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * @dev: ISHTP device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * Set host ready indication to FW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static void set_host_ready(struct ishtp_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (dev->pdev->device == CHV_DEVICE_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (dev->pdev->revision == REVISION_ID_CHT_A0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) (dev->pdev->revision & REVISION_ID_SI_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) REVISION_ID_CHT_Ax_SI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) ish_reg_write(dev, IPC_REG_HOST_COMM, 0x81);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) else if (dev->pdev->revision == REVISION_ID_CHT_B0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) (dev->pdev->revision & REVISION_ID_SI_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) REVISION_ID_CHT_Bx_SI ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) (dev->pdev->revision & REVISION_ID_SI_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) REVISION_ID_CHT_Kx_SI ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) (dev->pdev->revision & REVISION_ID_SI_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) REVISION_ID_CHT_Dx_SI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) uint32_t host_comm_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) host_comm_val = ish_reg_read(dev, IPC_REG_HOST_COMM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) host_comm_val |= IPC_HOSTCOMM_INT_EN_BIT_CHV_AB | 0x81;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) ish_reg_write(dev, IPC_REG_HOST_COMM, host_comm_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) uint32_t host_pimr_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) host_pimr_val = ish_reg_read(dev, IPC_REG_PIMR_BXT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) host_pimr_val |= IPC_PIMR_INT_EN_BIT_BXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * disable interrupt generated instead of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * RX_complete_msg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) host_pimr_val &= ~IPC_HOST2ISH_BUSYCLEAR_MASK_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ish_reg_write(dev, IPC_REG_PIMR_BXT, host_pimr_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * ishtp_fw_is_ready() - Check if FW ready
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * @dev: ISHTP device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * Check if ISH FW is ready
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * Return: Read true or false
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static bool ishtp_fw_is_ready(struct ishtp_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) uint32_t ish_status = _ish_read_fw_sts_reg(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return IPC_IS_ISH_ILUP(ish_status) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) IPC_IS_ISH_ISHTP_READY(ish_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * ish_set_host_rdy() - Indicate host ready
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * @dev: ISHTP device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * Set host ready indication to FW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static void ish_set_host_rdy(struct ishtp_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) uint32_t host_status = ish_reg_read(dev, IPC_REG_HOST_COMM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) IPC_SET_HOST_READY(host_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ish_reg_write(dev, IPC_REG_HOST_COMM, host_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * ish_clr_host_rdy() - Indicate host not ready
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * @dev: ISHTP device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * Send host not ready indication to FW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static void ish_clr_host_rdy(struct ishtp_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) uint32_t host_status = ish_reg_read(dev, IPC_REG_HOST_COMM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) IPC_CLEAR_HOST_READY(host_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) ish_reg_write(dev, IPC_REG_HOST_COMM, host_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * _ishtp_read_hdr() - Read message header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * @dev: ISHTP device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * Read header of 32bit length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * Return: Read register value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static uint32_t _ishtp_read_hdr(const struct ishtp_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return ish_reg_read(dev, IPC_REG_ISH2HOST_MSG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * _ishtp_read - Read message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * @dev: ISHTP device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * @buffer: message buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * @buffer_length: length of message buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * Read message from FW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * Return: Always 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static int _ishtp_read(struct ishtp_device *dev, unsigned char *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) unsigned long buffer_length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) uint32_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) uint32_t *r_buf = (uint32_t *)buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) uint32_t msg_offs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) msg_offs = IPC_REG_ISH2HOST_MSG + sizeof(struct ishtp_msg_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) for (i = 0; i < buffer_length; i += sizeof(uint32_t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) *r_buf++ = ish_reg_read(dev, msg_offs + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * write_ipc_from_queue() - try to write ipc msg from Tx queue to device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * @dev: ishtp device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * Check if DRBL is cleared. if it is - write the first IPC msg, then call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * the callback function (unless it's NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * Return: 0 for success else failure code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static int write_ipc_from_queue(struct ishtp_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) struct wr_msg_ctl_info *ipc_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) unsigned long length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) unsigned long rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) uint32_t doorbell_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) uint32_t *r_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) uint32_t reg_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) void (*ipc_send_compl)(void *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) void *ipc_send_compl_prm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (dev->dev_state == ISHTP_DEV_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) spin_lock_irqsave(&dev->wr_processing_spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (!ish_is_input_ready(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * if tx send list is empty - return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * may happen, as RX_COMPLETE handler doesn't check list emptiness.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (list_empty(&dev->wr_processing_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) ipc_link = list_first_entry(&dev->wr_processing_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct wr_msg_ctl_info, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /* first 4 bytes of the data is the doorbell value (IPC header) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) length = ipc_link->length - sizeof(uint32_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) doorbell_val = *(uint32_t *)ipc_link->inline_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) r_buf = (uint32_t *)(ipc_link->inline_data + sizeof(uint32_t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /* If sending MNG_SYNC_FW_CLOCK, update clock again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (IPC_HEADER_GET_PROTOCOL(doorbell_val) == IPC_PROTOCOL_MNG &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) IPC_HEADER_GET_MNG_CMD(doorbell_val) == MNG_SYNC_FW_CLOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) uint64_t usec_system, usec_utc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) struct ipc_time_update_msg time_update;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct time_sync_format ts_format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) usec_system = ktime_to_us(ktime_get_boottime());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) usec_utc = ktime_to_us(ktime_get_real());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) ts_format.ts1_source = HOST_SYSTEM_TIME_USEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ts_format.ts2_source = HOST_UTC_TIME_USEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) ts_format.reserved = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) time_update.primary_host_time = usec_system;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) time_update.secondary_host_time = usec_utc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) time_update.sync_info = ts_format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) memcpy(r_buf, &time_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) sizeof(struct ipc_time_update_msg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) for (i = 0, reg_addr = IPC_REG_HOST2ISH_MSG; i < length >> 2; i++,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) reg_addr += 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) ish_reg_write(dev, reg_addr, r_buf[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) rem = length & 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (rem > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) uint32_t reg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) memcpy(®, &r_buf[length >> 2], rem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) ish_reg_write(dev, reg_addr, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, doorbell_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* Flush writes to msg registers and doorbell */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) /* Update IPC counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) ++dev->ipc_tx_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) dev->ipc_tx_bytes_cnt += IPC_HEADER_GET_LENGTH(doorbell_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) ipc_send_compl = ipc_link->ipc_send_compl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) ipc_send_compl_prm = ipc_link->ipc_send_compl_prm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) list_del_init(&ipc_link->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) list_add(&ipc_link->link, &dev->wr_free_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) * callback will be called out of spinlock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) * after ipc_link returned to free list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (ipc_send_compl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) ipc_send_compl(ipc_send_compl_prm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * write_ipc_to_queue() - write ipc msg to Tx queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * @dev: ishtp device instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * @ipc_send_compl: Send complete callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * @ipc_send_compl_prm: Parameter to send in complete callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * @msg: Pointer to message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * @length: Length of message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) * Recived msg with IPC (and upper protocol) header and add it to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * Tx-to-write list then try to send the first IPC waiting msg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * (if DRBL is cleared)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * This function returns negative value for failure (means free list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * is empty, or msg too long) and 0 for success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * Return: 0 for success else failure code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static int write_ipc_to_queue(struct ishtp_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) void (*ipc_send_compl)(void *), void *ipc_send_compl_prm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) unsigned char *msg, int length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct wr_msg_ctl_info *ipc_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (length > IPC_FULL_MSG_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) spin_lock_irqsave(&dev->wr_processing_spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (list_empty(&dev->wr_free_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) ipc_link = list_first_entry(&dev->wr_free_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct wr_msg_ctl_info, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) list_del_init(&ipc_link->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) ipc_link->ipc_send_compl = ipc_send_compl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) ipc_link->ipc_send_compl_prm = ipc_send_compl_prm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) ipc_link->length = length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) memcpy(ipc_link->inline_data, msg, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) list_add_tail(&ipc_link->link, &dev->wr_processing_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) write_ipc_from_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * ipc_send_mng_msg() - Send management message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * @dev: ishtp device instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) * @msg_code: Message code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * @msg: Pointer to message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) * @size: Length of message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * Send management message to FW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * Return: 0 for success else failure code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static int ipc_send_mng_msg(struct ishtp_device *dev, uint32_t msg_code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) void *msg, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) unsigned char ipc_msg[IPC_FULL_MSG_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) uint32_t drbl_val = IPC_BUILD_MNG_MSG(msg_code, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) memcpy(ipc_msg, &drbl_val, sizeof(uint32_t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) memcpy(ipc_msg + sizeof(uint32_t), msg, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) return write_ipc_to_queue(dev, NULL, NULL, ipc_msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) sizeof(uint32_t) + size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) #define WAIT_FOR_FW_RDY 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) #define WAIT_FOR_INPUT_RDY 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * timed_wait_for_timeout() - wait special event with timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * @dev: ISHTP device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * @condition: indicate the condition for waiting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * @timeinc: time slice for every wait cycle, in ms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * @timeout: time in ms for timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * This function will check special event to be ready in a loop, the loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * period is specificd in timeinc. Wait timeout will causes failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * Return: 0 for success else failure code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) static int timed_wait_for_timeout(struct ishtp_device *dev, int condition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) unsigned int timeinc, unsigned int timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) bool complete = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (condition == WAIT_FOR_FW_RDY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) complete = ishtp_fw_is_ready(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) } else if (condition == WAIT_FOR_INPUT_RDY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) complete = ish_is_input_ready(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (!complete) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) unsigned long left_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) left_time = msleep_interruptible(timeinc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) timeout -= (timeinc - left_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) } while (!complete && timeout > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (complete)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) #define TIME_SLICE_FOR_FW_RDY_MS 100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) #define TIME_SLICE_FOR_INPUT_RDY_MS 100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) #define TIMEOUT_FOR_FW_RDY_MS 2000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) #define TIMEOUT_FOR_INPUT_RDY_MS 2000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) * ish_fw_reset_handler() - FW reset handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) * @dev: ishtp device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * Handle FW reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * Return: 0 for success else failure code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) static int ish_fw_reset_handler(struct ishtp_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) uint32_t reset_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /* Read reset ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) reset_id = ish_reg_read(dev, IPC_REG_ISH2HOST_MSG) & 0xFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /* Clear IPC output queue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) spin_lock_irqsave(&dev->wr_processing_spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) list_splice_init(&dev->wr_processing_list, &dev->wr_free_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /* ISHTP notification in IPC_RESET */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) ishtp_reset_handler(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (!ish_is_input_ready(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) timed_wait_for_timeout(dev, WAIT_FOR_INPUT_RDY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) TIME_SLICE_FOR_INPUT_RDY_MS, TIMEOUT_FOR_INPUT_RDY_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /* ISH FW is dead */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (!ish_is_input_ready(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return -EPIPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) * Set HOST2ISH.ILUP. Apparently we need this BEFORE sending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * RESET_NOTIFY_ACK - FW will be checking for it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) ish_set_host_rdy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) /* Send RESET_NOTIFY_ACK (with reset_id) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) ipc_send_mng_msg(dev, MNG_RESET_NOTIFY_ACK, &reset_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) sizeof(uint32_t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) /* Wait for ISH FW'es ILUP and ISHTP_READY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) timed_wait_for_timeout(dev, WAIT_FOR_FW_RDY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) TIME_SLICE_FOR_FW_RDY_MS, TIMEOUT_FOR_FW_RDY_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (!ishtp_fw_is_ready(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) /* ISH FW is dead */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) uint32_t ish_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) ish_status = _ish_read_fw_sts_reg(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) dev_err(dev->devc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) "[ishtp-ish]: completed reset, ISH is dead (FWSTS = %08X)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) ish_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) #define TIMEOUT_FOR_HW_RDY_MS 300
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) * ish_fw_reset_work_fn() - FW reset worker function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) * @unused: not used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * Call ish_fw_reset_handler to complete FW reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static void fw_reset_work_fn(struct work_struct *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) rv = ish_fw_reset_handler(ishtp_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (!rv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) /* ISH is ILUP & ISHTP-ready. Restart ISHTP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) msleep_interruptible(TIMEOUT_FOR_HW_RDY_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) ishtp_dev->recvd_hw_ready = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) wake_up_interruptible(&ishtp_dev->wait_hw_ready);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) /* ISHTP notification in IPC_RESET sequence completion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) ishtp_reset_compl_handler(ishtp_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) dev_err(ishtp_dev->devc, "[ishtp-ish]: FW reset failed (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) rv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) * _ish_sync_fw_clock() -Sync FW clock with the OS clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) * @dev: ishtp device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) * Sync FW and OS time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) static void _ish_sync_fw_clock(struct ishtp_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) static unsigned long prev_sync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) uint64_t usec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (prev_sync && jiffies - prev_sync < 20 * HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) prev_sync = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) usec = ktime_to_us(ktime_get_boottime());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) ipc_send_mng_msg(dev, MNG_SYNC_FW_CLOCK, &usec, sizeof(uint64_t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) * recv_ipc() - Receive and process IPC management messages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) * @dev: ishtp device instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) * @doorbell_val: doorbell value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) * This function runs in ISR context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) * NOTE: Any other mng command than reset_notify and reset_notify_ack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * won't wake BH handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) static void recv_ipc(struct ishtp_device *dev, uint32_t doorbell_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) uint32_t mng_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) mng_cmd = IPC_HEADER_GET_MNG_CMD(doorbell_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) switch (mng_cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) case MNG_RX_CMPL_INDICATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) if (dev->suspend_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) dev->suspend_flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) wake_up_interruptible(&dev->suspend_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (dev->resume_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) dev->resume_flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) wake_up_interruptible(&dev->resume_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) write_ipc_from_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) case MNG_RESET_NOTIFY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (!ishtp_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) ishtp_dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) INIT_WORK(&fw_reset_work, fw_reset_work_fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) schedule_work(&fw_reset_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) case MNG_RESET_NOTIFY_ACK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) dev->recvd_hw_ready = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) wake_up_interruptible(&dev->wait_hw_ready);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) * ish_irq_handler() - ISH IRQ handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * @irq: irq number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * @dev_id: ishtp device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * ISH IRQ handler. If interrupt is generated and is for ISH it will process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * the interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) irqreturn_t ish_irq_handler(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) struct ishtp_device *dev = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) uint32_t doorbell_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) bool interrupt_generated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) /* Check that it's interrupt from ISH (may be shared) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) interrupt_generated = check_generated_interrupt(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (!interrupt_generated)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) doorbell_val = ish_reg_read(dev, IPC_REG_ISH2HOST_DRBL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (!IPC_IS_BUSY(doorbell_val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (dev->dev_state == ISHTP_DEV_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) /* Sanity check: IPC dgram length in header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (IPC_HEADER_GET_LENGTH(doorbell_val) > IPC_PAYLOAD_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) dev_err(dev->devc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) "IPC hdr - bad length: %u; dropped\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) (unsigned int)IPC_HEADER_GET_LENGTH(doorbell_val));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) goto eoi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) switch (IPC_HEADER_GET_PROTOCOL(doorbell_val)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) case IPC_PROTOCOL_MNG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) recv_ipc(dev, doorbell_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) case IPC_PROTOCOL_ISHTP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) ishtp_recv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) eoi:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /* Update IPC counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) ++dev->ipc_rx_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) dev->ipc_rx_bytes_cnt += IPC_HEADER_GET_LENGTH(doorbell_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) ish_reg_write(dev, IPC_REG_ISH2HOST_DRBL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) /* Flush write to doorbell */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * ish_disable_dma() - disable dma communication between host and ISHFW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * @dev: ishtp device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * Clear the dma enable bit and wait for dma inactive.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * Return: 0 for success else error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) int ish_disable_dma(struct ishtp_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) unsigned int dma_delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) /* Clear the dma enable bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) ish_reg_write(dev, IPC_REG_ISH_RMP2, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) /* wait for dma inactive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) for (dma_delay = 0; dma_delay < MAX_DMA_DELAY &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) _ish_read_fw_sts_reg(dev) & (IPC_ISH_IN_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) dma_delay += 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) mdelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (dma_delay >= MAX_DMA_DELAY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) dev_err(dev->devc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) "Wait for DMA inactive timeout\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * ish_wakeup() - wakeup ishfw from waiting-for-host state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) * @dev: ishtp device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * Set the dma enable bit and send a void message to FW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * it wil wakeup FW from waiting-for-host state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) static void ish_wakeup(struct ishtp_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) /* Set dma enable bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) ish_reg_write(dev, IPC_REG_ISH_RMP2, IPC_RMP2_DMA_ENABLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) * Send 0 IPC message so that ISH FW wakes up if it was already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) * asleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, IPC_DRBL_BUSY_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) /* Flush writes to doorbell and REMAP2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * _ish_hw_reset() - HW reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * @dev: ishtp device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) * Reset ISH HW to recover if any error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) * Return: 0 for success else error fault code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) static int _ish_hw_reset(struct ishtp_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) struct pci_dev *pdev = dev->pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) int rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) uint16_t csr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (!pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) rv = pci_reset_function(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (!rv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) dev->dev_state = ISHTP_DEV_RESETTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (!pdev->pm_cap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) dev_err(&pdev->dev, "Can't reset - no PM caps\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) /* Disable dma communication between FW and host */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (ish_disable_dma(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) "Can't reset - stuck with DMA in-progress\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &csr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) csr &= ~PCI_PM_CTRL_STATE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) csr |= PCI_D3hot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, csr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) mdelay(pdev->d3hot_delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) csr &= ~PCI_PM_CTRL_STATE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) csr |= PCI_D0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, csr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) /* Now we can enable ISH DMA operation and wakeup ISHFW */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) ish_wakeup(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) * _ish_ipc_reset() - IPC reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) * @dev: ishtp device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) * Resets host and fw IPC and upper layers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) * Return: 0 for success else error fault code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) static int _ish_ipc_reset(struct ishtp_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) struct ipc_rst_payload_type ipc_mng_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) int rv = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) ipc_mng_msg.reset_id = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) ipc_mng_msg.reserved = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) set_host_ready(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) /* Clear the incoming doorbell */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) ish_reg_write(dev, IPC_REG_ISH2HOST_DRBL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) /* Flush write to doorbell */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) dev->recvd_hw_ready = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) /* send message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) rv = ipc_send_mng_msg(dev, MNG_RESET_NOTIFY, &ipc_mng_msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) sizeof(struct ipc_rst_payload_type));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (rv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) dev_err(dev->devc, "Failed to send IPC MNG_RESET_NOTIFY\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) wait_event_interruptible_timeout(dev->wait_hw_ready,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) dev->recvd_hw_ready, 2 * HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (!dev->recvd_hw_ready) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) dev_err(dev->devc, "Timed out waiting for HW ready\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) rv = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) * ish_hw_start() -Start ISH HW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) * @dev: ishtp device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) * Set host to ready state and wait for FW reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) * Return: 0 for success else error fault code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) int ish_hw_start(struct ishtp_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) ish_set_host_rdy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) set_host_ready(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) /* After that we can enable ISH DMA operation and wakeup ISHFW */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) ish_wakeup(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) /* wait for FW-initiated reset flow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (!dev->recvd_hw_ready)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) wait_event_interruptible_timeout(dev->wait_hw_ready,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) dev->recvd_hw_ready,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) 10 * HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (!dev->recvd_hw_ready) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) dev_err(dev->devc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) "[ishtp-ish]: Timed out waiting for FW-initiated reset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * ish_ipc_get_header() -Get doorbell value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * @dev: ishtp device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * @length: length of message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * @busy: busy status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) * Get door bell value from message header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) * Return: door bell value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) static uint32_t ish_ipc_get_header(struct ishtp_device *dev, int length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) int busy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) uint32_t drbl_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) drbl_val = IPC_BUILD_HEADER(length, IPC_PROTOCOL_ISHTP, busy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return drbl_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) static const struct ishtp_hw_ops ish_hw_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) .hw_reset = _ish_hw_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) .ipc_reset = _ish_ipc_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) .ipc_get_header = ish_ipc_get_header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) .ishtp_read = _ishtp_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) .write = write_ipc_to_queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) .get_fw_status = _ish_read_fw_sts_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) .sync_fw_clock = _ish_sync_fw_clock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) .ishtp_read_hdr = _ishtp_read_hdr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) * ish_dev_init() -Initialize ISH devoce
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) * @pdev: PCI device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) * Allocate ISHTP device and initialize IPC processing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) * Return: ISHTP device instance on success else NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) struct ishtp_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) dev = devm_kzalloc(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) sizeof(struct ishtp_device) + sizeof(struct ish_hw),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) ishtp_device_init(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) init_waitqueue_head(&dev->wait_hw_ready);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) spin_lock_init(&dev->wr_processing_spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /* Init IPC processing and free lists */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) INIT_LIST_HEAD(&dev->wr_processing_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) INIT_LIST_HEAD(&dev->wr_free_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) for (i = 0; i < IPC_TX_FIFO_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) struct wr_msg_ctl_info *tx_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) tx_buf = devm_kzalloc(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) sizeof(struct wr_msg_ctl_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if (!tx_buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) * IPC buffers may be limited or not available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) * at all - although this shouldn't happen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) dev_err(dev->devc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) "[ishtp-ish]: failure in Tx FIFO allocations (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) list_add_tail(&tx_buf->link, &dev->wr_free_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) dev->ops = &ish_hw_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) dev->devc = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) dev->mtu = IPC_PAYLOAD_SIZE - sizeof(struct ishtp_msg_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) return dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) * ish_device_disable() - Disable ISH device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) * @dev: ISHTP device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) * Disable ISH by clearing host ready to inform firmware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) void ish_device_disable(struct ishtp_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) struct pci_dev *pdev = dev->pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) if (!pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) /* Disable dma communication between FW and host */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) if (ish_disable_dma(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) "Can't reset - stuck with DMA in-progress\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) /* Put ISH to D3hot state for power saving */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) pci_set_power_state(pdev, PCI_D3hot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) dev->dev_state = ISHTP_DEV_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) ish_clr_host_rdy(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) }