1795536acSTomas Winkler /* 2795536acSTomas Winkler * 3795536acSTomas Winkler * Intel Management Engine Interface (Intel MEI) Linux driver 4795536acSTomas Winkler * Copyright (c) 2013-2014, Intel Corporation. 5795536acSTomas Winkler * 6795536acSTomas Winkler * This program is free software; you can redistribute it and/or modify it 7795536acSTomas Winkler * under the terms and conditions of the GNU General Public License, 8795536acSTomas Winkler * version 2, as published by the Free Software Foundation. 9795536acSTomas Winkler * 10795536acSTomas Winkler * This program is distributed in the hope it will be useful, but WITHOUT 11795536acSTomas Winkler * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12795536acSTomas Winkler * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13795536acSTomas Winkler * more details. 14795536acSTomas Winkler * 15795536acSTomas Winkler */ 16795536acSTomas Winkler 17795536acSTomas Winkler #include <linux/module.h> 18795536acSTomas Winkler #include <linux/kernel.h> 19795536acSTomas Winkler #include <linux/device.h> 20795536acSTomas Winkler #include <linux/fs.h> 21795536acSTomas Winkler #include <linux/errno.h> 22795536acSTomas Winkler #include <linux/types.h> 23795536acSTomas Winkler #include <linux/pci.h> 24795536acSTomas Winkler #include <linux/init.h> 25795536acSTomas Winkler #include <linux/sched.h> 26795536acSTomas Winkler #include <linux/uuid.h> 27795536acSTomas Winkler #include <linux/jiffies.h> 28795536acSTomas Winkler #include <linux/interrupt.h> 29795536acSTomas Winkler #include <linux/workqueue.h> 30cfe5ab85SAlexander Usyskin #include <linux/pm_runtime.h> 31795536acSTomas Winkler 32795536acSTomas Winkler #include <linux/mei.h> 33795536acSTomas Winkler 34795536acSTomas Winkler 35795536acSTomas Winkler #include "mei_dev.h" 36795536acSTomas Winkler #include "hw-txe.h" 37795536acSTomas Winkler 38a05f8f86STomas Winkler static const struct pci_device_id mei_txe_pci_tbl[] = { 398d929d48SAlexander Usyskin {MEI_PCI_DEVICE(0x0F18, mei_txe_cfg)}, /* Baytrail */ 40795536acSTomas Winkler {0, } 41795536acSTomas Winkler }; 42795536acSTomas Winkler MODULE_DEVICE_TABLE(pci, mei_txe_pci_tbl); 43795536acSTomas Winkler 44d2d56faeSAlexander Usyskin #ifdef CONFIG_PM_RUNTIME 45d2d56faeSAlexander Usyskin static inline void mei_txe_set_pm_domain(struct mei_device *dev); 46d2d56faeSAlexander Usyskin static inline void mei_txe_unset_pm_domain(struct mei_device *dev); 47d2d56faeSAlexander Usyskin #else 48d2d56faeSAlexander Usyskin static inline void mei_txe_set_pm_domain(struct mei_device *dev) {} 49d2d56faeSAlexander Usyskin static inline void mei_txe_unset_pm_domain(struct mei_device *dev) {} 50d2d56faeSAlexander Usyskin #endif /* CONFIG_PM_RUNTIME */ 51795536acSTomas Winkler 52795536acSTomas Winkler static void mei_txe_pci_iounmap(struct pci_dev *pdev, struct mei_txe_hw *hw) 53795536acSTomas Winkler { 54795536acSTomas Winkler int i; 5592db1555STomas Winkler 56795536acSTomas Winkler for (i = SEC_BAR; i < NUM_OF_MEM_BARS; i++) { 57795536acSTomas Winkler if (hw->mem_addr[i]) { 58795536acSTomas Winkler pci_iounmap(pdev, hw->mem_addr[i]); 59795536acSTomas Winkler hw->mem_addr[i] = NULL; 60795536acSTomas Winkler } 61795536acSTomas Winkler } 62795536acSTomas Winkler } 63795536acSTomas Winkler /** 64795536acSTomas Winkler * mei_probe - Device Initialization Routine 65795536acSTomas Winkler * 66795536acSTomas Winkler * @pdev: PCI device structure 67795536acSTomas Winkler * @ent: entry in mei_txe_pci_tbl 68795536acSTomas Winkler * 69795536acSTomas Winkler * returns 0 on success, <0 on failure. 70795536acSTomas Winkler */ 71795536acSTomas Winkler static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 72795536acSTomas Winkler { 738d929d48SAlexander Usyskin const struct mei_cfg *cfg = (struct mei_cfg *)(ent->driver_data); 74795536acSTomas Winkler struct mei_device *dev; 75795536acSTomas Winkler struct mei_txe_hw *hw; 76795536acSTomas Winkler int err; 77795536acSTomas Winkler int i; 78795536acSTomas Winkler 79795536acSTomas Winkler /* enable pci dev */ 80795536acSTomas Winkler err = pci_enable_device(pdev); 81795536acSTomas Winkler if (err) { 82795536acSTomas Winkler dev_err(&pdev->dev, "failed to enable pci device.\n"); 83795536acSTomas Winkler goto end; 84795536acSTomas Winkler } 85795536acSTomas Winkler /* set PCI host mastering */ 86795536acSTomas Winkler pci_set_master(pdev); 87795536acSTomas Winkler /* pci request regions for mei driver */ 88795536acSTomas Winkler err = pci_request_regions(pdev, KBUILD_MODNAME); 89795536acSTomas Winkler if (err) { 90795536acSTomas Winkler dev_err(&pdev->dev, "failed to get pci regions.\n"); 91795536acSTomas Winkler goto disable_device; 92795536acSTomas Winkler } 93795536acSTomas Winkler 94795536acSTomas Winkler err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); 95795536acSTomas Winkler if (err) { 96795536acSTomas Winkler err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); 97795536acSTomas Winkler if (err) { 98795536acSTomas Winkler dev_err(&pdev->dev, "No suitable DMA available.\n"); 99795536acSTomas Winkler goto release_regions; 100795536acSTomas Winkler } 101795536acSTomas Winkler } 102795536acSTomas Winkler 103795536acSTomas Winkler /* allocates and initializes the mei dev structure */ 1048d929d48SAlexander Usyskin dev = mei_txe_dev_init(pdev, cfg); 105795536acSTomas Winkler if (!dev) { 106795536acSTomas Winkler err = -ENOMEM; 107795536acSTomas Winkler goto release_regions; 108795536acSTomas Winkler } 109795536acSTomas Winkler hw = to_txe_hw(dev); 110795536acSTomas Winkler 111795536acSTomas Winkler /* mapping IO device memory */ 112795536acSTomas Winkler for (i = SEC_BAR; i < NUM_OF_MEM_BARS; i++) { 113795536acSTomas Winkler hw->mem_addr[i] = pci_iomap(pdev, i, 0); 114795536acSTomas Winkler if (!hw->mem_addr[i]) { 115795536acSTomas Winkler dev_err(&pdev->dev, "mapping I/O device memory failure.\n"); 116795536acSTomas Winkler err = -ENOMEM; 117795536acSTomas Winkler goto free_device; 118795536acSTomas Winkler } 119795536acSTomas Winkler } 120795536acSTomas Winkler 121795536acSTomas Winkler 122795536acSTomas Winkler pci_enable_msi(pdev); 123795536acSTomas Winkler 124795536acSTomas Winkler /* clear spurious interrupts */ 125795536acSTomas Winkler mei_clear_interrupts(dev); 126795536acSTomas Winkler 127795536acSTomas Winkler /* request and enable interrupt */ 128795536acSTomas Winkler if (pci_dev_msi_enabled(pdev)) 129795536acSTomas Winkler err = request_threaded_irq(pdev->irq, 130795536acSTomas Winkler NULL, 131795536acSTomas Winkler mei_txe_irq_thread_handler, 132795536acSTomas Winkler IRQF_ONESHOT, KBUILD_MODNAME, dev); 133795536acSTomas Winkler else 134795536acSTomas Winkler err = request_threaded_irq(pdev->irq, 135795536acSTomas Winkler mei_txe_irq_quick_handler, 136795536acSTomas Winkler mei_txe_irq_thread_handler, 137795536acSTomas Winkler IRQF_SHARED, KBUILD_MODNAME, dev); 138795536acSTomas Winkler if (err) { 139795536acSTomas Winkler dev_err(&pdev->dev, "mei: request_threaded_irq failure. irq = %d\n", 140795536acSTomas Winkler pdev->irq); 141795536acSTomas Winkler goto free_device; 142795536acSTomas Winkler } 143795536acSTomas Winkler 144795536acSTomas Winkler if (mei_start(dev)) { 145795536acSTomas Winkler dev_err(&pdev->dev, "init hw failure.\n"); 146795536acSTomas Winkler err = -ENODEV; 147795536acSTomas Winkler goto release_irq; 148795536acSTomas Winkler } 149795536acSTomas Winkler 150cfe5ab85SAlexander Usyskin pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_TXI_RPM_TIMEOUT); 151cfe5ab85SAlexander Usyskin pm_runtime_use_autosuspend(&pdev->dev); 152cfe5ab85SAlexander Usyskin 153f3d8e878SAlexander Usyskin err = mei_register(dev, &pdev->dev); 154795536acSTomas Winkler if (err) 155795536acSTomas Winkler goto release_irq; 156795536acSTomas Winkler 157795536acSTomas Winkler pci_set_drvdata(pdev, dev); 158795536acSTomas Winkler 159d2d56faeSAlexander Usyskin /* 160d2d56faeSAlexander Usyskin * For not wake-able HW runtime pm framework 161d2d56faeSAlexander Usyskin * can't be used on pci device level. 162d2d56faeSAlexander Usyskin * Use domain runtime pm callbacks instead. 163d2d56faeSAlexander Usyskin */ 164d2d56faeSAlexander Usyskin if (!pci_dev_run_wake(pdev)) 165d2d56faeSAlexander Usyskin mei_txe_set_pm_domain(dev); 166d2d56faeSAlexander Usyskin 167cfe5ab85SAlexander Usyskin pm_runtime_put_noidle(&pdev->dev); 168cfe5ab85SAlexander Usyskin 169795536acSTomas Winkler return 0; 170795536acSTomas Winkler 171795536acSTomas Winkler release_irq: 172795536acSTomas Winkler 173795536acSTomas Winkler mei_cancel_work(dev); 174795536acSTomas Winkler 175795536acSTomas Winkler /* disable interrupts */ 176795536acSTomas Winkler mei_disable_interrupts(dev); 177795536acSTomas Winkler 178795536acSTomas Winkler free_irq(pdev->irq, dev); 179795536acSTomas Winkler pci_disable_msi(pdev); 180795536acSTomas Winkler 181795536acSTomas Winkler free_device: 182795536acSTomas Winkler mei_txe_pci_iounmap(pdev, hw); 183795536acSTomas Winkler 184795536acSTomas Winkler kfree(dev); 185795536acSTomas Winkler release_regions: 186795536acSTomas Winkler pci_release_regions(pdev); 187795536acSTomas Winkler disable_device: 188795536acSTomas Winkler pci_disable_device(pdev); 189795536acSTomas Winkler end: 190795536acSTomas Winkler dev_err(&pdev->dev, "initialization failed.\n"); 191795536acSTomas Winkler return err; 192795536acSTomas Winkler } 193795536acSTomas Winkler 194795536acSTomas Winkler /** 195795536acSTomas Winkler * mei_remove - Device Removal Routine 196795536acSTomas Winkler * 197795536acSTomas Winkler * @pdev: PCI device structure 198795536acSTomas Winkler * 199795536acSTomas Winkler * mei_remove is called by the PCI subsystem to alert the driver 200795536acSTomas Winkler * that it should release a PCI device. 201795536acSTomas Winkler */ 202795536acSTomas Winkler static void mei_txe_remove(struct pci_dev *pdev) 203795536acSTomas Winkler { 204795536acSTomas Winkler struct mei_device *dev; 205795536acSTomas Winkler struct mei_txe_hw *hw; 206795536acSTomas Winkler 207795536acSTomas Winkler dev = pci_get_drvdata(pdev); 208795536acSTomas Winkler if (!dev) { 209795536acSTomas Winkler dev_err(&pdev->dev, "mei: dev =NULL\n"); 210795536acSTomas Winkler return; 211795536acSTomas Winkler } 212795536acSTomas Winkler 213cfe5ab85SAlexander Usyskin pm_runtime_get_noresume(&pdev->dev); 214cfe5ab85SAlexander Usyskin 215795536acSTomas Winkler hw = to_txe_hw(dev); 216795536acSTomas Winkler 217795536acSTomas Winkler mei_stop(dev); 218795536acSTomas Winkler 219d2d56faeSAlexander Usyskin if (!pci_dev_run_wake(pdev)) 220d2d56faeSAlexander Usyskin mei_txe_unset_pm_domain(dev); 221d2d56faeSAlexander Usyskin 222795536acSTomas Winkler /* disable interrupts */ 223795536acSTomas Winkler mei_disable_interrupts(dev); 224795536acSTomas Winkler free_irq(pdev->irq, dev); 225795536acSTomas Winkler pci_disable_msi(pdev); 226795536acSTomas Winkler 227795536acSTomas Winkler pci_set_drvdata(pdev, NULL); 228795536acSTomas Winkler 229795536acSTomas Winkler mei_txe_pci_iounmap(pdev, hw); 230795536acSTomas Winkler 231795536acSTomas Winkler mei_deregister(dev); 232795536acSTomas Winkler 233795536acSTomas Winkler kfree(dev); 234795536acSTomas Winkler 235795536acSTomas Winkler pci_release_regions(pdev); 236795536acSTomas Winkler pci_disable_device(pdev); 237795536acSTomas Winkler } 238795536acSTomas Winkler 239795536acSTomas Winkler 240e0270addSTomas Winkler #ifdef CONFIG_PM_SLEEP 241795536acSTomas Winkler static int mei_txe_pci_suspend(struct device *device) 242795536acSTomas Winkler { 243795536acSTomas Winkler struct pci_dev *pdev = to_pci_dev(device); 244795536acSTomas Winkler struct mei_device *dev = pci_get_drvdata(pdev); 245795536acSTomas Winkler 246795536acSTomas Winkler if (!dev) 247795536acSTomas Winkler return -ENODEV; 248795536acSTomas Winkler 249795536acSTomas Winkler dev_dbg(&pdev->dev, "suspend\n"); 250795536acSTomas Winkler 251795536acSTomas Winkler mei_stop(dev); 252795536acSTomas Winkler 253795536acSTomas Winkler mei_disable_interrupts(dev); 254795536acSTomas Winkler 255795536acSTomas Winkler free_irq(pdev->irq, dev); 256795536acSTomas Winkler pci_disable_msi(pdev); 257795536acSTomas Winkler 258795536acSTomas Winkler return 0; 259795536acSTomas Winkler } 260795536acSTomas Winkler 261795536acSTomas Winkler static int mei_txe_pci_resume(struct device *device) 262795536acSTomas Winkler { 263795536acSTomas Winkler struct pci_dev *pdev = to_pci_dev(device); 264795536acSTomas Winkler struct mei_device *dev; 265795536acSTomas Winkler int err; 266795536acSTomas Winkler 267795536acSTomas Winkler dev = pci_get_drvdata(pdev); 268795536acSTomas Winkler if (!dev) 269795536acSTomas Winkler return -ENODEV; 270795536acSTomas Winkler 271795536acSTomas Winkler pci_enable_msi(pdev); 272795536acSTomas Winkler 273795536acSTomas Winkler mei_clear_interrupts(dev); 274795536acSTomas Winkler 275795536acSTomas Winkler /* request and enable interrupt */ 276795536acSTomas Winkler if (pci_dev_msi_enabled(pdev)) 277795536acSTomas Winkler err = request_threaded_irq(pdev->irq, 278795536acSTomas Winkler NULL, 279795536acSTomas Winkler mei_txe_irq_thread_handler, 280795536acSTomas Winkler IRQF_ONESHOT, KBUILD_MODNAME, dev); 281795536acSTomas Winkler else 282795536acSTomas Winkler err = request_threaded_irq(pdev->irq, 283795536acSTomas Winkler mei_txe_irq_quick_handler, 284795536acSTomas Winkler mei_txe_irq_thread_handler, 285795536acSTomas Winkler IRQF_SHARED, KBUILD_MODNAME, dev); 286795536acSTomas Winkler if (err) { 287795536acSTomas Winkler dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n", 288795536acSTomas Winkler pdev->irq); 289795536acSTomas Winkler return err; 290795536acSTomas Winkler } 291795536acSTomas Winkler 292795536acSTomas Winkler err = mei_restart(dev); 293795536acSTomas Winkler 294795536acSTomas Winkler return err; 295795536acSTomas Winkler } 296cfe5ab85SAlexander Usyskin #endif /* CONFIG_PM_SLEEP */ 297795536acSTomas Winkler 298cfe5ab85SAlexander Usyskin #ifdef CONFIG_PM_RUNTIME 299cfe5ab85SAlexander Usyskin static int mei_txe_pm_runtime_idle(struct device *device) 300cfe5ab85SAlexander Usyskin { 301cfe5ab85SAlexander Usyskin struct pci_dev *pdev = to_pci_dev(device); 302cfe5ab85SAlexander Usyskin struct mei_device *dev; 303cfe5ab85SAlexander Usyskin 304cfe5ab85SAlexander Usyskin dev_dbg(&pdev->dev, "rpm: txe: runtime_idle\n"); 305cfe5ab85SAlexander Usyskin 306cfe5ab85SAlexander Usyskin dev = pci_get_drvdata(pdev); 307cfe5ab85SAlexander Usyskin if (!dev) 308cfe5ab85SAlexander Usyskin return -ENODEV; 309cfe5ab85SAlexander Usyskin if (mei_write_is_idle(dev)) 310d5d83f8aSAlexander Usyskin pm_runtime_autosuspend(device); 311cfe5ab85SAlexander Usyskin 312cfe5ab85SAlexander Usyskin return -EBUSY; 313cfe5ab85SAlexander Usyskin } 314cfe5ab85SAlexander Usyskin static int mei_txe_pm_runtime_suspend(struct device *device) 315cfe5ab85SAlexander Usyskin { 316cfe5ab85SAlexander Usyskin struct pci_dev *pdev = to_pci_dev(device); 317cfe5ab85SAlexander Usyskin struct mei_device *dev; 318cfe5ab85SAlexander Usyskin int ret; 319cfe5ab85SAlexander Usyskin 320cfe5ab85SAlexander Usyskin dev_dbg(&pdev->dev, "rpm: txe: runtime suspend\n"); 321cfe5ab85SAlexander Usyskin 322cfe5ab85SAlexander Usyskin dev = pci_get_drvdata(pdev); 323cfe5ab85SAlexander Usyskin if (!dev) 324cfe5ab85SAlexander Usyskin return -ENODEV; 325cfe5ab85SAlexander Usyskin 326cfe5ab85SAlexander Usyskin mutex_lock(&dev->device_lock); 327cfe5ab85SAlexander Usyskin 328cfe5ab85SAlexander Usyskin if (mei_write_is_idle(dev)) 329cfe5ab85SAlexander Usyskin ret = mei_txe_aliveness_set_sync(dev, 0); 330cfe5ab85SAlexander Usyskin else 331cfe5ab85SAlexander Usyskin ret = -EAGAIN; 332cfe5ab85SAlexander Usyskin 333cfe5ab85SAlexander Usyskin /* 334cfe5ab85SAlexander Usyskin * If everything is okay we're about to enter PCI low 335cfe5ab85SAlexander Usyskin * power state (D3) therefor we need to disable the 336cfe5ab85SAlexander Usyskin * interrupts towards host. 337cfe5ab85SAlexander Usyskin * However if device is not wakeable we do not enter 338cfe5ab85SAlexander Usyskin * D-low state and we need to keep the interrupt kicking 339cfe5ab85SAlexander Usyskin */ 340cfe5ab85SAlexander Usyskin if (!ret && pci_dev_run_wake(pdev)) 341cfe5ab85SAlexander Usyskin mei_disable_interrupts(dev); 342cfe5ab85SAlexander Usyskin 343cfe5ab85SAlexander Usyskin dev_dbg(&pdev->dev, "rpm: txe: runtime suspend ret=%d\n", ret); 344cfe5ab85SAlexander Usyskin 345cfe5ab85SAlexander Usyskin mutex_unlock(&dev->device_lock); 346cfe5ab85SAlexander Usyskin return ret; 347cfe5ab85SAlexander Usyskin } 348cfe5ab85SAlexander Usyskin 349cfe5ab85SAlexander Usyskin static int mei_txe_pm_runtime_resume(struct device *device) 350cfe5ab85SAlexander Usyskin { 351cfe5ab85SAlexander Usyskin struct pci_dev *pdev = to_pci_dev(device); 352cfe5ab85SAlexander Usyskin struct mei_device *dev; 353cfe5ab85SAlexander Usyskin int ret; 354cfe5ab85SAlexander Usyskin 355cfe5ab85SAlexander Usyskin dev_dbg(&pdev->dev, "rpm: txe: runtime resume\n"); 356cfe5ab85SAlexander Usyskin 357cfe5ab85SAlexander Usyskin dev = pci_get_drvdata(pdev); 358cfe5ab85SAlexander Usyskin if (!dev) 359cfe5ab85SAlexander Usyskin return -ENODEV; 360cfe5ab85SAlexander Usyskin 361cfe5ab85SAlexander Usyskin mutex_lock(&dev->device_lock); 362cfe5ab85SAlexander Usyskin 363cfe5ab85SAlexander Usyskin mei_enable_interrupts(dev); 364cfe5ab85SAlexander Usyskin 365cfe5ab85SAlexander Usyskin ret = mei_txe_aliveness_set_sync(dev, 1); 366cfe5ab85SAlexander Usyskin 367cfe5ab85SAlexander Usyskin mutex_unlock(&dev->device_lock); 368cfe5ab85SAlexander Usyskin 369cfe5ab85SAlexander Usyskin dev_dbg(&pdev->dev, "rpm: txe: runtime resume ret = %d\n", ret); 370cfe5ab85SAlexander Usyskin 371cfe5ab85SAlexander Usyskin return ret; 372cfe5ab85SAlexander Usyskin } 373d2d56faeSAlexander Usyskin 374d2d56faeSAlexander Usyskin /** 375d2d56faeSAlexander Usyskin * mei_txe_set_pm_domain - fill and set pm domian stucture for device 376d2d56faeSAlexander Usyskin * 377d2d56faeSAlexander Usyskin * @dev: mei_device 378d2d56faeSAlexander Usyskin */ 379d2d56faeSAlexander Usyskin static inline void mei_txe_set_pm_domain(struct mei_device *dev) 380d2d56faeSAlexander Usyskin { 381*d08b8fc0STomas Winkler struct pci_dev *pdev = to_pci_dev(dev->dev); 382d2d56faeSAlexander Usyskin 383d2d56faeSAlexander Usyskin if (pdev->dev.bus && pdev->dev.bus->pm) { 384d2d56faeSAlexander Usyskin dev->pg_domain.ops = *pdev->dev.bus->pm; 385d2d56faeSAlexander Usyskin 386d2d56faeSAlexander Usyskin dev->pg_domain.ops.runtime_suspend = mei_txe_pm_runtime_suspend; 387d2d56faeSAlexander Usyskin dev->pg_domain.ops.runtime_resume = mei_txe_pm_runtime_resume; 388d2d56faeSAlexander Usyskin dev->pg_domain.ops.runtime_idle = mei_txe_pm_runtime_idle; 389d2d56faeSAlexander Usyskin 390d2d56faeSAlexander Usyskin pdev->dev.pm_domain = &dev->pg_domain; 391d2d56faeSAlexander Usyskin } 392d2d56faeSAlexander Usyskin } 393d2d56faeSAlexander Usyskin 394d2d56faeSAlexander Usyskin /** 395d2d56faeSAlexander Usyskin * mei_txe_unset_pm_domain - clean pm domian stucture for device 396d2d56faeSAlexander Usyskin * 397d2d56faeSAlexander Usyskin * @dev: mei_device 398d2d56faeSAlexander Usyskin */ 399d2d56faeSAlexander Usyskin static inline void mei_txe_unset_pm_domain(struct mei_device *dev) 400d2d56faeSAlexander Usyskin { 401d2d56faeSAlexander Usyskin /* stop using pm callbacks if any */ 4022bf94cabSTomas Winkler dev->dev->pm_domain = NULL; 403d2d56faeSAlexander Usyskin } 404cfe5ab85SAlexander Usyskin #endif /* CONFIG_PM_RUNTIME */ 405cfe5ab85SAlexander Usyskin 406cfe5ab85SAlexander Usyskin #ifdef CONFIG_PM 407cfe5ab85SAlexander Usyskin static const struct dev_pm_ops mei_txe_pm_ops = { 408cfe5ab85SAlexander Usyskin SET_SYSTEM_SLEEP_PM_OPS(mei_txe_pci_suspend, 409cfe5ab85SAlexander Usyskin mei_txe_pci_resume) 410cfe5ab85SAlexander Usyskin SET_RUNTIME_PM_OPS( 411cfe5ab85SAlexander Usyskin mei_txe_pm_runtime_suspend, 412cfe5ab85SAlexander Usyskin mei_txe_pm_runtime_resume, 413cfe5ab85SAlexander Usyskin mei_txe_pm_runtime_idle) 414cfe5ab85SAlexander Usyskin }; 415795536acSTomas Winkler 416795536acSTomas Winkler #define MEI_TXE_PM_OPS (&mei_txe_pm_ops) 417795536acSTomas Winkler #else 418795536acSTomas Winkler #define MEI_TXE_PM_OPS NULL 419cfe5ab85SAlexander Usyskin #endif /* CONFIG_PM */ 420cfe5ab85SAlexander Usyskin 421795536acSTomas Winkler /* 422795536acSTomas Winkler * PCI driver structure 423795536acSTomas Winkler */ 424795536acSTomas Winkler static struct pci_driver mei_txe_driver = { 425795536acSTomas Winkler .name = KBUILD_MODNAME, 426795536acSTomas Winkler .id_table = mei_txe_pci_tbl, 427795536acSTomas Winkler .probe = mei_txe_probe, 428795536acSTomas Winkler .remove = mei_txe_remove, 429795536acSTomas Winkler .shutdown = mei_txe_remove, 430795536acSTomas Winkler .driver.pm = MEI_TXE_PM_OPS, 431795536acSTomas Winkler }; 432795536acSTomas Winkler 433795536acSTomas Winkler module_pci_driver(mei_txe_driver); 434795536acSTomas Winkler 435795536acSTomas Winkler MODULE_AUTHOR("Intel Corporation"); 436795536acSTomas Winkler MODULE_DESCRIPTION("Intel(R) Trusted Execution Environment Interface"); 437795536acSTomas Winkler MODULE_LICENSE("GPL v2"); 438