^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) * PCI glue for ISHTP provider device (ISH) driver
^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/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/suspend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define CREATE_TRACE_POINTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <trace/events/intel_ish.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "ishtp-dev.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "hw-ish.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static const struct pci_device_id ish_pci_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CHV_DEVICE_ID)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, BXT_Ax_DEVICE_ID)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, BXT_Bx_DEVICE_ID)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, APL_Ax_DEVICE_ID)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_Ax_DEVICE_ID)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CNL_Ax_DEVICE_ID)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, GLK_Ax_DEVICE_ID)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CNL_H_DEVICE_ID)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ICL_MOBILE_DEVICE_ID)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_H_DEVICE_ID)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CML_LP_DEVICE_ID)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CMP_H_DEVICE_ID)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, EHL_Ax_DEVICE_ID)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, TGL_LP_DEVICE_ID)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {0, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * ish_event_tracer() - Callback function to dump trace messages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * @dev: ishtp device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * @format: printf style format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * Callback to direct log messages to Linux trace buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static __printf(2, 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) void ish_event_tracer(struct ishtp_device *dev, const char *format, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (trace_ishtp_dump_enabled()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) va_list args;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) char tmp_buf[100];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) va_start(args, format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) vsnprintf(tmp_buf, sizeof(tmp_buf), format, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) va_end(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) trace_ishtp_dump(tmp_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^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) * ish_init() - Init function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * @dev: ishtp device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * This function initialize wait queues for suspend/resume and call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * calls hadware initialization function. This will initiate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * startup sequence
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * Return: 0 for success or error code for failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static int ish_init(struct ishtp_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* Set the state of ISH HW to start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) ret = ish_hw_start(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) dev_err(dev->devc, "ISH: hw start failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* Start the inter process communication to ISH processor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) ret = ishtp_start(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) dev_err(dev->devc, "ISHTP: Protocol init failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static const struct pci_device_id ish_invalid_pci_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* Mehlow platform special pci ids */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xA309)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xA30A)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static inline bool ish_should_enter_d0i3(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return !pm_suspend_via_firmware() || pdev->device == CHV_DEVICE_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static inline bool ish_should_leave_d0i3(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return !pm_resume_via_firmware() || pdev->device == CHV_DEVICE_ID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * ish_probe() - PCI driver probe callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * @pdev: pci device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * @ent: pci device id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * Initialize PCI function, setup interrupt and call for ISH initialization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * Return: 0 for success or error code for failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct ish_hw *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) unsigned long irq_flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct ishtp_device *ishtp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* Check for invalid platforms for ISH support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (pci_dev_present(ish_invalid_pci_ids))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /* enable pci dev */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) ret = pcim_enable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) dev_err(dev, "ISH: Failed to enable PCI device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* set PCI host mastering */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) pci_set_master(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* pci request regions for ISH driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) ret = pcim_iomap_regions(pdev, 1 << 0, KBUILD_MODNAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) dev_err(dev, "ISH: Failed to get PCI regions\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return ret;
^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) /* allocates and initializes the ISH dev structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) ishtp = ish_dev_init(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (!ishtp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) hw = to_ish_hw(ishtp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) ishtp->print_log = ish_event_tracer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /* mapping IO device memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) hw->mem_addr = pcim_iomap_table(pdev)[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ishtp->pdev = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /* request and enable interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (!pdev->msi_enabled && !pdev->msix_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) irq_flag = IRQF_SHARED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) ret = devm_request_irq(dev, pdev->irq, ish_irq_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) irq_flag, KBUILD_MODNAME, ishtp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) dev_err(dev, "ISH: request IRQ %d failed\n", pdev->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) dev_set_drvdata(ishtp->devc, ishtp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) init_waitqueue_head(&ishtp->suspend_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) init_waitqueue_head(&ishtp->resume_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) ret = ish_init(ishtp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * ish_remove() - PCI driver remove callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * @pdev: pci device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * This function does cleanup of ISH on pci remove callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static void ish_remove(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct ishtp_device *ishtp_dev = pci_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) ishtp_bus_remove_all_clients(ishtp_dev, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) ish_device_disable(ishtp_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static struct device __maybe_unused *ish_resume_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /* 50ms to get resume response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) #define WAIT_FOR_RESUME_ACK_MS 50
^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) * ish_resume_handler() - Work function to complete resume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * @work: work struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * The resume work function to complete resume function asynchronously.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * There are two resume paths, one where ISH is not powered off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * in that case a simple resume message is enough, others we need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * a reset sequence.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static void __maybe_unused ish_resume_handler(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct pci_dev *pdev = to_pci_dev(ish_resume_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct ishtp_device *dev = pci_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (ish_should_leave_d0i3(pdev) && !dev->suspend_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) disable_irq_wake(pdev->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) ishtp_send_resume(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /* Waiting to get resume response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (dev->resume_flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ret = wait_event_interruptible_timeout(dev->resume_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) !dev->resume_flag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) msecs_to_jiffies(WAIT_FOR_RESUME_ACK_MS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * If the flag is not cleared, something is wrong with ISH FW.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * So on resume, need to go through init sequence again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (dev->resume_flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ish_init(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * Resume from the D3, full reboot of ISH processor will happen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * so need to go through init sequence again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) ish_init(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * ish_suspend() - ISH suspend callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * @device: device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * ISH suspend callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * Return: 0 to the pm core
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static int __maybe_unused ish_suspend(struct device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct pci_dev *pdev = to_pci_dev(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct ishtp_device *dev = pci_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (ish_should_enter_d0i3(pdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * If previous suspend hasn't been asnwered then ISH is likely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * dead, don't attempt nested notification
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (dev->suspend_flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) dev->resume_flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) dev->suspend_flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) ishtp_send_suspend(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /* 25 ms should be enough for live ISH to flush all IPC buf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (dev->suspend_flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) wait_event_interruptible_timeout(dev->suspend_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) !dev->suspend_flag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) msecs_to_jiffies(25));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (dev->suspend_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * It looks like FW halt, clear the DMA bit, and put
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * ISH into D3, and FW would reset on resume.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) ish_disable_dma(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * Save state so PCI core will keep the device at D0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * the ISH would enter D0i3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) pci_save_state(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) enable_irq_wake(pdev->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * Clear the DMA bit before putting ISH into D3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * or ISH FW would reset automatically.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) ish_disable_dma(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static __maybe_unused DECLARE_WORK(resume_work, ish_resume_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * ish_resume() - ISH resume callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * @device: device pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * ISH resume callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * Return: 0 to the pm core
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static int __maybe_unused ish_resume(struct device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct pci_dev *pdev = to_pci_dev(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct ishtp_device *dev = pci_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) ish_resume_device = device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) dev->resume_flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) schedule_work(&resume_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return 0;
^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) static SIMPLE_DEV_PM_OPS(ish_pm_ops, ish_suspend, ish_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static struct pci_driver ish_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) .name = KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) .id_table = ish_pci_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) .probe = ish_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) .remove = ish_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) .driver.pm = &ish_pm_ops,
^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) module_pci_driver(ish_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) /* Original author */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) MODULE_AUTHOR("Daniel Drubin <daniel.drubin@intel.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) /* Adoption to upstream Linux kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) MODULE_DESCRIPTION("Intel(R) Integrated Sensor Hub PCI Device Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) MODULE_LICENSE("GPL");