1/* 2 * 3 * Intel Management Engine Interface (Intel MEI) Linux driver 4 * Copyright (c) 2013-2014, Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 */ 16 17#include <linux/module.h> 18#include <linux/kernel.h> 19#include <linux/device.h> 20#include <linux/fs.h> 21#include <linux/errno.h> 22#include <linux/types.h> 23#include <linux/pci.h> 24#include <linux/init.h> 25#include <linux/sched.h> 26#include <linux/uuid.h> 27#include <linux/jiffies.h> 28#include <linux/interrupt.h> 29#include <linux/workqueue.h> 30#include <linux/pm_runtime.h> 31 32#include <linux/mei.h> 33 34 35#include "mei_dev.h" 36#include "hw-txe.h" 37 38static const struct pci_device_id mei_txe_pci_tbl[] = { 39 {PCI_VDEVICE(INTEL, 0x0F18)}, /* Baytrail */ 40 {PCI_VDEVICE(INTEL, 0x2298)}, /* Cherrytrail */ 41 42 {0, } 43}; 44MODULE_DEVICE_TABLE(pci, mei_txe_pci_tbl); 45 46#ifdef CONFIG_PM 47static inline void mei_txe_set_pm_domain(struct mei_device *dev); 48static inline void mei_txe_unset_pm_domain(struct mei_device *dev); 49#else 50static inline void mei_txe_set_pm_domain(struct mei_device *dev) {} 51static inline void mei_txe_unset_pm_domain(struct mei_device *dev) {} 52#endif /* CONFIG_PM */ 53 54static void mei_txe_pci_iounmap(struct pci_dev *pdev, struct mei_txe_hw *hw) 55{ 56 int i; 57 58 for (i = SEC_BAR; i < NUM_OF_MEM_BARS; i++) { 59 if (hw->mem_addr[i]) { 60 pci_iounmap(pdev, hw->mem_addr[i]); 61 hw->mem_addr[i] = NULL; 62 } 63 } 64} 65/** 66 * mei_txe_probe - Device Initialization Routine 67 * 68 * @pdev: PCI device structure 69 * @ent: entry in mei_txe_pci_tbl 70 * 71 * Return: 0 on success, <0 on failure. 72 */ 73static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 74{ 75 struct mei_device *dev; 76 struct mei_txe_hw *hw; 77 int err; 78 int i; 79 80 /* enable pci dev */ 81 err = pci_enable_device(pdev); 82 if (err) { 83 dev_err(&pdev->dev, "failed to enable pci device.\n"); 84 goto end; 85 } 86 /* set PCI host mastering */ 87 pci_set_master(pdev); 88 /* pci request regions for mei driver */ 89 err = pci_request_regions(pdev, KBUILD_MODNAME); 90 if (err) { 91 dev_err(&pdev->dev, "failed to get pci regions.\n"); 92 goto disable_device; 93 } 94 95 err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); 96 if (err) { 97 err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); 98 if (err) { 99 dev_err(&pdev->dev, "No suitable DMA available.\n"); 100 goto release_regions; 101 } 102 } 103 104 /* allocates and initializes the mei dev structure */ 105 dev = mei_txe_dev_init(pdev); 106 if (!dev) { 107 err = -ENOMEM; 108 goto release_regions; 109 } 110 hw = to_txe_hw(dev); 111 112 /* mapping IO device memory */ 113 for (i = SEC_BAR; i < NUM_OF_MEM_BARS; i++) { 114 hw->mem_addr[i] = pci_iomap(pdev, i, 0); 115 if (!hw->mem_addr[i]) { 116 dev_err(&pdev->dev, "mapping I/O device memory failure.\n"); 117 err = -ENOMEM; 118 goto free_device; 119 } 120 } 121 122 123 pci_enable_msi(pdev); 124 125 /* clear spurious interrupts */ 126 mei_clear_interrupts(dev); 127 128 /* request and enable interrupt */ 129 if (pci_dev_msi_enabled(pdev)) 130 err = request_threaded_irq(pdev->irq, 131 NULL, 132 mei_txe_irq_thread_handler, 133 IRQF_ONESHOT, KBUILD_MODNAME, dev); 134 else 135 err = request_threaded_irq(pdev->irq, 136 mei_txe_irq_quick_handler, 137 mei_txe_irq_thread_handler, 138 IRQF_SHARED, KBUILD_MODNAME, dev); 139 if (err) { 140 dev_err(&pdev->dev, "mei: request_threaded_irq failure. irq = %d\n", 141 pdev->irq); 142 goto free_device; 143 } 144 145 if (mei_start(dev)) { 146 dev_err(&pdev->dev, "init hw failure.\n"); 147 err = -ENODEV; 148 goto release_irq; 149 } 150 151 pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_TXI_RPM_TIMEOUT); 152 pm_runtime_use_autosuspend(&pdev->dev); 153 154 err = mei_register(dev, &pdev->dev); 155 if (err) 156 goto release_irq; 157 158 pci_set_drvdata(pdev, dev); 159 160 /* 161 * For not wake-able HW runtime pm framework 162 * can't be used on pci device level. 163 * Use domain runtime pm callbacks instead. 164 */ 165 if (!pci_dev_run_wake(pdev)) 166 mei_txe_set_pm_domain(dev); 167 168 pm_runtime_put_noidle(&pdev->dev); 169 170 return 0; 171 172release_irq: 173 174 mei_cancel_work(dev); 175 176 /* disable interrupts */ 177 mei_disable_interrupts(dev); 178 179 free_irq(pdev->irq, dev); 180 pci_disable_msi(pdev); 181 182free_device: 183 mei_txe_pci_iounmap(pdev, hw); 184 185 kfree(dev); 186release_regions: 187 pci_release_regions(pdev); 188disable_device: 189 pci_disable_device(pdev); 190end: 191 dev_err(&pdev->dev, "initialization failed.\n"); 192 return err; 193} 194 195/** 196 * mei_txe_remove - Device Removal Routine 197 * 198 * @pdev: PCI device structure 199 * 200 * mei_remove is called by the PCI subsystem to alert the driver 201 * that it should release a PCI device. 202 */ 203static void mei_txe_remove(struct pci_dev *pdev) 204{ 205 struct mei_device *dev; 206 struct mei_txe_hw *hw; 207 208 dev = pci_get_drvdata(pdev); 209 if (!dev) { 210 dev_err(&pdev->dev, "mei: dev =NULL\n"); 211 return; 212 } 213 214 pm_runtime_get_noresume(&pdev->dev); 215 216 hw = to_txe_hw(dev); 217 218 mei_stop(dev); 219 220 if (!pci_dev_run_wake(pdev)) 221 mei_txe_unset_pm_domain(dev); 222 223 /* disable interrupts */ 224 mei_disable_interrupts(dev); 225 free_irq(pdev->irq, dev); 226 pci_disable_msi(pdev); 227 228 pci_set_drvdata(pdev, NULL); 229 230 mei_txe_pci_iounmap(pdev, hw); 231 232 mei_deregister(dev); 233 234 kfree(dev); 235 236 pci_release_regions(pdev); 237 pci_disable_device(pdev); 238} 239 240 241#ifdef CONFIG_PM_SLEEP 242static int mei_txe_pci_suspend(struct device *device) 243{ 244 struct pci_dev *pdev = to_pci_dev(device); 245 struct mei_device *dev = pci_get_drvdata(pdev); 246 247 if (!dev) 248 return -ENODEV; 249 250 dev_dbg(&pdev->dev, "suspend\n"); 251 252 mei_stop(dev); 253 254 mei_disable_interrupts(dev); 255 256 free_irq(pdev->irq, dev); 257 pci_disable_msi(pdev); 258 259 return 0; 260} 261 262static int mei_txe_pci_resume(struct device *device) 263{ 264 struct pci_dev *pdev = to_pci_dev(device); 265 struct mei_device *dev; 266 int err; 267 268 dev = pci_get_drvdata(pdev); 269 if (!dev) 270 return -ENODEV; 271 272 pci_enable_msi(pdev); 273 274 mei_clear_interrupts(dev); 275 276 /* request and enable interrupt */ 277 if (pci_dev_msi_enabled(pdev)) 278 err = request_threaded_irq(pdev->irq, 279 NULL, 280 mei_txe_irq_thread_handler, 281 IRQF_ONESHOT, KBUILD_MODNAME, dev); 282 else 283 err = request_threaded_irq(pdev->irq, 284 mei_txe_irq_quick_handler, 285 mei_txe_irq_thread_handler, 286 IRQF_SHARED, KBUILD_MODNAME, dev); 287 if (err) { 288 dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n", 289 pdev->irq); 290 return err; 291 } 292 293 err = mei_restart(dev); 294 295 return err; 296} 297#endif /* CONFIG_PM_SLEEP */ 298 299#ifdef CONFIG_PM 300static int mei_txe_pm_runtime_idle(struct device *device) 301{ 302 struct pci_dev *pdev = to_pci_dev(device); 303 struct mei_device *dev; 304 305 dev_dbg(&pdev->dev, "rpm: txe: runtime_idle\n"); 306 307 dev = pci_get_drvdata(pdev); 308 if (!dev) 309 return -ENODEV; 310 if (mei_write_is_idle(dev)) 311 pm_runtime_autosuspend(device); 312 313 return -EBUSY; 314} 315static int mei_txe_pm_runtime_suspend(struct device *device) 316{ 317 struct pci_dev *pdev = to_pci_dev(device); 318 struct mei_device *dev; 319 int ret; 320 321 dev_dbg(&pdev->dev, "rpm: txe: runtime suspend\n"); 322 323 dev = pci_get_drvdata(pdev); 324 if (!dev) 325 return -ENODEV; 326 327 mutex_lock(&dev->device_lock); 328 329 if (mei_write_is_idle(dev)) 330 ret = mei_txe_aliveness_set_sync(dev, 0); 331 else 332 ret = -EAGAIN; 333 334 /* 335 * If everything is okay we're about to enter PCI low 336 * power state (D3) therefor we need to disable the 337 * interrupts towards host. 338 * However if device is not wakeable we do not enter 339 * D-low state and we need to keep the interrupt kicking 340 */ 341 if (!ret && pci_dev_run_wake(pdev)) 342 mei_disable_interrupts(dev); 343 344 dev_dbg(&pdev->dev, "rpm: txe: runtime suspend ret=%d\n", ret); 345 346 mutex_unlock(&dev->device_lock); 347 return ret; 348} 349 350static int mei_txe_pm_runtime_resume(struct device *device) 351{ 352 struct pci_dev *pdev = to_pci_dev(device); 353 struct mei_device *dev; 354 int ret; 355 356 dev_dbg(&pdev->dev, "rpm: txe: runtime resume\n"); 357 358 dev = pci_get_drvdata(pdev); 359 if (!dev) 360 return -ENODEV; 361 362 mutex_lock(&dev->device_lock); 363 364 mei_enable_interrupts(dev); 365 366 ret = mei_txe_aliveness_set_sync(dev, 1); 367 368 mutex_unlock(&dev->device_lock); 369 370 dev_dbg(&pdev->dev, "rpm: txe: runtime resume ret = %d\n", ret); 371 372 return ret; 373} 374 375/** 376 * mei_txe_set_pm_domain - fill and set pm domain structure for device 377 * 378 * @dev: mei_device 379 */ 380static inline void mei_txe_set_pm_domain(struct mei_device *dev) 381{ 382 struct pci_dev *pdev = to_pci_dev(dev->dev); 383 384 if (pdev->dev.bus && pdev->dev.bus->pm) { 385 dev->pg_domain.ops = *pdev->dev.bus->pm; 386 387 dev->pg_domain.ops.runtime_suspend = mei_txe_pm_runtime_suspend; 388 dev->pg_domain.ops.runtime_resume = mei_txe_pm_runtime_resume; 389 dev->pg_domain.ops.runtime_idle = mei_txe_pm_runtime_idle; 390 391 pdev->dev.pm_domain = &dev->pg_domain; 392 } 393} 394 395/** 396 * mei_txe_unset_pm_domain - clean pm domain structure for device 397 * 398 * @dev: mei_device 399 */ 400static inline void mei_txe_unset_pm_domain(struct mei_device *dev) 401{ 402 /* stop using pm callbacks if any */ 403 dev->dev->pm_domain = NULL; 404} 405 406static const struct dev_pm_ops mei_txe_pm_ops = { 407 SET_SYSTEM_SLEEP_PM_OPS(mei_txe_pci_suspend, 408 mei_txe_pci_resume) 409 SET_RUNTIME_PM_OPS( 410 mei_txe_pm_runtime_suspend, 411 mei_txe_pm_runtime_resume, 412 mei_txe_pm_runtime_idle) 413}; 414 415#define MEI_TXE_PM_OPS (&mei_txe_pm_ops) 416#else 417#define MEI_TXE_PM_OPS NULL 418#endif /* CONFIG_PM */ 419 420/* 421 * PCI driver structure 422 */ 423static struct pci_driver mei_txe_driver = { 424 .name = KBUILD_MODNAME, 425 .id_table = mei_txe_pci_tbl, 426 .probe = mei_txe_probe, 427 .remove = mei_txe_remove, 428 .shutdown = mei_txe_remove, 429 .driver.pm = MEI_TXE_PM_OPS, 430}; 431 432module_pci_driver(mei_txe_driver); 433 434MODULE_AUTHOR("Intel Corporation"); 435MODULE_DESCRIPTION("Intel(R) Trusted Execution Environment Interface"); 436MODULE_LICENSE("GPL v2"); 437