1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * PCI glue for ISHTP provider device (ISH) driver 4 * 5 * Copyright (c) 2014-2016, Intel Corporation. 6 */ 7 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> 13 #include <linux/fs.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" 24 #include "hw-ish.h" 25 26 static const struct pci_device_id ish_pci_tbl[] = { 27 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CHV_DEVICE_ID)}, 28 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, BXT_Ax_DEVICE_ID)}, 29 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, BXT_Bx_DEVICE_ID)}, 30 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, APL_Ax_DEVICE_ID)}, 31 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_Ax_DEVICE_ID)}, 32 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CNL_Ax_DEVICE_ID)}, 33 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, GLK_Ax_DEVICE_ID)}, 34 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CNL_H_DEVICE_ID)}, 35 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ICL_MOBILE_DEVICE_ID)}, 36 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_H_DEVICE_ID)}, 37 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CML_LP_DEVICE_ID)}, 38 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CMP_H_DEVICE_ID)}, 39 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, EHL_Ax_DEVICE_ID)}, 40 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, TGL_LP_DEVICE_ID)}, 41 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, TGL_H_DEVICE_ID)}, 42 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ADL_S_DEVICE_ID)}, 43 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ADL_P_DEVICE_ID)}, 44 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ADL_N_DEVICE_ID)}, 45 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, RPL_S_DEVICE_ID)}, 46 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MTL_P_DEVICE_ID)}, 47 {0, } 48 }; 49 MODULE_DEVICE_TABLE(pci, ish_pci_tbl); 50 51 /** 52 * ish_event_tracer() - Callback function to dump trace messages 53 * @dev: ishtp device 54 * @format: printf style format 55 * 56 * Callback to direct log messages to Linux trace buffers 57 */ 58 static __printf(2, 3) 59 void ish_event_tracer(struct ishtp_device *dev, const char *format, ...) 60 { 61 if (trace_ishtp_dump_enabled()) { 62 va_list args; 63 char tmp_buf[100]; 64 65 va_start(args, format); 66 vsnprintf(tmp_buf, sizeof(tmp_buf), format, args); 67 va_end(args); 68 69 trace_ishtp_dump(tmp_buf); 70 } 71 } 72 73 /** 74 * ish_init() - Init function 75 * @dev: ishtp device 76 * 77 * This function initialize wait queues for suspend/resume and call 78 * calls hadware initialization function. This will initiate 79 * startup sequence 80 * 81 * Return: 0 for success or error code for failure 82 */ 83 static int ish_init(struct ishtp_device *dev) 84 { 85 int ret; 86 87 /* Set the state of ISH HW to start */ 88 ret = ish_hw_start(dev); 89 if (ret) { 90 dev_err(dev->devc, "ISH: hw start failed.\n"); 91 return ret; 92 } 93 94 /* Start the inter process communication to ISH processor */ 95 ret = ishtp_start(dev); 96 if (ret) { 97 dev_err(dev->devc, "ISHTP: Protocol init failed.\n"); 98 return ret; 99 } 100 101 return 0; 102 } 103 104 static const struct pci_device_id ish_invalid_pci_ids[] = { 105 /* Mehlow platform special pci ids */ 106 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xA309)}, 107 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xA30A)}, 108 {} 109 }; 110 111 static inline bool ish_should_enter_d0i3(struct pci_dev *pdev) 112 { 113 return !pm_suspend_via_firmware() || pdev->device == CHV_DEVICE_ID; 114 } 115 116 static inline bool ish_should_leave_d0i3(struct pci_dev *pdev) 117 { 118 return !pm_resume_via_firmware() || pdev->device == CHV_DEVICE_ID; 119 } 120 121 static int enable_gpe(struct device *dev) 122 { 123 #ifdef CONFIG_ACPI 124 acpi_status acpi_sts; 125 struct acpi_device *adev; 126 struct acpi_device_wakeup *wakeup; 127 128 adev = ACPI_COMPANION(dev); 129 if (!adev) { 130 dev_err(dev, "get acpi handle failed\n"); 131 return -ENODEV; 132 } 133 wakeup = &adev->wakeup; 134 135 acpi_sts = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number); 136 if (ACPI_FAILURE(acpi_sts)) { 137 dev_err(dev, "enable ose_gpe failed\n"); 138 return -EIO; 139 } 140 141 return 0; 142 #else 143 return -ENODEV; 144 #endif 145 } 146 147 static void enable_pme_wake(struct pci_dev *pdev) 148 { 149 if ((pci_pme_capable(pdev, PCI_D0) || 150 pci_pme_capable(pdev, PCI_D3hot) || 151 pci_pme_capable(pdev, PCI_D3cold)) && !enable_gpe(&pdev->dev)) { 152 pci_pme_active(pdev, true); 153 dev_dbg(&pdev->dev, "ish ipc driver pme wake enabled\n"); 154 } 155 } 156 157 /** 158 * ish_probe() - PCI driver probe callback 159 * @pdev: pci device 160 * @ent: pci device id 161 * 162 * Initialize PCI function, setup interrupt and call for ISH initialization 163 * 164 * Return: 0 for success or error code for failure 165 */ 166 static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 167 { 168 int ret; 169 struct ish_hw *hw; 170 unsigned long irq_flag = 0; 171 struct ishtp_device *ishtp; 172 struct device *dev = &pdev->dev; 173 174 /* Check for invalid platforms for ISH support */ 175 if (pci_dev_present(ish_invalid_pci_ids)) 176 return -ENODEV; 177 178 /* enable pci dev */ 179 ret = pcim_enable_device(pdev); 180 if (ret) { 181 dev_err(dev, "ISH: Failed to enable PCI device\n"); 182 return ret; 183 } 184 185 /* set PCI host mastering */ 186 pci_set_master(pdev); 187 188 /* pci request regions for ISH driver */ 189 ret = pcim_iomap_regions(pdev, 1 << 0, KBUILD_MODNAME); 190 if (ret) { 191 dev_err(dev, "ISH: Failed to get PCI regions\n"); 192 return ret; 193 } 194 195 /* allocates and initializes the ISH dev structure */ 196 ishtp = ish_dev_init(pdev); 197 if (!ishtp) { 198 ret = -ENOMEM; 199 return ret; 200 } 201 hw = to_ish_hw(ishtp); 202 ishtp->print_log = ish_event_tracer; 203 204 /* mapping IO device memory */ 205 hw->mem_addr = pcim_iomap_table(pdev)[0]; 206 ishtp->pdev = pdev; 207 208 /* request and enable interrupt */ 209 ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); 210 if (!pdev->msi_enabled && !pdev->msix_enabled) 211 irq_flag = IRQF_SHARED; 212 213 ret = devm_request_irq(dev, pdev->irq, ish_irq_handler, 214 irq_flag, KBUILD_MODNAME, ishtp); 215 if (ret) { 216 dev_err(dev, "ISH: request IRQ %d failed\n", pdev->irq); 217 return ret; 218 } 219 220 dev_set_drvdata(ishtp->devc, ishtp); 221 222 init_waitqueue_head(&ishtp->suspend_wait); 223 init_waitqueue_head(&ishtp->resume_wait); 224 225 /* Enable PME for EHL */ 226 if (pdev->device == EHL_Ax_DEVICE_ID) 227 enable_pme_wake(pdev); 228 229 ret = ish_init(ishtp); 230 if (ret) 231 return ret; 232 233 return 0; 234 } 235 236 /** 237 * ish_remove() - PCI driver remove callback 238 * @pdev: pci device 239 * 240 * This function does cleanup of ISH on pci remove callback 241 */ 242 static void ish_remove(struct pci_dev *pdev) 243 { 244 struct ishtp_device *ishtp_dev = pci_get_drvdata(pdev); 245 246 ishtp_bus_remove_all_clients(ishtp_dev, false); 247 ish_device_disable(ishtp_dev); 248 } 249 250 static struct device __maybe_unused *ish_resume_device; 251 252 /* 50ms to get resume response */ 253 #define WAIT_FOR_RESUME_ACK_MS 50 254 255 /** 256 * ish_resume_handler() - Work function to complete resume 257 * @work: work struct 258 * 259 * The resume work function to complete resume function asynchronously. 260 * There are two resume paths, one where ISH is not powered off, 261 * in that case a simple resume message is enough, others we need 262 * a reset sequence. 263 */ 264 static void __maybe_unused ish_resume_handler(struct work_struct *work) 265 { 266 struct pci_dev *pdev = to_pci_dev(ish_resume_device); 267 struct ishtp_device *dev = pci_get_drvdata(pdev); 268 uint32_t fwsts = dev->ops->get_fw_status(dev); 269 270 if (ish_should_leave_d0i3(pdev) && !dev->suspend_flag 271 && IPC_IS_ISH_ILUP(fwsts)) { 272 if (device_may_wakeup(&pdev->dev)) 273 disable_irq_wake(pdev->irq); 274 275 ish_set_host_ready(dev); 276 277 ishtp_send_resume(dev); 278 279 /* Waiting to get resume response */ 280 if (dev->resume_flag) 281 wait_event_interruptible_timeout(dev->resume_wait, 282 !dev->resume_flag, 283 msecs_to_jiffies(WAIT_FOR_RESUME_ACK_MS)); 284 285 /* 286 * If the flag is not cleared, something is wrong with ISH FW. 287 * So on resume, need to go through init sequence again. 288 */ 289 if (dev->resume_flag) 290 ish_init(dev); 291 } else { 292 /* 293 * Resume from the D3, full reboot of ISH processor will happen, 294 * so need to go through init sequence again. 295 */ 296 ish_init(dev); 297 } 298 } 299 300 /** 301 * ish_suspend() - ISH suspend callback 302 * @device: device pointer 303 * 304 * ISH suspend callback 305 * 306 * Return: 0 to the pm core 307 */ 308 static int __maybe_unused ish_suspend(struct device *device) 309 { 310 struct pci_dev *pdev = to_pci_dev(device); 311 struct ishtp_device *dev = pci_get_drvdata(pdev); 312 313 if (ish_should_enter_d0i3(pdev)) { 314 /* 315 * If previous suspend hasn't been asnwered then ISH is likely 316 * dead, don't attempt nested notification 317 */ 318 if (dev->suspend_flag) 319 return 0; 320 321 dev->resume_flag = 0; 322 dev->suspend_flag = 1; 323 ishtp_send_suspend(dev); 324 325 /* 25 ms should be enough for live ISH to flush all IPC buf */ 326 if (dev->suspend_flag) 327 wait_event_interruptible_timeout(dev->suspend_wait, 328 !dev->suspend_flag, 329 msecs_to_jiffies(25)); 330 331 if (dev->suspend_flag) { 332 /* 333 * It looks like FW halt, clear the DMA bit, and put 334 * ISH into D3, and FW would reset on resume. 335 */ 336 ish_disable_dma(dev); 337 } else { 338 /* 339 * Save state so PCI core will keep the device at D0, 340 * the ISH would enter D0i3 341 */ 342 pci_save_state(pdev); 343 344 if (device_may_wakeup(&pdev->dev)) 345 enable_irq_wake(pdev->irq); 346 } 347 } else { 348 /* 349 * Clear the DMA bit before putting ISH into D3, 350 * or ISH FW would reset automatically. 351 */ 352 ish_disable_dma(dev); 353 } 354 355 return 0; 356 } 357 358 static __maybe_unused DECLARE_WORK(resume_work, ish_resume_handler); 359 /** 360 * ish_resume() - ISH resume callback 361 * @device: device pointer 362 * 363 * ISH resume callback 364 * 365 * Return: 0 to the pm core 366 */ 367 static int __maybe_unused ish_resume(struct device *device) 368 { 369 struct pci_dev *pdev = to_pci_dev(device); 370 struct ishtp_device *dev = pci_get_drvdata(pdev); 371 372 /* add this to finish power flow for EHL */ 373 if (dev->pdev->device == EHL_Ax_DEVICE_ID) { 374 pci_set_power_state(pdev, PCI_D0); 375 enable_pme_wake(pdev); 376 dev_dbg(dev->devc, "set power state to D0 for ehl\n"); 377 } 378 379 ish_resume_device = device; 380 dev->resume_flag = 1; 381 382 schedule_work(&resume_work); 383 384 return 0; 385 } 386 387 static SIMPLE_DEV_PM_OPS(ish_pm_ops, ish_suspend, ish_resume); 388 389 static struct pci_driver ish_driver = { 390 .name = KBUILD_MODNAME, 391 .id_table = ish_pci_tbl, 392 .probe = ish_probe, 393 .remove = ish_remove, 394 .driver.pm = &ish_pm_ops, 395 }; 396 397 module_pci_driver(ish_driver); 398 399 /* Original author */ 400 MODULE_AUTHOR("Daniel Drubin <daniel.drubin@intel.com>"); 401 /* Adoption to upstream Linux kernel */ 402 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 403 404 MODULE_DESCRIPTION("Intel(R) Integrated Sensor Hub PCI Device Driver"); 405 MODULE_LICENSE("GPL"); 406