Lines Matching +full:send +full:- +full:flush +full:- +full:out +full:- +full:sequence
1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (c) 2014-2016, Intel Corporation.
8 #include <linux/devm-helpers.h>
14 #include "hw-ish.h"
22 * ish_reg_read() - Read register
35 return readl(hw->mem_addr + offset); in ish_reg_read()
39 * ish_reg_write() - Write register
52 writel(value, hw->mem_addr + offset); in ish_reg_write()
56 * _ish_read_fw_sts_reg() - Read FW status register
69 * check_generated_interrupt() - Check if ISH interrupt
81 if (dev->pdev->device == PCI_DEVICE_ID_INTEL_ISH_CHV) { in check_generated_interrupt()
88 /* only busy-clear bit is RW, others are RO */ in check_generated_interrupt()
97 * ish_is_input_ready() - Check if FW ready for RX
113 * set_host_ready() - Indicate host ready
120 if (dev->pdev->device == PCI_DEVICE_ID_INTEL_ISH_CHV) { in set_host_ready()
121 if (dev->pdev->revision == REVISION_ID_CHT_A0 || in set_host_ready()
122 (dev->pdev->revision & REVISION_ID_SI_MASK) == in set_host_ready()
125 else if (dev->pdev->revision == REVISION_ID_CHT_B0 || in set_host_ready()
126 (dev->pdev->revision & REVISION_ID_SI_MASK) == in set_host_ready()
128 (dev->pdev->revision & REVISION_ID_SI_MASK) == in set_host_ready()
130 (dev->pdev->revision & REVISION_ID_SI_MASK) == in set_host_ready()
154 * ishtp_fw_is_ready() - Check if FW ready
170 * ish_set_host_rdy() - Indicate host ready
184 * ish_clr_host_rdy() - Indicate host not ready
187 * Send host not ready indication to FW
205 * ish_set_host_ready() - reconfig ipc host registers
225 * _ishtp_read_hdr() - Read message header
238 * _ishtp_read - Read message
262 * write_ipc_from_queue() - try to write ipc msg from Tx queue to device
265 * Check if DRBL is cleared. if it is - write the first IPC msg, then call
283 if (dev->dev_state == ISHTP_DEV_DISABLED) in write_ipc_from_queue()
284 return -EINVAL; in write_ipc_from_queue()
286 spin_lock_irqsave(&dev->wr_processing_spinlock, flags); in write_ipc_from_queue()
288 spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); in write_ipc_from_queue()
289 return -EBUSY; in write_ipc_from_queue()
293 * if tx send list is empty - return 0; in write_ipc_from_queue()
296 if (list_empty(&dev->wr_processing_list)) { in write_ipc_from_queue()
297 spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); in write_ipc_from_queue()
301 ipc_link = list_first_entry(&dev->wr_processing_list, in write_ipc_from_queue()
304 length = ipc_link->length - sizeof(uint32_t); in write_ipc_from_queue()
305 doorbell_val = *(uint32_t *)ipc_link->inline_data; in write_ipc_from_queue()
306 r_buf = (uint32_t *)(ipc_link->inline_data + sizeof(uint32_t)); in write_ipc_from_queue()
342 /* Flush writes to msg registers and doorbell */ in write_ipc_from_queue()
346 ++dev->ipc_tx_cnt; in write_ipc_from_queue()
347 dev->ipc_tx_bytes_cnt += IPC_HEADER_GET_LENGTH(doorbell_val); in write_ipc_from_queue()
349 ipc_send_compl = ipc_link->ipc_send_compl; in write_ipc_from_queue()
350 ipc_send_compl_prm = ipc_link->ipc_send_compl_prm; in write_ipc_from_queue()
351 list_del_init(&ipc_link->link); in write_ipc_from_queue()
352 list_add(&ipc_link->link, &dev->wr_free_list); in write_ipc_from_queue()
353 spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); in write_ipc_from_queue()
356 * callback will be called out of spinlock, in write_ipc_from_queue()
366 * write_ipc_to_queue() - write ipc msg to Tx queue
368 * @ipc_send_compl: Send complete callback
369 * @ipc_send_compl_prm: Parameter to send in complete callback
374 * Tx-to-write list then try to send the first IPC waiting msg
389 return -EMSGSIZE; in write_ipc_to_queue()
391 spin_lock_irqsave(&dev->wr_processing_spinlock, flags); in write_ipc_to_queue()
392 if (list_empty(&dev->wr_free_list)) { in write_ipc_to_queue()
393 spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); in write_ipc_to_queue()
394 return -ENOMEM; in write_ipc_to_queue()
396 ipc_link = list_first_entry(&dev->wr_free_list, in write_ipc_to_queue()
398 list_del_init(&ipc_link->link); in write_ipc_to_queue()
400 ipc_link->ipc_send_compl = ipc_send_compl; in write_ipc_to_queue()
401 ipc_link->ipc_send_compl_prm = ipc_send_compl_prm; in write_ipc_to_queue()
402 ipc_link->length = length; in write_ipc_to_queue()
403 memcpy(ipc_link->inline_data, msg, length); in write_ipc_to_queue()
405 list_add_tail(&ipc_link->link, &dev->wr_processing_list); in write_ipc_to_queue()
406 spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); in write_ipc_to_queue()
414 * ipc_send_mng_msg() - Send management message
420 * Send management message to FW
440 * timed_wait_for_timeout() - wait special event with timeout
463 ret = -EINVAL; in timed_wait_for_timeout()
464 goto out; in timed_wait_for_timeout()
471 timeout -= (timeinc - left_time); in timed_wait_for_timeout()
478 ret = -EBUSY; in timed_wait_for_timeout()
480 out: in timed_wait_for_timeout()
490 * ish_fw_reset_handler() - FW reset handler
506 spin_lock_irqsave(&dev->wr_processing_spinlock, flags); in ish_fw_reset_handler()
507 list_splice_init(&dev->wr_processing_list, &dev->wr_free_list); in ish_fw_reset_handler()
508 spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); in ish_fw_reset_handler()
519 return -EPIPE; in ish_fw_reset_handler()
521 /* Send clock sync at once after reset */ in ish_fw_reset_handler()
522 ishtp_dev->prev_sync = 0; in ish_fw_reset_handler()
526 * RESET_NOTIFY_ACK - FW will be checking for it in ish_fw_reset_handler()
529 /* Send RESET_NOTIFY_ACK (with reset_id) */ in ish_fw_reset_handler()
541 dev_err(dev->devc, in ish_fw_reset_handler()
542 "[ishtp-ish]: completed reset, ISH is dead (FWSTS = %08X)\n", in ish_fw_reset_handler()
544 return -ENODEV; in ish_fw_reset_handler()
552 * fw_reset_work_fn() - FW reset worker function
563 /* ISH is ILUP & ISHTP-ready. Restart ISHTP */ in fw_reset_work_fn()
565 ishtp_dev->recvd_hw_ready = 1; in fw_reset_work_fn()
566 wake_up_interruptible(&ishtp_dev->wait_hw_ready); in fw_reset_work_fn()
568 /* ISHTP notification in IPC_RESET sequence completion */ in fw_reset_work_fn()
572 dev_err(ishtp_dev->devc, "[ishtp-ish]: FW reset failed (%d)\n", in fw_reset_work_fn()
577 * _ish_sync_fw_clock() -Sync FW clock with the OS clock
586 if (dev->prev_sync && time_before(jiffies, dev->prev_sync + 20 * HZ)) in _ish_sync_fw_clock()
589 dev->prev_sync = jiffies; in _ish_sync_fw_clock()
595 * recv_ipc() - Receive and process IPC management messages
614 if (dev->suspend_flag) { in recv_ipc()
615 dev->suspend_flag = 0; in recv_ipc()
616 wake_up_interruptible(&dev->suspend_wait); in recv_ipc()
618 if (dev->resume_flag) { in recv_ipc()
619 dev->resume_flag = 0; in recv_ipc()
620 wake_up_interruptible(&dev->resume_wait); in recv_ipc()
634 dev->recvd_hw_ready = 1; in recv_ipc()
635 wake_up_interruptible(&dev->wait_hw_ready); in recv_ipc()
641 * ish_irq_handler() - ISH IRQ handler
664 if (dev->dev_state == ISHTP_DEV_DISABLED) in ish_irq_handler()
669 dev_err(dev->devc, in ish_irq_handler()
670 "IPC hdr - bad length: %u; dropped\n", in ish_irq_handler()
688 ++dev->ipc_rx_cnt; in ish_irq_handler()
689 dev->ipc_rx_bytes_cnt += IPC_HEADER_GET_LENGTH(doorbell_val); in ish_irq_handler()
692 /* Flush write to doorbell */ in ish_irq_handler()
699 * ish_disable_dma() - disable dma communication between host and ISHFW
720 dev_err(dev->devc, in ish_disable_dma()
722 return -EBUSY; in ish_disable_dma()
729 * ish_wakeup() - wakeup ishfw from waiting-for-host state
732 * Set the dma enable bit and send a void message to FW,
733 * it wil wakeup FW from waiting-for-host state.
741 * Send 0 IPC message so that ISH FW wakes up if it was already in ish_wakeup()
746 /* Flush writes to doorbell and REMAP2 */ in ish_wakeup()
751 * _ish_hw_reset() - HW reset
760 struct pci_dev *pdev = dev->pdev; in _ish_hw_reset()
765 return -ENODEV; in _ish_hw_reset()
769 dev->dev_state = ISHTP_DEV_RESETTING; in _ish_hw_reset()
771 if (!pdev->pm_cap) { in _ish_hw_reset()
772 dev_err(&pdev->dev, "Can't reset - no PM caps\n"); in _ish_hw_reset()
773 return -EINVAL; in _ish_hw_reset()
778 dev_err(&pdev->dev, in _ish_hw_reset()
779 "Can't reset - stuck with DMA in-progress\n"); in _ish_hw_reset()
780 return -EBUSY; in _ish_hw_reset()
783 pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &csr); in _ish_hw_reset()
787 pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, csr); in _ish_hw_reset()
789 mdelay(pdev->d3hot_delay); in _ish_hw_reset()
793 pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, csr); in _ish_hw_reset()
802 * _ish_ipc_reset() - IPC reset
821 /* Flush write to doorbell */ in _ish_ipc_reset()
824 dev->recvd_hw_ready = 0; in _ish_ipc_reset()
826 /* send message */ in _ish_ipc_reset()
830 dev_err(dev->devc, "Failed to send IPC MNG_RESET_NOTIFY\n"); in _ish_ipc_reset()
834 wait_event_interruptible_timeout(dev->wait_hw_ready, in _ish_ipc_reset()
835 dev->recvd_hw_ready, 2 * HZ); in _ish_ipc_reset()
836 if (!dev->recvd_hw_ready) { in _ish_ipc_reset()
837 dev_err(dev->devc, "Timed out waiting for HW ready\n"); in _ish_ipc_reset()
838 rv = -ENODEV; in _ish_ipc_reset()
845 * ish_hw_start() -Start ISH HW
861 /* wait for FW-initiated reset flow */ in ish_hw_start()
862 if (!dev->recvd_hw_ready) in ish_hw_start()
863 wait_event_interruptible_timeout(dev->wait_hw_ready, in ish_hw_start()
864 dev->recvd_hw_ready, in ish_hw_start()
867 if (!dev->recvd_hw_ready) { in ish_hw_start()
868 dev_err(dev->devc, in ish_hw_start()
869 "[ishtp-ish]: Timed out waiting for FW-initiated reset\n"); in ish_hw_start()
870 return -ENODEV; in ish_hw_start()
877 * ish_ipc_get_header() -Get doorbell value
901 * flush is needed when do DMA operation.
911 * Return: false - has cache snooping capability
912 * true - no cache snooping, need manually cache flush
916 return (dev->pdev->device == PCI_DEVICE_ID_INTEL_ISH_EHL_Ax || in _dma_no_cache_snooping()
917 dev->pdev->device == PCI_DEVICE_ID_INTEL_ISH_TGL_LP || in _dma_no_cache_snooping()
918 dev->pdev->device == PCI_DEVICE_ID_INTEL_ISH_TGL_H || in _dma_no_cache_snooping()
919 dev->pdev->device == PCI_DEVICE_ID_INTEL_ISH_ADL_S || in _dma_no_cache_snooping()
920 dev->pdev->device == PCI_DEVICE_ID_INTEL_ISH_ADL_P); in _dma_no_cache_snooping()
936 * ish_dev_init() -Initialize ISH devoce
949 dev = devm_kzalloc(&pdev->dev, in ish_dev_init()
955 dev->devc = &pdev->dev; in ish_dev_init()
958 init_waitqueue_head(&dev->wait_hw_ready); in ish_dev_init()
960 spin_lock_init(&dev->wr_processing_spinlock); in ish_dev_init()
963 INIT_LIST_HEAD(&dev->wr_processing_list); in ish_dev_init()
964 INIT_LIST_HEAD(&dev->wr_free_list); in ish_dev_init()
968 tx_buf = devm_kzalloc(&pdev->dev, in ish_dev_init()
974 * at all - although this shouldn't happen in ish_dev_init()
976 dev_err(dev->devc, in ish_dev_init()
977 "[ishtp-ish]: failure in Tx FIFO allocations (%d)\n", in ish_dev_init()
981 list_add_tail(&tx_buf->link, &dev->wr_free_list); in ish_dev_init()
984 ret = devm_work_autocancel(&pdev->dev, &fw_reset_work, fw_reset_work_fn); in ish_dev_init()
986 dev_err(dev->devc, "Failed to initialise FW reset work\n"); in ish_dev_init()
990 dev->ops = &ish_hw_ops; in ish_dev_init()
991 dev->mtu = IPC_PAYLOAD_SIZE - sizeof(struct ishtp_msg_hdr); in ish_dev_init()
996 * ish_device_disable() - Disable ISH device
1003 struct pci_dev *pdev = dev->pdev; in ish_device_disable()
1010 dev_err(&pdev->dev, in ish_device_disable()
1011 "Can't reset - stuck with DMA in-progress\n"); in ish_device_disable()
1018 dev->dev_state = ISHTP_DEV_DISABLED; in ish_device_disable()