Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * H/W layer of ISHTP provider device (ISH)
0004  *
0005  * Copyright (c) 2014-2016, Intel Corporation.
0006  */
0007 
0008 #include <linux/sched.h>
0009 #include <linux/spinlock.h>
0010 #include <linux/delay.h>
0011 #include <linux/jiffies.h>
0012 #include "client.h"
0013 #include "hw-ish.h"
0014 #include "hbm.h"
0015 
0016 /* For FW reset flow */
0017 static struct work_struct fw_reset_work;
0018 static struct ishtp_device *ishtp_dev;
0019 
0020 /**
0021  * ish_reg_read() - Read register
0022  * @dev: ISHTP device pointer
0023  * @offset: Register offset
0024  *
0025  * Read 32 bit register at a given offset
0026  *
0027  * Return: Read register value
0028  */
0029 static inline uint32_t ish_reg_read(const struct ishtp_device *dev,
0030     unsigned long offset)
0031 {
0032     struct ish_hw *hw = to_ish_hw(dev);
0033 
0034     return readl(hw->mem_addr + offset);
0035 }
0036 
0037 /**
0038  * ish_reg_write() - Write register
0039  * @dev: ISHTP device pointer
0040  * @offset: Register offset
0041  * @value: Value to write
0042  *
0043  * Writes 32 bit register at a give offset
0044  */
0045 static inline void ish_reg_write(struct ishtp_device *dev,
0046                  unsigned long offset,
0047                  uint32_t value)
0048 {
0049     struct ish_hw *hw = to_ish_hw(dev);
0050 
0051     writel(value, hw->mem_addr + offset);
0052 }
0053 
0054 /**
0055  * _ish_read_fw_sts_reg() - Read FW status register
0056  * @dev: ISHTP device pointer
0057  *
0058  * Read FW status register
0059  *
0060  * Return: Read register value
0061  */
0062 static inline uint32_t _ish_read_fw_sts_reg(struct ishtp_device *dev)
0063 {
0064     return ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS);
0065 }
0066 
0067 /**
0068  * check_generated_interrupt() - Check if ISH interrupt
0069  * @dev: ISHTP device pointer
0070  *
0071  * Check if an interrupt was generated for ISH
0072  *
0073  * Return: Read true or false
0074  */
0075 static bool check_generated_interrupt(struct ishtp_device *dev)
0076 {
0077     bool interrupt_generated = true;
0078     uint32_t pisr_val = 0;
0079 
0080     if (dev->pdev->device == CHV_DEVICE_ID) {
0081         pisr_val = ish_reg_read(dev, IPC_REG_PISR_CHV_AB);
0082         interrupt_generated =
0083             IPC_INT_FROM_ISH_TO_HOST_CHV_AB(pisr_val);
0084     } else {
0085         pisr_val = ish_reg_read(dev, IPC_REG_PISR_BXT);
0086         interrupt_generated = !!pisr_val;
0087         /* only busy-clear bit is RW, others are RO */
0088         if (pisr_val)
0089             ish_reg_write(dev, IPC_REG_PISR_BXT, pisr_val);
0090     }
0091 
0092     return interrupt_generated;
0093 }
0094 
0095 /**
0096  * ish_is_input_ready() - Check if FW ready for RX
0097  * @dev: ISHTP device pointer
0098  *
0099  * Check if ISH FW is ready for receiving data
0100  *
0101  * Return: Read true or false
0102  */
0103 static bool ish_is_input_ready(struct ishtp_device *dev)
0104 {
0105     uint32_t doorbell_val;
0106 
0107     doorbell_val = ish_reg_read(dev, IPC_REG_HOST2ISH_DRBL);
0108     return !IPC_IS_BUSY(doorbell_val);
0109 }
0110 
0111 /**
0112  * set_host_ready() - Indicate host ready
0113  * @dev: ISHTP device pointer
0114  *
0115  * Set host ready indication to FW
0116  */
0117 static void set_host_ready(struct ishtp_device *dev)
0118 {
0119     if (dev->pdev->device == CHV_DEVICE_ID) {
0120         if (dev->pdev->revision == REVISION_ID_CHT_A0 ||
0121                 (dev->pdev->revision & REVISION_ID_SI_MASK) ==
0122                 REVISION_ID_CHT_Ax_SI)
0123             ish_reg_write(dev, IPC_REG_HOST_COMM, 0x81);
0124         else if (dev->pdev->revision == REVISION_ID_CHT_B0 ||
0125                 (dev->pdev->revision & REVISION_ID_SI_MASK) ==
0126                 REVISION_ID_CHT_Bx_SI ||
0127                 (dev->pdev->revision & REVISION_ID_SI_MASK) ==
0128                 REVISION_ID_CHT_Kx_SI ||
0129                 (dev->pdev->revision & REVISION_ID_SI_MASK) ==
0130                 REVISION_ID_CHT_Dx_SI) {
0131             uint32_t host_comm_val;
0132 
0133             host_comm_val = ish_reg_read(dev, IPC_REG_HOST_COMM);
0134             host_comm_val |= IPC_HOSTCOMM_INT_EN_BIT_CHV_AB | 0x81;
0135             ish_reg_write(dev, IPC_REG_HOST_COMM, host_comm_val);
0136         }
0137     } else {
0138             uint32_t host_pimr_val;
0139 
0140             host_pimr_val = ish_reg_read(dev, IPC_REG_PIMR_BXT);
0141             host_pimr_val |= IPC_PIMR_INT_EN_BIT_BXT;
0142             /*
0143              * disable interrupt generated instead of
0144              * RX_complete_msg
0145              */
0146             host_pimr_val &= ~IPC_HOST2ISH_BUSYCLEAR_MASK_BIT;
0147 
0148             ish_reg_write(dev, IPC_REG_PIMR_BXT, host_pimr_val);
0149     }
0150 }
0151 
0152 /**
0153  * ishtp_fw_is_ready() - Check if FW ready
0154  * @dev: ISHTP device pointer
0155  *
0156  * Check if ISH FW is ready
0157  *
0158  * Return: Read true or false
0159  */
0160 static bool ishtp_fw_is_ready(struct ishtp_device *dev)
0161 {
0162     uint32_t ish_status = _ish_read_fw_sts_reg(dev);
0163 
0164     return IPC_IS_ISH_ILUP(ish_status) &&
0165         IPC_IS_ISH_ISHTP_READY(ish_status);
0166 }
0167 
0168 /**
0169  * ish_set_host_rdy() - Indicate host ready
0170  * @dev: ISHTP device pointer
0171  *
0172  * Set host ready indication to FW
0173  */
0174 static void ish_set_host_rdy(struct ishtp_device *dev)
0175 {
0176     uint32_t host_status = ish_reg_read(dev, IPC_REG_HOST_COMM);
0177 
0178     IPC_SET_HOST_READY(host_status);
0179     ish_reg_write(dev, IPC_REG_HOST_COMM, host_status);
0180 }
0181 
0182 /**
0183  * ish_clr_host_rdy() - Indicate host not ready
0184  * @dev: ISHTP device pointer
0185  *
0186  * Send host not ready indication to FW
0187  */
0188 static void ish_clr_host_rdy(struct ishtp_device *dev)
0189 {
0190     uint32_t host_status = ish_reg_read(dev, IPC_REG_HOST_COMM);
0191 
0192     IPC_CLEAR_HOST_READY(host_status);
0193     ish_reg_write(dev, IPC_REG_HOST_COMM, host_status);
0194 }
0195 
0196 static bool ish_chk_host_rdy(struct ishtp_device *dev)
0197 {
0198     uint32_t host_status = ish_reg_read(dev, IPC_REG_HOST_COMM);
0199 
0200     return (host_status & IPC_HOSTCOMM_READY_BIT);
0201 }
0202 
0203 /**
0204  * ish_set_host_ready() - reconfig ipc host registers
0205  * @dev: ishtp device pointer
0206  *
0207  * Set host to ready state
0208  * This API is called in some case:
0209  *    fw is still on, but ipc is powered down.
0210  *    such as OOB case.
0211  *
0212  * Return: 0 for success else error fault code
0213  */
0214 void ish_set_host_ready(struct ishtp_device *dev)
0215 {
0216     if (ish_chk_host_rdy(dev))
0217         return;
0218 
0219     ish_set_host_rdy(dev);
0220     set_host_ready(dev);
0221 }
0222 
0223 /**
0224  * _ishtp_read_hdr() - Read message header
0225  * @dev: ISHTP device pointer
0226  *
0227  * Read header of 32bit length
0228  *
0229  * Return: Read register value
0230  */
0231 static uint32_t _ishtp_read_hdr(const struct ishtp_device *dev)
0232 {
0233     return ish_reg_read(dev, IPC_REG_ISH2HOST_MSG);
0234 }
0235 
0236 /**
0237  * _ishtp_read - Read message
0238  * @dev: ISHTP device pointer
0239  * @buffer: message buffer
0240  * @buffer_length: length of message buffer
0241  *
0242  * Read message from FW
0243  *
0244  * Return: Always 0
0245  */
0246 static int _ishtp_read(struct ishtp_device *dev, unsigned char *buffer,
0247     unsigned long buffer_length)
0248 {
0249     uint32_t    i;
0250     uint32_t    *r_buf = (uint32_t *)buffer;
0251     uint32_t    msg_offs;
0252 
0253     msg_offs = IPC_REG_ISH2HOST_MSG + sizeof(struct ishtp_msg_hdr);
0254     for (i = 0; i < buffer_length; i += sizeof(uint32_t))
0255         *r_buf++ = ish_reg_read(dev, msg_offs + i);
0256 
0257     return 0;
0258 }
0259 
0260 /**
0261  * write_ipc_from_queue() - try to write ipc msg from Tx queue to device
0262  * @dev: ishtp device pointer
0263  *
0264  * Check if DRBL is cleared. if it is - write the first IPC msg,  then call
0265  * the callback function (unless it's NULL)
0266  *
0267  * Return: 0 for success else failure code
0268  */
0269 static int write_ipc_from_queue(struct ishtp_device *dev)
0270 {
0271     struct wr_msg_ctl_info  *ipc_link;
0272     unsigned long   length;
0273     unsigned long   rem;
0274     unsigned long   flags;
0275     uint32_t    doorbell_val;
0276     uint32_t    *r_buf;
0277     uint32_t    reg_addr;
0278     int i;
0279     void    (*ipc_send_compl)(void *);
0280     void    *ipc_send_compl_prm;
0281 
0282     if (dev->dev_state == ISHTP_DEV_DISABLED)
0283         return -EINVAL;
0284 
0285     spin_lock_irqsave(&dev->wr_processing_spinlock, flags);
0286     if (!ish_is_input_ready(dev)) {
0287         spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
0288         return -EBUSY;
0289     }
0290 
0291     /*
0292      * if tx send list is empty - return 0;
0293      * may happen, as RX_COMPLETE handler doesn't check list emptiness.
0294      */
0295     if (list_empty(&dev->wr_processing_list)) {
0296         spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
0297         return  0;
0298     }
0299 
0300     ipc_link = list_first_entry(&dev->wr_processing_list,
0301                     struct wr_msg_ctl_info, link);
0302     /* first 4 bytes of the data is the doorbell value (IPC header) */
0303     length = ipc_link->length - sizeof(uint32_t);
0304     doorbell_val = *(uint32_t *)ipc_link->inline_data;
0305     r_buf = (uint32_t *)(ipc_link->inline_data + sizeof(uint32_t));
0306 
0307     /* If sending MNG_SYNC_FW_CLOCK, update clock again */
0308     if (IPC_HEADER_GET_PROTOCOL(doorbell_val) == IPC_PROTOCOL_MNG &&
0309         IPC_HEADER_GET_MNG_CMD(doorbell_val) == MNG_SYNC_FW_CLOCK) {
0310         uint64_t usec_system, usec_utc;
0311         struct ipc_time_update_msg time_update;
0312         struct time_sync_format ts_format;
0313 
0314         usec_system = ktime_to_us(ktime_get_boottime());
0315         usec_utc = ktime_to_us(ktime_get_real());
0316         ts_format.ts1_source = HOST_SYSTEM_TIME_USEC;
0317         ts_format.ts2_source = HOST_UTC_TIME_USEC;
0318         ts_format.reserved = 0;
0319 
0320         time_update.primary_host_time = usec_system;
0321         time_update.secondary_host_time = usec_utc;
0322         time_update.sync_info = ts_format;
0323 
0324         memcpy(r_buf, &time_update,
0325                sizeof(struct ipc_time_update_msg));
0326     }
0327 
0328     for (i = 0, reg_addr = IPC_REG_HOST2ISH_MSG; i < length >> 2; i++,
0329             reg_addr += 4)
0330         ish_reg_write(dev, reg_addr, r_buf[i]);
0331 
0332     rem = length & 0x3;
0333     if (rem > 0) {
0334         uint32_t reg = 0;
0335 
0336         memcpy(&reg, &r_buf[length >> 2], rem);
0337         ish_reg_write(dev, reg_addr, reg);
0338     }
0339     ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, doorbell_val);
0340 
0341     /* Flush writes to msg registers and doorbell */
0342     ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS);
0343 
0344     /* Update IPC counters */
0345     ++dev->ipc_tx_cnt;
0346     dev->ipc_tx_bytes_cnt += IPC_HEADER_GET_LENGTH(doorbell_val);
0347 
0348     ipc_send_compl = ipc_link->ipc_send_compl;
0349     ipc_send_compl_prm = ipc_link->ipc_send_compl_prm;
0350     list_del_init(&ipc_link->link);
0351     list_add(&ipc_link->link, &dev->wr_free_list);
0352     spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
0353 
0354     /*
0355      * callback will be called out of spinlock,
0356      * after ipc_link returned to free list
0357      */
0358     if (ipc_send_compl)
0359         ipc_send_compl(ipc_send_compl_prm);
0360 
0361     return 0;
0362 }
0363 
0364 /**
0365  * write_ipc_to_queue() - write ipc msg to Tx queue
0366  * @dev: ishtp device instance
0367  * @ipc_send_compl: Send complete callback
0368  * @ipc_send_compl_prm: Parameter to send in complete callback
0369  * @msg: Pointer to message
0370  * @length: Length of message
0371  *
0372  * Recived msg with IPC (and upper protocol) header  and add it to the device
0373  *  Tx-to-write list then try to send the first IPC waiting msg
0374  *  (if DRBL is cleared)
0375  * This function returns negative value for failure (means free list
0376  *  is empty, or msg too long) and 0 for success.
0377  *
0378  * Return: 0 for success else failure code
0379  */
0380 static int write_ipc_to_queue(struct ishtp_device *dev,
0381     void (*ipc_send_compl)(void *), void *ipc_send_compl_prm,
0382     unsigned char *msg, int length)
0383 {
0384     struct wr_msg_ctl_info *ipc_link;
0385     unsigned long flags;
0386 
0387     if (length > IPC_FULL_MSG_SIZE)
0388         return -EMSGSIZE;
0389 
0390     spin_lock_irqsave(&dev->wr_processing_spinlock, flags);
0391     if (list_empty(&dev->wr_free_list)) {
0392         spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
0393         return -ENOMEM;
0394     }
0395     ipc_link = list_first_entry(&dev->wr_free_list,
0396                     struct wr_msg_ctl_info, link);
0397     list_del_init(&ipc_link->link);
0398 
0399     ipc_link->ipc_send_compl = ipc_send_compl;
0400     ipc_link->ipc_send_compl_prm = ipc_send_compl_prm;
0401     ipc_link->length = length;
0402     memcpy(ipc_link->inline_data, msg, length);
0403 
0404     list_add_tail(&ipc_link->link, &dev->wr_processing_list);
0405     spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
0406 
0407     write_ipc_from_queue(dev);
0408 
0409     return 0;
0410 }
0411 
0412 /**
0413  * ipc_send_mng_msg() - Send management message
0414  * @dev: ishtp device instance
0415  * @msg_code: Message code
0416  * @msg: Pointer to message
0417  * @size: Length of message
0418  *
0419  * Send management message to FW
0420  *
0421  * Return: 0 for success else failure code
0422  */
0423 static int ipc_send_mng_msg(struct ishtp_device *dev, uint32_t msg_code,
0424     void *msg, size_t size)
0425 {
0426     unsigned char   ipc_msg[IPC_FULL_MSG_SIZE];
0427     uint32_t    drbl_val = IPC_BUILD_MNG_MSG(msg_code, size);
0428 
0429     memcpy(ipc_msg, &drbl_val, sizeof(uint32_t));
0430     memcpy(ipc_msg + sizeof(uint32_t), msg, size);
0431     return  write_ipc_to_queue(dev, NULL, NULL, ipc_msg,
0432         sizeof(uint32_t) + size);
0433 }
0434 
0435 #define WAIT_FOR_FW_RDY         0x1
0436 #define WAIT_FOR_INPUT_RDY      0x2
0437 
0438 /**
0439  * timed_wait_for_timeout() - wait special event with timeout
0440  * @dev: ISHTP device pointer
0441  * @condition: indicate the condition for waiting
0442  * @timeinc: time slice for every wait cycle, in ms
0443  * @timeout: time in ms for timeout
0444  *
0445  * This function will check special event to be ready in a loop, the loop
0446  * period is specificd in timeinc. Wait timeout will causes failure.
0447  *
0448  * Return: 0 for success else failure code
0449  */
0450 static int timed_wait_for_timeout(struct ishtp_device *dev, int condition,
0451                 unsigned int timeinc, unsigned int timeout)
0452 {
0453     bool complete = false;
0454     int ret;
0455 
0456     do {
0457         if (condition == WAIT_FOR_FW_RDY) {
0458             complete = ishtp_fw_is_ready(dev);
0459         } else if (condition == WAIT_FOR_INPUT_RDY) {
0460             complete = ish_is_input_ready(dev);
0461         } else {
0462             ret = -EINVAL;
0463             goto out;
0464         }
0465 
0466         if (!complete) {
0467             unsigned long left_time;
0468 
0469             left_time = msleep_interruptible(timeinc);
0470             timeout -= (timeinc - left_time);
0471         }
0472     } while (!complete && timeout > 0);
0473 
0474     if (complete)
0475         ret = 0;
0476     else
0477         ret = -EBUSY;
0478 
0479 out:
0480     return ret;
0481 }
0482 
0483 #define TIME_SLICE_FOR_FW_RDY_MS        100
0484 #define TIME_SLICE_FOR_INPUT_RDY_MS     100
0485 #define TIMEOUT_FOR_FW_RDY_MS           2000
0486 #define TIMEOUT_FOR_INPUT_RDY_MS        2000
0487 
0488 /**
0489  * ish_fw_reset_handler() - FW reset handler
0490  * @dev: ishtp device pointer
0491  *
0492  * Handle FW reset
0493  *
0494  * Return: 0 for success else failure code
0495  */
0496 static int ish_fw_reset_handler(struct ishtp_device *dev)
0497 {
0498     uint32_t    reset_id;
0499     unsigned long   flags;
0500 
0501     /* Read reset ID */
0502     reset_id = ish_reg_read(dev, IPC_REG_ISH2HOST_MSG) & 0xFFFF;
0503 
0504     /* Clear IPC output queue */
0505     spin_lock_irqsave(&dev->wr_processing_spinlock, flags);
0506     list_splice_init(&dev->wr_processing_list, &dev->wr_free_list);
0507     spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
0508 
0509     /* ISHTP notification in IPC_RESET */
0510     ishtp_reset_handler(dev);
0511 
0512     if (!ish_is_input_ready(dev))
0513         timed_wait_for_timeout(dev, WAIT_FOR_INPUT_RDY,
0514             TIME_SLICE_FOR_INPUT_RDY_MS, TIMEOUT_FOR_INPUT_RDY_MS);
0515 
0516     /* ISH FW is dead */
0517     if (!ish_is_input_ready(dev))
0518         return  -EPIPE;
0519     /*
0520      * Set HOST2ISH.ILUP. Apparently we need this BEFORE sending
0521      * RESET_NOTIFY_ACK - FW will be checking for it
0522      */
0523     ish_set_host_rdy(dev);
0524     /* Send RESET_NOTIFY_ACK (with reset_id) */
0525     ipc_send_mng_msg(dev, MNG_RESET_NOTIFY_ACK, &reset_id,
0526              sizeof(uint32_t));
0527 
0528     /* Wait for ISH FW'es ILUP and ISHTP_READY */
0529     timed_wait_for_timeout(dev, WAIT_FOR_FW_RDY,
0530             TIME_SLICE_FOR_FW_RDY_MS, TIMEOUT_FOR_FW_RDY_MS);
0531     if (!ishtp_fw_is_ready(dev)) {
0532         /* ISH FW is dead */
0533         uint32_t    ish_status;
0534 
0535         ish_status = _ish_read_fw_sts_reg(dev);
0536         dev_err(dev->devc,
0537             "[ishtp-ish]: completed reset, ISH is dead (FWSTS = %08X)\n",
0538             ish_status);
0539         return -ENODEV;
0540     }
0541     return  0;
0542 }
0543 
0544 #define TIMEOUT_FOR_HW_RDY_MS           300
0545 
0546 /**
0547  * fw_reset_work_fn() - FW reset worker function
0548  * @unused: not used
0549  *
0550  * Call ish_fw_reset_handler to complete FW reset
0551  */
0552 static void fw_reset_work_fn(struct work_struct *unused)
0553 {
0554     int rv;
0555 
0556     rv = ish_fw_reset_handler(ishtp_dev);
0557     if (!rv) {
0558         /* ISH is ILUP & ISHTP-ready. Restart ISHTP */
0559         msleep_interruptible(TIMEOUT_FOR_HW_RDY_MS);
0560         ishtp_dev->recvd_hw_ready = 1;
0561         wake_up_interruptible(&ishtp_dev->wait_hw_ready);
0562 
0563         /* ISHTP notification in IPC_RESET sequence completion */
0564         ishtp_reset_compl_handler(ishtp_dev);
0565     } else
0566         dev_err(ishtp_dev->devc, "[ishtp-ish]: FW reset failed (%d)\n",
0567             rv);
0568 }
0569 
0570 /**
0571  * _ish_sync_fw_clock() -Sync FW clock with the OS clock
0572  * @dev: ishtp device pointer
0573  *
0574  * Sync FW and OS time
0575  */
0576 static void _ish_sync_fw_clock(struct ishtp_device *dev)
0577 {
0578     static unsigned long    prev_sync;
0579     uint64_t    usec;
0580 
0581     if (prev_sync && time_before(jiffies, prev_sync + 20 * HZ))
0582         return;
0583 
0584     prev_sync = jiffies;
0585     usec = ktime_to_us(ktime_get_boottime());
0586     ipc_send_mng_msg(dev, MNG_SYNC_FW_CLOCK, &usec, sizeof(uint64_t));
0587 }
0588 
0589 /**
0590  * recv_ipc() - Receive and process IPC management messages
0591  * @dev: ishtp device instance
0592  * @doorbell_val: doorbell value
0593  *
0594  * This function runs in ISR context.
0595  * NOTE: Any other mng command than reset_notify and reset_notify_ack
0596  * won't wake BH handler
0597  */
0598 static void recv_ipc(struct ishtp_device *dev, uint32_t doorbell_val)
0599 {
0600     uint32_t    mng_cmd;
0601 
0602     mng_cmd = IPC_HEADER_GET_MNG_CMD(doorbell_val);
0603 
0604     switch (mng_cmd) {
0605     default:
0606         break;
0607 
0608     case MNG_RX_CMPL_INDICATION:
0609         if (dev->suspend_flag) {
0610             dev->suspend_flag = 0;
0611             wake_up_interruptible(&dev->suspend_wait);
0612         }
0613         if (dev->resume_flag) {
0614             dev->resume_flag = 0;
0615             wake_up_interruptible(&dev->resume_wait);
0616         }
0617 
0618         write_ipc_from_queue(dev);
0619         break;
0620 
0621     case MNG_RESET_NOTIFY:
0622         if (!ishtp_dev) {
0623             ishtp_dev = dev;
0624             INIT_WORK(&fw_reset_work, fw_reset_work_fn);
0625         }
0626         schedule_work(&fw_reset_work);
0627         break;
0628 
0629     case MNG_RESET_NOTIFY_ACK:
0630         dev->recvd_hw_ready = 1;
0631         wake_up_interruptible(&dev->wait_hw_ready);
0632         break;
0633     }
0634 }
0635 
0636 /**
0637  * ish_irq_handler() - ISH IRQ handler
0638  * @irq: irq number
0639  * @dev_id: ishtp device pointer
0640  *
0641  * ISH IRQ handler. If interrupt is generated and is for ISH it will process
0642  * the interrupt.
0643  */
0644 irqreturn_t ish_irq_handler(int irq, void *dev_id)
0645 {
0646     struct ishtp_device *dev = dev_id;
0647     uint32_t    doorbell_val;
0648     bool    interrupt_generated;
0649 
0650     /* Check that it's interrupt from ISH (may be shared) */
0651     interrupt_generated = check_generated_interrupt(dev);
0652 
0653     if (!interrupt_generated)
0654         return IRQ_NONE;
0655 
0656     doorbell_val = ish_reg_read(dev, IPC_REG_ISH2HOST_DRBL);
0657     if (!IPC_IS_BUSY(doorbell_val))
0658         return IRQ_HANDLED;
0659 
0660     if (dev->dev_state == ISHTP_DEV_DISABLED)
0661         return  IRQ_HANDLED;
0662 
0663     /* Sanity check: IPC dgram length in header */
0664     if (IPC_HEADER_GET_LENGTH(doorbell_val) > IPC_PAYLOAD_SIZE) {
0665         dev_err(dev->devc,
0666             "IPC hdr - bad length: %u; dropped\n",
0667             (unsigned int)IPC_HEADER_GET_LENGTH(doorbell_val));
0668         goto    eoi;
0669     }
0670 
0671     switch (IPC_HEADER_GET_PROTOCOL(doorbell_val)) {
0672     default:
0673         break;
0674     case IPC_PROTOCOL_MNG:
0675         recv_ipc(dev, doorbell_val);
0676         break;
0677     case IPC_PROTOCOL_ISHTP:
0678         ishtp_recv(dev);
0679         break;
0680     }
0681 
0682 eoi:
0683     /* Update IPC counters */
0684     ++dev->ipc_rx_cnt;
0685     dev->ipc_rx_bytes_cnt += IPC_HEADER_GET_LENGTH(doorbell_val);
0686 
0687     ish_reg_write(dev, IPC_REG_ISH2HOST_DRBL, 0);
0688     /* Flush write to doorbell */
0689     ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS);
0690 
0691     return  IRQ_HANDLED;
0692 }
0693 
0694 /**
0695  * ish_disable_dma() - disable dma communication between host and ISHFW
0696  * @dev: ishtp device pointer
0697  *
0698  * Clear the dma enable bit and wait for dma inactive.
0699  *
0700  * Return: 0 for success else error code.
0701  */
0702 int ish_disable_dma(struct ishtp_device *dev)
0703 {
0704     unsigned int    dma_delay;
0705 
0706     /* Clear the dma enable bit */
0707     ish_reg_write(dev, IPC_REG_ISH_RMP2, 0);
0708 
0709     /* wait for dma inactive */
0710     for (dma_delay = 0; dma_delay < MAX_DMA_DELAY &&
0711         _ish_read_fw_sts_reg(dev) & (IPC_ISH_IN_DMA);
0712         dma_delay += 5)
0713         mdelay(5);
0714 
0715     if (dma_delay >= MAX_DMA_DELAY) {
0716         dev_err(dev->devc,
0717             "Wait for DMA inactive timeout\n");
0718         return  -EBUSY;
0719     }
0720 
0721     return 0;
0722 }
0723 
0724 /**
0725  * ish_wakeup() - wakeup ishfw from waiting-for-host state
0726  * @dev: ishtp device pointer
0727  *
0728  * Set the dma enable bit and send a void message to FW,
0729  * it wil wakeup FW from waiting-for-host state.
0730  */
0731 static void ish_wakeup(struct ishtp_device *dev)
0732 {
0733     /* Set dma enable bit */
0734     ish_reg_write(dev, IPC_REG_ISH_RMP2, IPC_RMP2_DMA_ENABLED);
0735 
0736     /*
0737      * Send 0 IPC message so that ISH FW wakes up if it was already
0738      * asleep.
0739      */
0740     ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, IPC_DRBL_BUSY_BIT);
0741 
0742     /* Flush writes to doorbell and REMAP2 */
0743     ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS);
0744 }
0745 
0746 /**
0747  * _ish_hw_reset() - HW reset
0748  * @dev: ishtp device pointer
0749  *
0750  * Reset ISH HW to recover if any error
0751  *
0752  * Return: 0 for success else error fault code
0753  */
0754 static int _ish_hw_reset(struct ishtp_device *dev)
0755 {
0756     struct pci_dev *pdev = dev->pdev;
0757     int rv;
0758     uint16_t csr;
0759 
0760     if (!pdev)
0761         return  -ENODEV;
0762 
0763     rv = pci_reset_function(pdev);
0764     if (!rv)
0765         dev->dev_state = ISHTP_DEV_RESETTING;
0766 
0767     if (!pdev->pm_cap) {
0768         dev_err(&pdev->dev, "Can't reset - no PM caps\n");
0769         return  -EINVAL;
0770     }
0771 
0772     /* Disable dma communication between FW and host */
0773     if (ish_disable_dma(dev)) {
0774         dev_err(&pdev->dev,
0775             "Can't reset - stuck with DMA in-progress\n");
0776         return  -EBUSY;
0777     }
0778 
0779     pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &csr);
0780 
0781     csr &= ~PCI_PM_CTRL_STATE_MASK;
0782     csr |= PCI_D3hot;
0783     pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, csr);
0784 
0785     mdelay(pdev->d3hot_delay);
0786 
0787     csr &= ~PCI_PM_CTRL_STATE_MASK;
0788     csr |= PCI_D0;
0789     pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, csr);
0790 
0791     /* Now we can enable ISH DMA operation and wakeup ISHFW */
0792     ish_wakeup(dev);
0793 
0794     return  0;
0795 }
0796 
0797 /**
0798  * _ish_ipc_reset() - IPC reset
0799  * @dev: ishtp device pointer
0800  *
0801  * Resets host and fw IPC and upper layers
0802  *
0803  * Return: 0 for success else error fault code
0804  */
0805 static int _ish_ipc_reset(struct ishtp_device *dev)
0806 {
0807     struct ipc_rst_payload_type ipc_mng_msg;
0808     int rv = 0;
0809 
0810     ipc_mng_msg.reset_id = 1;
0811     ipc_mng_msg.reserved = 0;
0812 
0813     set_host_ready(dev);
0814 
0815     /* Clear the incoming doorbell */
0816     ish_reg_write(dev, IPC_REG_ISH2HOST_DRBL, 0);
0817     /* Flush write to doorbell */
0818     ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS);
0819 
0820     dev->recvd_hw_ready = 0;
0821 
0822     /* send message */
0823     rv = ipc_send_mng_msg(dev, MNG_RESET_NOTIFY, &ipc_mng_msg,
0824         sizeof(struct ipc_rst_payload_type));
0825     if (rv) {
0826         dev_err(dev->devc, "Failed to send IPC MNG_RESET_NOTIFY\n");
0827         return  rv;
0828     }
0829 
0830     wait_event_interruptible_timeout(dev->wait_hw_ready,
0831                      dev->recvd_hw_ready, 2 * HZ);
0832     if (!dev->recvd_hw_ready) {
0833         dev_err(dev->devc, "Timed out waiting for HW ready\n");
0834         rv = -ENODEV;
0835     }
0836 
0837     return rv;
0838 }
0839 
0840 /**
0841  * ish_hw_start() -Start ISH HW
0842  * @dev: ishtp device pointer
0843  *
0844  * Set host to ready state and wait for FW reset
0845  *
0846  * Return: 0 for success else error fault code
0847  */
0848 int ish_hw_start(struct ishtp_device *dev)
0849 {
0850     ish_set_host_rdy(dev);
0851 
0852     set_host_ready(dev);
0853 
0854     /* After that we can enable ISH DMA operation and wakeup ISHFW */
0855     ish_wakeup(dev);
0856 
0857     /* wait for FW-initiated reset flow */
0858     if (!dev->recvd_hw_ready)
0859         wait_event_interruptible_timeout(dev->wait_hw_ready,
0860                          dev->recvd_hw_ready,
0861                          10 * HZ);
0862 
0863     if (!dev->recvd_hw_ready) {
0864         dev_err(dev->devc,
0865             "[ishtp-ish]: Timed out waiting for FW-initiated reset\n");
0866         return  -ENODEV;
0867     }
0868 
0869     return 0;
0870 }
0871 
0872 /**
0873  * ish_ipc_get_header() -Get doorbell value
0874  * @dev: ishtp device pointer
0875  * @length: length of message
0876  * @busy: busy status
0877  *
0878  * Get door bell value from message header
0879  *
0880  * Return: door bell value
0881  */
0882 static uint32_t ish_ipc_get_header(struct ishtp_device *dev, int length,
0883                    int busy)
0884 {
0885     uint32_t drbl_val;
0886 
0887     drbl_val = IPC_BUILD_HEADER(length, IPC_PROTOCOL_ISHTP, busy);
0888 
0889     return drbl_val;
0890 }
0891 
0892 /**
0893  * _dma_no_cache_snooping()
0894  *
0895  * Check on current platform, DMA supports cache snooping or not.
0896  * This callback is used to notify uplayer driver if manully cache
0897  * flush is needed when do DMA operation.
0898  *
0899  * Please pay attention to this callback implementation, if declare
0900  * having cache snooping on a cache snooping not supported platform
0901  * will cause uplayer driver receiving mismatched data; and if
0902  * declare no cache snooping on a cache snooping supported platform
0903  * will cause cache be flushed twice and performance hit.
0904  *
0905  * @dev: ishtp device pointer
0906  *
0907  * Return: false - has cache snooping capability
0908  *         true - no cache snooping, need manually cache flush
0909  */
0910 static bool _dma_no_cache_snooping(struct ishtp_device *dev)
0911 {
0912     return (dev->pdev->device == EHL_Ax_DEVICE_ID ||
0913         dev->pdev->device == TGL_LP_DEVICE_ID ||
0914         dev->pdev->device == TGL_H_DEVICE_ID ||
0915         dev->pdev->device == ADL_S_DEVICE_ID ||
0916         dev->pdev->device == ADL_P_DEVICE_ID);
0917 }
0918 
0919 static const struct ishtp_hw_ops ish_hw_ops = {
0920     .hw_reset = _ish_hw_reset,
0921     .ipc_reset = _ish_ipc_reset,
0922     .ipc_get_header = ish_ipc_get_header,
0923     .ishtp_read = _ishtp_read,
0924     .write = write_ipc_to_queue,
0925     .get_fw_status = _ish_read_fw_sts_reg,
0926     .sync_fw_clock = _ish_sync_fw_clock,
0927     .ishtp_read_hdr = _ishtp_read_hdr,
0928     .dma_no_cache_snooping = _dma_no_cache_snooping
0929 };
0930 
0931 /**
0932  * ish_dev_init() -Initialize ISH devoce
0933  * @pdev: PCI device
0934  *
0935  * Allocate ISHTP device and initialize IPC processing
0936  *
0937  * Return: ISHTP device instance on success else NULL
0938  */
0939 struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
0940 {
0941     struct ishtp_device *dev;
0942     int i;
0943 
0944     dev = devm_kzalloc(&pdev->dev,
0945                sizeof(struct ishtp_device) + sizeof(struct ish_hw),
0946                GFP_KERNEL);
0947     if (!dev)
0948         return NULL;
0949 
0950     ishtp_device_init(dev);
0951 
0952     init_waitqueue_head(&dev->wait_hw_ready);
0953 
0954     spin_lock_init(&dev->wr_processing_spinlock);
0955 
0956     /* Init IPC processing and free lists */
0957     INIT_LIST_HEAD(&dev->wr_processing_list);
0958     INIT_LIST_HEAD(&dev->wr_free_list);
0959     for (i = 0; i < IPC_TX_FIFO_SIZE; i++) {
0960         struct wr_msg_ctl_info  *tx_buf;
0961 
0962         tx_buf = devm_kzalloc(&pdev->dev,
0963                       sizeof(struct wr_msg_ctl_info),
0964                       GFP_KERNEL);
0965         if (!tx_buf) {
0966             /*
0967              * IPC buffers may be limited or not available
0968              * at all - although this shouldn't happen
0969              */
0970             dev_err(dev->devc,
0971                 "[ishtp-ish]: failure in Tx FIFO allocations (%d)\n",
0972                 i);
0973             break;
0974         }
0975         list_add_tail(&tx_buf->link, &dev->wr_free_list);
0976     }
0977 
0978     dev->ops = &ish_hw_ops;
0979     dev->devc = &pdev->dev;
0980     dev->mtu = IPC_PAYLOAD_SIZE - sizeof(struct ishtp_msg_hdr);
0981     return dev;
0982 }
0983 
0984 /**
0985  * ish_device_disable() - Disable ISH device
0986  * @dev: ISHTP device pointer
0987  *
0988  * Disable ISH by clearing host ready to inform firmware.
0989  */
0990 void    ish_device_disable(struct ishtp_device *dev)
0991 {
0992     struct pci_dev *pdev = dev->pdev;
0993 
0994     if (!pdev)
0995         return;
0996 
0997     /* Disable dma communication between FW and host */
0998     if (ish_disable_dma(dev)) {
0999         dev_err(&pdev->dev,
1000             "Can't reset - stuck with DMA in-progress\n");
1001         return;
1002     }
1003 
1004     /* Put ISH to D3hot state for power saving */
1005     pci_set_power_state(pdev, PCI_D3hot);
1006 
1007     dev->dev_state = ISHTP_DEV_DISABLED;
1008     ish_clr_host_rdy(dev);
1009 }