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 31 #include <linux/mei.h> 32 33 34 #include "mei_dev.h" 35 #include "hw-txe.h" 36 37 static const struct pci_device_id mei_txe_pci_tbl[] = { 38 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0F18)}, /* Baytrail */ 39 {0, } 40 }; 41 MODULE_DEVICE_TABLE(pci, mei_txe_pci_tbl); 42 43 44 static void mei_txe_pci_iounmap(struct pci_dev *pdev, struct mei_txe_hw *hw) 45 { 46 int i; 47 for (i = SEC_BAR; i < NUM_OF_MEM_BARS; i++) { 48 if (hw->mem_addr[i]) { 49 pci_iounmap(pdev, hw->mem_addr[i]); 50 hw->mem_addr[i] = NULL; 51 } 52 } 53 } 54 /** 55 * mei_probe - Device Initialization Routine 56 * 57 * @pdev: PCI device structure 58 * @ent: entry in mei_txe_pci_tbl 59 * 60 * returns 0 on success, <0 on failure. 61 */ 62 static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 63 { 64 struct mei_device *dev; 65 struct mei_txe_hw *hw; 66 int err; 67 int i; 68 69 /* enable pci dev */ 70 err = pci_enable_device(pdev); 71 if (err) { 72 dev_err(&pdev->dev, "failed to enable pci device.\n"); 73 goto end; 74 } 75 /* set PCI host mastering */ 76 pci_set_master(pdev); 77 /* pci request regions for mei driver */ 78 err = pci_request_regions(pdev, KBUILD_MODNAME); 79 if (err) { 80 dev_err(&pdev->dev, "failed to get pci regions.\n"); 81 goto disable_device; 82 } 83 84 err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); 85 if (err) { 86 err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); 87 if (err) { 88 dev_err(&pdev->dev, "No suitable DMA available.\n"); 89 goto release_regions; 90 } 91 } 92 93 /* allocates and initializes the mei dev structure */ 94 dev = mei_txe_dev_init(pdev); 95 if (!dev) { 96 err = -ENOMEM; 97 goto release_regions; 98 } 99 hw = to_txe_hw(dev); 100 101 /* mapping IO device memory */ 102 for (i = SEC_BAR; i < NUM_OF_MEM_BARS; i++) { 103 hw->mem_addr[i] = pci_iomap(pdev, i, 0); 104 if (!hw->mem_addr[i]) { 105 dev_err(&pdev->dev, "mapping I/O device memory failure.\n"); 106 err = -ENOMEM; 107 goto free_device; 108 } 109 } 110 111 112 pci_enable_msi(pdev); 113 114 /* clear spurious interrupts */ 115 mei_clear_interrupts(dev); 116 117 /* request and enable interrupt */ 118 if (pci_dev_msi_enabled(pdev)) 119 err = request_threaded_irq(pdev->irq, 120 NULL, 121 mei_txe_irq_thread_handler, 122 IRQF_ONESHOT, KBUILD_MODNAME, dev); 123 else 124 err = request_threaded_irq(pdev->irq, 125 mei_txe_irq_quick_handler, 126 mei_txe_irq_thread_handler, 127 IRQF_SHARED, KBUILD_MODNAME, dev); 128 if (err) { 129 dev_err(&pdev->dev, "mei: request_threaded_irq failure. irq = %d\n", 130 pdev->irq); 131 goto free_device; 132 } 133 134 if (mei_start(dev)) { 135 dev_err(&pdev->dev, "init hw failure.\n"); 136 err = -ENODEV; 137 goto release_irq; 138 } 139 140 err = mei_register(dev); 141 if (err) 142 goto release_irq; 143 144 pci_set_drvdata(pdev, dev); 145 146 return 0; 147 148 release_irq: 149 150 mei_cancel_work(dev); 151 152 /* disable interrupts */ 153 mei_disable_interrupts(dev); 154 155 free_irq(pdev->irq, dev); 156 pci_disable_msi(pdev); 157 158 free_device: 159 mei_txe_pci_iounmap(pdev, hw); 160 161 kfree(dev); 162 release_regions: 163 pci_release_regions(pdev); 164 disable_device: 165 pci_disable_device(pdev); 166 end: 167 dev_err(&pdev->dev, "initialization failed.\n"); 168 return err; 169 } 170 171 /** 172 * mei_remove - Device Removal Routine 173 * 174 * @pdev: PCI device structure 175 * 176 * mei_remove is called by the PCI subsystem to alert the driver 177 * that it should release a PCI device. 178 */ 179 static void mei_txe_remove(struct pci_dev *pdev) 180 { 181 struct mei_device *dev; 182 struct mei_txe_hw *hw; 183 184 dev = pci_get_drvdata(pdev); 185 if (!dev) { 186 dev_err(&pdev->dev, "mei: dev =NULL\n"); 187 return; 188 } 189 190 hw = to_txe_hw(dev); 191 192 mei_stop(dev); 193 194 /* disable interrupts */ 195 mei_disable_interrupts(dev); 196 free_irq(pdev->irq, dev); 197 pci_disable_msi(pdev); 198 199 pci_set_drvdata(pdev, NULL); 200 201 mei_txe_pci_iounmap(pdev, hw); 202 203 mei_deregister(dev); 204 205 kfree(dev); 206 207 pci_release_regions(pdev); 208 pci_disable_device(pdev); 209 } 210 211 212 #ifdef CONFIG_PM_SLEEP 213 static int mei_txe_pci_suspend(struct device *device) 214 { 215 struct pci_dev *pdev = to_pci_dev(device); 216 struct mei_device *dev = pci_get_drvdata(pdev); 217 218 if (!dev) 219 return -ENODEV; 220 221 dev_dbg(&pdev->dev, "suspend\n"); 222 223 mei_stop(dev); 224 225 mei_disable_interrupts(dev); 226 227 free_irq(pdev->irq, dev); 228 pci_disable_msi(pdev); 229 230 return 0; 231 } 232 233 static int mei_txe_pci_resume(struct device *device) 234 { 235 struct pci_dev *pdev = to_pci_dev(device); 236 struct mei_device *dev; 237 int err; 238 239 dev = pci_get_drvdata(pdev); 240 if (!dev) 241 return -ENODEV; 242 243 pci_enable_msi(pdev); 244 245 mei_clear_interrupts(dev); 246 247 /* request and enable interrupt */ 248 if (pci_dev_msi_enabled(pdev)) 249 err = request_threaded_irq(pdev->irq, 250 NULL, 251 mei_txe_irq_thread_handler, 252 IRQF_ONESHOT, KBUILD_MODNAME, dev); 253 else 254 err = request_threaded_irq(pdev->irq, 255 mei_txe_irq_quick_handler, 256 mei_txe_irq_thread_handler, 257 IRQF_SHARED, KBUILD_MODNAME, dev); 258 if (err) { 259 dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n", 260 pdev->irq); 261 return err; 262 } 263 264 err = mei_restart(dev); 265 266 return err; 267 } 268 269 static SIMPLE_DEV_PM_OPS(mei_txe_pm_ops, 270 mei_txe_pci_suspend, 271 mei_txe_pci_resume); 272 273 #define MEI_TXE_PM_OPS (&mei_txe_pm_ops) 274 #else 275 #define MEI_TXE_PM_OPS NULL 276 #endif /* CONFIG_PM_SLEEP */ 277 /* 278 * PCI driver structure 279 */ 280 static struct pci_driver mei_txe_driver = { 281 .name = KBUILD_MODNAME, 282 .id_table = mei_txe_pci_tbl, 283 .probe = mei_txe_probe, 284 .remove = mei_txe_remove, 285 .shutdown = mei_txe_remove, 286 .driver.pm = MEI_TXE_PM_OPS, 287 }; 288 289 module_pci_driver(mei_txe_driver); 290 291 MODULE_AUTHOR("Intel Corporation"); 292 MODULE_DESCRIPTION("Intel(R) Trusted Execution Environment Interface"); 293 MODULE_LICENSE("GPL v2"); 294