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 enum ishtp_driver_data_index { 27 ISHTP_DRIVER_DATA_NONE, 28 ISHTP_DRIVER_DATA_LNL_M, 29 ISHTP_DRIVER_DATA_PTL, 30 }; 31 32 #define ISH_FW_GEN_LNL_M "lnlm" 33 #define ISH_FW_GEN_PTL "ptl" 34 35 #define ISH_FIRMWARE_PATH(gen) "intel/ish/ish_" gen ".bin" 36 #define ISH_FIRMWARE_PATH_ALL "intel/ish/ish_*.bin" 37 38 static struct ishtp_driver_data ishtp_driver_data[] = { 39 [ISHTP_DRIVER_DATA_LNL_M] = { 40 .fw_generation = ISH_FW_GEN_LNL_M, 41 }, 42 [ISHTP_DRIVER_DATA_PTL] = { 43 .fw_generation = ISH_FW_GEN_PTL, 44 }, 45 }; 46 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}, 73 {} 74 }; 75 MODULE_DEVICE_TABLE(pci, ish_pci_tbl); 76 77 /** 78 * ish_event_tracer() - Callback function to dump trace messages 79 * @dev: ishtp device 80 * @format: printf style format 81 * 82 * Callback to direct log messages to Linux trace buffers 83 */ 84 static __printf(2, 3) 85 void ish_event_tracer(struct ishtp_device *dev, const char *format, ...) 86 { 87 if (trace_ishtp_dump_enabled()) { 88 va_list args; 89 char tmp_buf[100]; 90 91 va_start(args, format); 92 vsnprintf(tmp_buf, sizeof(tmp_buf), format, args); 93 va_end(args); 94 95 trace_ishtp_dump(tmp_buf); 96 } 97 } 98 99 /** 100 * ish_init() - Init function 101 * @dev: ishtp device 102 * 103 * This function initialize wait queues for suspend/resume and call 104 * calls hadware initialization function. This will initiate 105 * startup sequence 106 * 107 * Return: 0 for success or error code for failure 108 */ 109 static int ish_init(struct ishtp_device *dev) 110 { 111 int ret; 112 113 /* Set the state of ISH HW to start */ 114 ret = ish_hw_start(dev); 115 if (ret) { 116 dev_err(dev->devc, "ISH: hw start failed.\n"); 117 return ret; 118 } 119 120 /* Start the inter process communication to ISH processor */ 121 ret = ishtp_start(dev); 122 if (ret) { 123 dev_err(dev->devc, "ISHTP: Protocol init failed.\n"); 124 return ret; 125 } 126 127 return 0; 128 } 129 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)}, 134 {} 135 }; 136 137 static inline bool ish_should_enter_d0i3(struct pci_dev *pdev) 138 { 139 return !pm_suspend_via_firmware() || pdev->device == PCI_DEVICE_ID_INTEL_ISH_CHV; 140 } 141 142 static inline bool ish_should_leave_d0i3(struct pci_dev *pdev) 143 { 144 return !pm_resume_via_firmware() || pdev->device == PCI_DEVICE_ID_INTEL_ISH_CHV; 145 } 146 147 /** 148 * ish_probe() - PCI driver probe callback 149 * @pdev: pci device 150 * @ent: pci device id 151 * 152 * Initialize PCI function, setup interrupt and call for ISH initialization 153 * 154 * Return: 0 for success or error code for failure 155 */ 156 static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 157 { 158 int ret; 159 struct ish_hw *hw; 160 unsigned long irq_flag = 0; 161 struct ishtp_device *ishtp; 162 struct device *dev = &pdev->dev; 163 164 /* Check for invalid platforms for ISH support */ 165 if (pci_dev_present(ish_invalid_pci_ids)) 166 return -ENODEV; 167 168 /* enable pci dev */ 169 ret = pcim_enable_device(pdev); 170 if (ret) { 171 dev_err(dev, "ISH: Failed to enable PCI device\n"); 172 return ret; 173 } 174 175 /* set PCI host mastering */ 176 pci_set_master(pdev); 177 178 /* pci request regions for ISH driver */ 179 ret = pcim_iomap_regions(pdev, 1 << 0, KBUILD_MODNAME); 180 if (ret) { 181 dev_err(dev, "ISH: Failed to get PCI regions\n"); 182 return ret; 183 } 184 185 /* allocates and initializes the ISH dev structure */ 186 ishtp = ish_dev_init(pdev); 187 if (!ishtp) { 188 ret = -ENOMEM; 189 return ret; 190 } 191 hw = to_ish_hw(ishtp); 192 ishtp->print_log = ish_event_tracer; 193 ishtp->driver_data = &ishtp_driver_data[ent->driver_data]; 194 195 /* mapping IO device memory */ 196 hw->mem_addr = pcim_iomap_table(pdev)[0]; 197 ishtp->pdev = pdev; 198 199 /* request and enable interrupt */ 200 ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); 201 if (ret < 0) { 202 dev_err(dev, "ISH: Failed to allocate IRQ vectors\n"); 203 return ret; 204 } 205 206 if (!pdev->msi_enabled && !pdev->msix_enabled) 207 irq_flag = IRQF_SHARED; 208 209 ret = devm_request_irq(dev, pdev->irq, ish_irq_handler, 210 irq_flag, KBUILD_MODNAME, ishtp); 211 if (ret) { 212 dev_err(dev, "ISH: request IRQ %d failed\n", pdev->irq); 213 return ret; 214 } 215 216 dev_set_drvdata(ishtp->devc, ishtp); 217 218 init_waitqueue_head(&ishtp->suspend_wait); 219 init_waitqueue_head(&ishtp->resume_wait); 220 221 /* Enable PME for EHL */ 222 if (pdev->device == PCI_DEVICE_ID_INTEL_ISH_EHL_Ax) 223 device_init_wakeup(dev, true); 224 225 ret = ish_init(ishtp); 226 if (ret) 227 return ret; 228 229 return 0; 230 } 231 232 /** 233 * ish_remove() - PCI driver remove callback 234 * @pdev: pci device 235 * 236 * This function does cleanup of ISH on pci remove callback 237 */ 238 static void ish_remove(struct pci_dev *pdev) 239 { 240 struct ishtp_device *ishtp_dev = pci_get_drvdata(pdev); 241 242 ishtp_bus_remove_all_clients(ishtp_dev, false); 243 ish_device_disable(ishtp_dev); 244 } 245 246 247 /** 248 * ish_shutdown() - PCI driver shutdown callback 249 * @pdev: pci device 250 * 251 * This function sets up wakeup for S5 252 */ 253 static void ish_shutdown(struct pci_dev *pdev) 254 { 255 if (pdev->device == PCI_DEVICE_ID_INTEL_ISH_EHL_Ax) 256 pci_prepare_to_sleep(pdev); 257 } 258 259 static struct device __maybe_unused *ish_resume_device; 260 261 /* 50ms to get resume response */ 262 #define WAIT_FOR_RESUME_ACK_MS 50 263 264 /** 265 * ish_resume_handler() - Work function to complete resume 266 * @work: work struct 267 * 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 271 * a reset sequence. 272 */ 273 static void __maybe_unused ish_resume_handler(struct work_struct *work) 274 { 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); 278 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); 283 284 ish_set_host_ready(dev); 285 286 ishtp_send_resume(dev); 287 288 /* Waiting to get resume response */ 289 if (dev->resume_flag) 290 wait_event_interruptible_timeout(dev->resume_wait, 291 !dev->resume_flag, 292 msecs_to_jiffies(WAIT_FOR_RESUME_ACK_MS)); 293 294 /* 295 * If the flag is not cleared, something is wrong with ISH FW. 296 * So on resume, need to go through init sequence again. 297 */ 298 if (dev->resume_flag) 299 ish_init(dev); 300 } else { 301 /* 302 * Resume from the D3, full reboot of ISH processor will happen, 303 * so need to go through init sequence again. 304 */ 305 ish_init(dev); 306 } 307 } 308 309 /** 310 * ish_suspend() - ISH suspend callback 311 * @device: device pointer 312 * 313 * ISH suspend callback 314 * 315 * Return: 0 to the pm core 316 */ 317 static int __maybe_unused ish_suspend(struct device *device) 318 { 319 struct pci_dev *pdev = to_pci_dev(device); 320 struct ishtp_device *dev = pci_get_drvdata(pdev); 321 322 if (ish_should_enter_d0i3(pdev)) { 323 /* 324 * If previous suspend hasn't been asnwered then ISH is likely 325 * dead, don't attempt nested notification 326 */ 327 if (dev->suspend_flag) 328 return 0; 329 330 dev->resume_flag = 0; 331 dev->suspend_flag = 1; 332 ishtp_send_suspend(dev); 333 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, 337 !dev->suspend_flag, 338 msecs_to_jiffies(25)); 339 340 if (dev->suspend_flag) { 341 /* 342 * It looks like FW halt, clear the DMA bit, and put 343 * ISH into D3, and FW would reset on resume. 344 */ 345 ish_disable_dma(dev); 346 } else { 347 /* 348 * Save state so PCI core will keep the device at D0, 349 * the ISH would enter D0i3 350 */ 351 pci_save_state(pdev); 352 353 if (device_may_wakeup(&pdev->dev)) 354 enable_irq_wake(pdev->irq); 355 } 356 } else { 357 /* 358 * Clear the DMA bit before putting ISH into D3, 359 * or ISH FW would reset automatically. 360 */ 361 ish_disable_dma(dev); 362 } 363 364 return 0; 365 } 366 367 static __maybe_unused DECLARE_WORK(resume_work, ish_resume_handler); 368 /** 369 * ish_resume() - ISH resume callback 370 * @device: device pointer 371 * 372 * ISH resume callback 373 * 374 * Return: 0 to the pm core 375 */ 376 static int __maybe_unused ish_resume(struct device *device) 377 { 378 struct pci_dev *pdev = to_pci_dev(device); 379 struct ishtp_device *dev = pci_get_drvdata(pdev); 380 381 ish_resume_device = device; 382 dev->resume_flag = 1; 383 384 schedule_work(&resume_work); 385 386 return 0; 387 } 388 389 static SIMPLE_DEV_PM_OPS(ish_pm_ops, ish_suspend, ish_resume); 390 391 static ssize_t base_version_show(struct device *cdev, 392 struct device_attribute *attr, char *buf) 393 { 394 struct ishtp_device *dev = dev_get_drvdata(cdev); 395 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); 399 } 400 static DEVICE_ATTR_RO(base_version); 401 402 static ssize_t project_version_show(struct device *cdev, 403 struct device_attribute *attr, char *buf) 404 { 405 struct ishtp_device *dev = dev_get_drvdata(cdev); 406 407 return sysfs_emit(buf, "%u.%u.%u.%u\n", dev->prj_ver.major, 408 dev->prj_ver.minor, dev->prj_ver.hotfix, 409 dev->prj_ver.build); 410 } 411 static DEVICE_ATTR_RO(project_version); 412 413 static struct attribute *ish_firmware_attrs[] = { 414 &dev_attr_base_version.attr, 415 &dev_attr_project_version.attr, 416 NULL 417 }; 418 419 static umode_t firmware_is_visible(struct kobject *kobj, struct attribute *attr, 420 int i) 421 { 422 struct ishtp_device *dev = dev_get_drvdata(kobj_to_dev(kobj)); 423 424 return dev->driver_data->fw_generation ? attr->mode : 0; 425 } 426 427 static const struct attribute_group ish_firmware_group = { 428 .name = "firmware", 429 .attrs = ish_firmware_attrs, 430 .is_visible = firmware_is_visible, 431 }; 432 433 __ATTRIBUTE_GROUPS(ish_firmware); 434 435 static struct pci_driver ish_driver = { 436 .name = KBUILD_MODNAME, 437 .id_table = ish_pci_tbl, 438 .probe = ish_probe, 439 .remove = ish_remove, 440 .shutdown = ish_shutdown, 441 .driver.pm = &ish_pm_ops, 442 .dev_groups = ish_firmware_groups, 443 }; 444 445 module_pci_driver(ish_driver); 446 447 /* Original author */ 448 MODULE_AUTHOR("Daniel Drubin <daniel.drubin@intel.com>"); 449 /* Adoption to upstream Linux kernel */ 450 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 451 452 MODULE_DESCRIPTION("Intel(R) Integrated Sensor Hub PCI Device Driver"); 453 MODULE_LICENSE("GPL"); 454 455 MODULE_FIRMWARE(ISH_FIRMWARE_PATH(ISH_FW_GEN_LNL_M)); 456 MODULE_FIRMWARE(ISH_FIRMWARE_PATH_ALL); 457