1 // SPDX-License-Identifier: GPL-2.0-only
3 * PCI glue for ISHTP provider device (ISH) driver
5 * Copyright (c) 2014-2016, Intel Corporation.
8 #include <linux/acpi.h>
9 #include <linux/module.h>
10 #include <linux/moduleparam.h>
11 #include <linux/kernel.h>
12 #include <linux/device.h>
14 #include <linux/errno.h>
15 #include <linux/types.h>
16 #include <linux/pci.h>
17 #include <linux/sched.h>
18 #include <linux/suspend.h>
19 #include <linux/interrupt.h>
20 #include <linux/workqueue.h>
21 #define CREATE_TRACE_POINTS
22 #include <trace/events/intel_ish.h>
23 #include "ishtp-dev.h"
26 enum ishtp_driver_data_index {
27 ISHTP_DRIVER_DATA_NONE,
28 ISHTP_DRIVER_DATA_LNL_M,
29 ISHTP_DRIVER_DATA_PTL,
32 #define ISH_FW_GEN_LNL_M "lnlm"
33 #define ISH_FW_GEN_PTL "ptl"
35 #define ISH_FIRMWARE_PATH(gen) "intel/ish/ish_" gen ".bin"
36 #define ISH_FIRMWARE_PATH_ALL "intel/ish/ish_*.bin"
38 static struct ishtp_driver_data ishtp_driver_data[] = {
39 [ISHTP_DRIVER_DATA_LNL_M] = {
40 .fw_generation = ISH_FW_GEN_LNL_M,
42 [ISHTP_DRIVER_DATA_PTL] = {
43 .fw_generation = ISH_FW_GEN_PTL,
47 static const struct pci_device_id ish_pci_tbl[] = {
48 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_CHV)},
49 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_BXT_Ax)},
50 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_BXT_Bx)},
51 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_APL_Ax)},
52 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_SPT_Ax)},
53 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_CNL_Ax)},
54 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_GLK_Ax)},
55 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_CNL_H)},
56 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_ICL_MOBILE)},
57 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_SPT_H)},
58 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_CML_LP)},
59 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_CMP_H)},
60 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_EHL_Ax)},
61 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_TGL_LP)},
62 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_TGL_H)},
63 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_ADL_S)},
64 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_ADL_P)},
65 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_ADL_N)},
66 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_RPL_S)},
67 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_MTL_P)},
68 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_ARL_H)},
69 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_ARL_S)},
70 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_LNL_M), .driver_data = ISHTP_DRIVER_DATA_LNL_M},
71 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_PTL_H), .driver_data = ISHTP_DRIVER_DATA_PTL},
72 {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_PTL_P), .driver_data = ISHTP_DRIVER_DATA_PTL},
75 MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
78 * ish_event_tracer() - Callback function to dump trace messages
80 * @format: printf style format
82 * Callback to direct log messages to Linux trace buffers
85 void ish_event_tracer(struct ishtp_device *dev, const char *format, ...)
87 if (trace_ishtp_dump_enabled()) {
91 va_start(args, format);
92 vsnprintf(tmp_buf, sizeof(tmp_buf), format, args);
95 trace_ishtp_dump(tmp_buf);
100 * ish_init() - Init function
103 * This function initialize wait queues for suspend/resume and call
104 * calls hadware initialization function. This will initiate
107 * Return: 0 for success or error code for failure
109 static int ish_init(struct ishtp_device *dev)
113 /* Set the state of ISH HW to start */
114 ret = ish_hw_start(dev);
116 dev_err(dev->devc, "ISH: hw start failed.\n");
120 /* Start the inter process communication to ISH processor */
121 ret = ishtp_start(dev);
123 dev_err(dev->devc, "ISHTP: Protocol init failed.\n");
130 static const struct pci_device_id ish_invalid_pci_ids[] = {
131 /* Mehlow platform special pci ids */
132 {PCI_VDEVICE(INTEL, 0xA309)},
133 {PCI_VDEVICE(INTEL, 0xA30A)},
137 static inline bool ish_should_enter_d0i3(struct pci_dev *pdev)
139 return !pm_suspend_via_firmware() || pdev->device == PCI_DEVICE_ID_INTEL_ISH_CHV;
142 static inline bool ish_should_leave_d0i3(struct pci_dev *pdev)
144 return !pm_resume_via_firmware() || pdev->device == PCI_DEVICE_ID_INTEL_ISH_CHV;
148 * ish_probe() - PCI driver probe callback
150 * @ent: pci device id
152 * Initialize PCI function, setup interrupt and call for ISH initialization
154 * Return: 0 for success or error code for failure
156 static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
160 unsigned long irq_flag = 0;
161 struct ishtp_device *ishtp;
162 struct device *dev = &pdev->dev;
164 /* Check for invalid platforms for ISH support */
165 if (pci_dev_present(ish_invalid_pci_ids))
169 ret = pcim_enable_device(pdev);
171 dev_err(dev, "ISH: Failed to enable PCI device\n");
175 /* set PCI host mastering */
176 pci_set_master(pdev);
178 /* pci request regions for ISH driver */
179 ret = pcim_iomap_regions(pdev, 1 << 0, KBUILD_MODNAME);
181 dev_err(dev, "ISH: Failed to get PCI regions\n");
185 /* allocates and initializes the ISH dev structure */
186 ishtp = ish_dev_init(pdev);
191 hw = to_ish_hw(ishtp);
192 ishtp->print_log = ish_event_tracer;
193 ishtp->driver_data = &ishtp_driver_data[ent->driver_data];
195 /* mapping IO device memory */
196 hw->mem_addr = pcim_iomap_table(pdev)[0];
199 /* request and enable interrupt */
200 ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
202 dev_err(dev, "ISH: Failed to allocate IRQ vectors\n");
206 if (!pdev->msi_enabled && !pdev->msix_enabled)
207 irq_flag = IRQF_SHARED;
209 ret = devm_request_irq(dev, pdev->irq, ish_irq_handler,
210 irq_flag, KBUILD_MODNAME, ishtp);
212 dev_err(dev, "ISH: request IRQ %d failed\n", pdev->irq);
216 dev_set_drvdata(ishtp->devc, ishtp);
218 init_waitqueue_head(&ishtp->suspend_wait);
219 init_waitqueue_head(&ishtp->resume_wait);
221 /* Enable PME for EHL */
222 if (pdev->device == PCI_DEVICE_ID_INTEL_ISH_EHL_Ax)
223 device_init_wakeup(dev, true);
225 ret = ish_init(ishtp);
233 * ish_remove() - PCI driver remove callback
236 * This function does cleanup of ISH on pci remove callback
238 static void ish_remove(struct pci_dev *pdev)
240 struct ishtp_device *ishtp_dev = pci_get_drvdata(pdev);
242 ishtp_bus_remove_all_clients(ishtp_dev, false);
243 ish_device_disable(ishtp_dev);
248 * ish_shutdown() - PCI driver shutdown callback
251 * This function sets up wakeup for S5
253 static void ish_shutdown(struct pci_dev *pdev)
255 if (pdev->device == PCI_DEVICE_ID_INTEL_ISH_EHL_Ax)
256 pci_prepare_to_sleep(pdev);
259 static struct device __maybe_unused *ish_resume_device;
261 /* 50ms to get resume response */
262 #define WAIT_FOR_RESUME_ACK_MS 50
265 * ish_resume_handler() - Work function to complete resume
268 * The resume work function to complete resume function asynchronously.
269 * There are two resume paths, one where ISH is not powered off,
270 * in that case a simple resume message is enough, others we need
273 static void __maybe_unused ish_resume_handler(struct work_struct *work)
275 struct pci_dev *pdev = to_pci_dev(ish_resume_device);
276 struct ishtp_device *dev = pci_get_drvdata(pdev);
277 uint32_t fwsts = dev->ops->get_fw_status(dev);
279 if (ish_should_leave_d0i3(pdev) && !dev->suspend_flag
280 && IPC_IS_ISH_ILUP(fwsts)) {
281 if (device_may_wakeup(&pdev->dev))
282 disable_irq_wake(pdev->irq);
284 ish_set_host_ready(dev);
286 ishtp_send_resume(dev);
288 /* Waiting to get resume response */
289 if (dev->resume_flag)
290 wait_event_interruptible_timeout(dev->resume_wait,
292 msecs_to_jiffies(WAIT_FOR_RESUME_ACK_MS));
295 * If the flag is not cleared, something is wrong with ISH FW.
296 * So on resume, need to go through init sequence again.
298 if (dev->resume_flag)
302 * Resume from the D3, full reboot of ISH processor will happen,
303 * so need to go through init sequence again.
310 * ish_suspend() - ISH suspend callback
311 * @device: device pointer
313 * ISH suspend callback
315 * Return: 0 to the pm core
317 static int __maybe_unused ish_suspend(struct device *device)
319 struct pci_dev *pdev = to_pci_dev(device);
320 struct ishtp_device *dev = pci_get_drvdata(pdev);
322 if (ish_should_enter_d0i3(pdev)) {
324 * If previous suspend hasn't been asnwered then ISH is likely
325 * dead, don't attempt nested notification
327 if (dev->suspend_flag)
330 dev->resume_flag = 0;
331 dev->suspend_flag = 1;
332 ishtp_send_suspend(dev);
334 /* 25 ms should be enough for live ISH to flush all IPC buf */
335 if (dev->suspend_flag)
336 wait_event_interruptible_timeout(dev->suspend_wait,
338 msecs_to_jiffies(25));
340 if (dev->suspend_flag) {
342 * It looks like FW halt, clear the DMA bit, and put
343 * ISH into D3, and FW would reset on resume.
345 ish_disable_dma(dev);
348 * Save state so PCI core will keep the device at D0,
349 * the ISH would enter D0i3
351 pci_save_state(pdev);
353 if (device_may_wakeup(&pdev->dev))
354 enable_irq_wake(pdev->irq);
358 * Clear the DMA bit before putting ISH into D3,
359 * or ISH FW would reset automatically.
361 ish_disable_dma(dev);
367 static __maybe_unused DECLARE_WORK(resume_work, ish_resume_handler);
369 * ish_resume() - ISH resume callback
370 * @device: device pointer
372 * ISH resume callback
374 * Return: 0 to the pm core
376 static int __maybe_unused ish_resume(struct device *device)
378 struct pci_dev *pdev = to_pci_dev(device);
379 struct ishtp_device *dev = pci_get_drvdata(pdev);
381 ish_resume_device = device;
382 dev->resume_flag = 1;
384 schedule_work(&resume_work);
389 static SIMPLE_DEV_PM_OPS(ish_pm_ops, ish_suspend, ish_resume);
391 static ssize_t base_version_show(struct device *cdev,
392 struct device_attribute *attr, char *buf)
394 struct ishtp_device *dev = dev_get_drvdata(cdev);
396 return sysfs_emit(buf, "%u.%u.%u.%u\n", dev->base_ver.major,
397 dev->base_ver.minor, dev->base_ver.hotfix,
398 dev->base_ver.build);
400 static DEVICE_ATTR_RO(base_version);
402 static ssize_t project_version_show(struct device *cdev,
403 struct device_attribute *attr, char *buf)
405 struct ishtp_device *dev = dev_get_drvdata(cdev);
407 return sysfs_emit(buf, "%u.%u.%u.%u\n", dev->prj_ver.major,
408 dev->prj_ver.minor, dev->prj_ver.hotfix,
411 static DEVICE_ATTR_RO(project_version);
413 static struct attribute *ish_firmware_attrs[] = {
414 &dev_attr_base_version.attr,
415 &dev_attr_project_version.attr,
419 static umode_t firmware_is_visible(struct kobject *kobj, struct attribute *attr,
422 struct ishtp_device *dev = dev_get_drvdata(kobj_to_dev(kobj));
424 return dev->driver_data->fw_generation ? attr->mode : 0;
427 static const struct attribute_group ish_firmware_group = {
429 .attrs = ish_firmware_attrs,
430 .is_visible = firmware_is_visible,
433 __ATTRIBUTE_GROUPS(ish_firmware);
435 static struct pci_driver ish_driver = {
436 .name = KBUILD_MODNAME,
437 .id_table = ish_pci_tbl,
439 .remove = ish_remove,
440 .shutdown = ish_shutdown,
441 .driver.pm = &ish_pm_ops,
442 .dev_groups = ish_firmware_groups,
445 module_pci_driver(ish_driver);
447 /* Original author */
449 /* Adoption to upstream Linux kernel */
452 MODULE_DESCRIPTION("Intel(R) Integrated Sensor Hub PCI Device Driver");
453 MODULE_LICENSE("GPL");
455 MODULE_FIRMWARE(ISH_FIRMWARE_PATH(ISH_FW_GEN_LNL_M));
456 MODULE_FIRMWARE(ISH_FIRMWARE_PATH_ALL);