1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2013-2017, Intel Corporation. All rights reserved.
4 * Intel Management Engine Interface (Intel MEI) Linux driver
7 #include <linux/module.h>
8 #include <linux/kernel.h>
9 #include <linux/device.h>
11 #include <linux/errno.h>
12 #include <linux/types.h>
13 #include <linux/pci.h>
14 #include <linux/init.h>
15 #include <linux/sched.h>
16 #include <linux/uuid.h>
17 #include <linux/jiffies.h>
18 #include <linux/interrupt.h>
19 #include <linux/workqueue.h>
20 #include <linux/pm_domain.h>
21 #include <linux/pm_runtime.h>
23 #include <linux/mei.h>
29 static const struct pci_device_id mei_txe_pci_tbl
[] = {
30 {PCI_VDEVICE(INTEL
, 0x0F18)}, /* Baytrail */
31 {PCI_VDEVICE(INTEL
, 0x2298)}, /* Cherrytrail */
35 MODULE_DEVICE_TABLE(pci
, mei_txe_pci_tbl
);
38 static inline void mei_txe_set_pm_domain(struct mei_device
*dev
);
39 static inline void mei_txe_unset_pm_domain(struct mei_device
*dev
);
41 static inline void mei_txe_set_pm_domain(struct mei_device
*dev
) {}
42 static inline void mei_txe_unset_pm_domain(struct mei_device
*dev
) {}
43 #endif /* CONFIG_PM */
46 * mei_txe_probe - Device Initialization Routine
48 * @pdev: PCI device structure
49 * @ent: entry in mei_txe_pci_tbl
51 * Return: 0 on success, <0 on failure.
53 static int mei_txe_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
55 struct mei_device
*dev
;
56 struct mei_txe_hw
*hw
;
57 const int mask
= BIT(SEC_BAR
) | BIT(BRIDGE_BAR
);
61 err
= pcim_enable_device(pdev
);
63 dev_err(&pdev
->dev
, "failed to enable pci device.\n");
66 /* set PCI host mastering */
68 /* pci request regions and mapping IO device memory for mei driver */
69 err
= pcim_iomap_regions(pdev
, mask
, KBUILD_MODNAME
);
71 dev_err(&pdev
->dev
, "failed to get pci regions.\n");
75 err
= pci_set_dma_mask(pdev
, DMA_BIT_MASK(36));
77 err
= pci_set_dma_mask(pdev
, DMA_BIT_MASK(32));
79 dev_err(&pdev
->dev
, "No suitable DMA available.\n");
84 /* allocates and initializes the mei dev structure */
85 dev
= mei_txe_dev_init(pdev
);
91 hw
->mem_addr
= pcim_iomap_table(pdev
);
95 /* clear spurious interrupts */
96 mei_clear_interrupts(dev
);
98 /* request and enable interrupt */
99 if (pci_dev_msi_enabled(pdev
))
100 err
= request_threaded_irq(pdev
->irq
,
102 mei_txe_irq_thread_handler
,
103 IRQF_ONESHOT
, KBUILD_MODNAME
, dev
);
105 err
= request_threaded_irq(pdev
->irq
,
106 mei_txe_irq_quick_handler
,
107 mei_txe_irq_thread_handler
,
108 IRQF_SHARED
, KBUILD_MODNAME
, dev
);
110 dev_err(&pdev
->dev
, "mei: request_threaded_irq failure. irq = %d\n",
115 if (mei_start(dev
)) {
116 dev_err(&pdev
->dev
, "init hw failure.\n");
121 pm_runtime_set_autosuspend_delay(&pdev
->dev
, MEI_TXI_RPM_TIMEOUT
);
122 pm_runtime_use_autosuspend(&pdev
->dev
);
124 err
= mei_register(dev
, &pdev
->dev
);
128 pci_set_drvdata(pdev
, dev
);
131 * MEI requires to resume from runtime suspend mode
132 * in order to perform link reset flow upon system suspend.
134 dev_pm_set_driver_flags(&pdev
->dev
, DPM_FLAG_NEVER_SKIP
);
137 * TXE maps runtime suspend/resume to own power gating states,
138 * hence we need to go around native PCI runtime service which
139 * eventually brings the device into D3cold/hot state.
140 * But the TXE device cannot wake up from D3 unlike from own
141 * power gating. To get around PCI device native runtime pm,
142 * TXE uses runtime pm domain handlers which take precedence.
144 mei_txe_set_pm_domain(dev
);
146 pm_runtime_put_noidle(&pdev
->dev
);
153 mei_cancel_work(dev
);
154 mei_disable_interrupts(dev
);
155 free_irq(pdev
->irq
, dev
);
157 dev_err(&pdev
->dev
, "initialization failed.\n");
162 * mei_txe_remove - Device Shutdown Routine
164 * @pdev: PCI device structure
166 * mei_txe_shutdown is called from the reboot notifier
167 * it's a simplified version of remove so we go down
170 static void mei_txe_shutdown(struct pci_dev
*pdev
)
172 struct mei_device
*dev
;
174 dev
= pci_get_drvdata(pdev
);
178 dev_dbg(&pdev
->dev
, "shutdown\n");
181 mei_txe_unset_pm_domain(dev
);
183 mei_disable_interrupts(dev
);
184 free_irq(pdev
->irq
, dev
);
188 * mei_txe_remove - Device Removal Routine
190 * @pdev: PCI device structure
192 * mei_remove is called by the PCI subsystem to alert the driver
193 * that it should release a PCI device.
195 static void mei_txe_remove(struct pci_dev
*pdev
)
197 struct mei_device
*dev
;
199 dev
= pci_get_drvdata(pdev
);
201 dev_err(&pdev
->dev
, "mei: dev == NULL\n");
205 pm_runtime_get_noresume(&pdev
->dev
);
209 mei_txe_unset_pm_domain(dev
);
211 mei_disable_interrupts(dev
);
212 free_irq(pdev
->irq
, dev
);
218 #ifdef CONFIG_PM_SLEEP
219 static int mei_txe_pci_suspend(struct device
*device
)
221 struct pci_dev
*pdev
= to_pci_dev(device
);
222 struct mei_device
*dev
= pci_get_drvdata(pdev
);
227 dev_dbg(&pdev
->dev
, "suspend\n");
231 mei_disable_interrupts(dev
);
233 free_irq(pdev
->irq
, dev
);
234 pci_disable_msi(pdev
);
239 static int mei_txe_pci_resume(struct device
*device
)
241 struct pci_dev
*pdev
= to_pci_dev(device
);
242 struct mei_device
*dev
;
245 dev
= pci_get_drvdata(pdev
);
249 pci_enable_msi(pdev
);
251 mei_clear_interrupts(dev
);
253 /* request and enable interrupt */
254 if (pci_dev_msi_enabled(pdev
))
255 err
= request_threaded_irq(pdev
->irq
,
257 mei_txe_irq_thread_handler
,
258 IRQF_ONESHOT
, KBUILD_MODNAME
, dev
);
260 err
= request_threaded_irq(pdev
->irq
,
261 mei_txe_irq_quick_handler
,
262 mei_txe_irq_thread_handler
,
263 IRQF_SHARED
, KBUILD_MODNAME
, dev
);
265 dev_err(&pdev
->dev
, "request_threaded_irq failed: irq = %d.\n",
270 err
= mei_restart(dev
);
274 #endif /* CONFIG_PM_SLEEP */
277 static int mei_txe_pm_runtime_idle(struct device
*device
)
279 struct mei_device
*dev
;
281 dev_dbg(device
, "rpm: txe: runtime_idle\n");
283 dev
= dev_get_drvdata(device
);
286 if (mei_write_is_idle(dev
))
287 pm_runtime_autosuspend(device
);
291 static int mei_txe_pm_runtime_suspend(struct device
*device
)
293 struct mei_device
*dev
;
296 dev_dbg(device
, "rpm: txe: runtime suspend\n");
298 dev
= dev_get_drvdata(device
);
302 mutex_lock(&dev
->device_lock
);
304 if (mei_write_is_idle(dev
))
305 ret
= mei_txe_aliveness_set_sync(dev
, 0);
309 /* keep irq on we are staying in D0 */
311 dev_dbg(device
, "rpm: txe: runtime suspend ret=%d\n", ret
);
313 mutex_unlock(&dev
->device_lock
);
315 if (ret
&& ret
!= -EAGAIN
)
316 schedule_work(&dev
->reset_work
);
321 static int mei_txe_pm_runtime_resume(struct device
*device
)
323 struct mei_device
*dev
;
326 dev_dbg(device
, "rpm: txe: runtime resume\n");
328 dev
= dev_get_drvdata(device
);
332 mutex_lock(&dev
->device_lock
);
334 mei_enable_interrupts(dev
);
336 ret
= mei_txe_aliveness_set_sync(dev
, 1);
338 mutex_unlock(&dev
->device_lock
);
340 dev_dbg(device
, "rpm: txe: runtime resume ret = %d\n", ret
);
343 schedule_work(&dev
->reset_work
);
349 * mei_txe_set_pm_domain - fill and set pm domain structure for device
353 static inline void mei_txe_set_pm_domain(struct mei_device
*dev
)
355 struct pci_dev
*pdev
= to_pci_dev(dev
->dev
);
357 if (pdev
->dev
.bus
&& pdev
->dev
.bus
->pm
) {
358 dev
->pg_domain
.ops
= *pdev
->dev
.bus
->pm
;
360 dev
->pg_domain
.ops
.runtime_suspend
= mei_txe_pm_runtime_suspend
;
361 dev
->pg_domain
.ops
.runtime_resume
= mei_txe_pm_runtime_resume
;
362 dev
->pg_domain
.ops
.runtime_idle
= mei_txe_pm_runtime_idle
;
364 dev_pm_domain_set(&pdev
->dev
, &dev
->pg_domain
);
369 * mei_txe_unset_pm_domain - clean pm domain structure for device
373 static inline void mei_txe_unset_pm_domain(struct mei_device
*dev
)
375 /* stop using pm callbacks if any */
376 dev_pm_domain_set(dev
->dev
, NULL
);
379 static const struct dev_pm_ops mei_txe_pm_ops
= {
380 SET_SYSTEM_SLEEP_PM_OPS(mei_txe_pci_suspend
,
383 mei_txe_pm_runtime_suspend
,
384 mei_txe_pm_runtime_resume
,
385 mei_txe_pm_runtime_idle
)
388 #define MEI_TXE_PM_OPS (&mei_txe_pm_ops)
390 #define MEI_TXE_PM_OPS NULL
391 #endif /* CONFIG_PM */
394 * PCI driver structure
396 static struct pci_driver mei_txe_driver
= {
397 .name
= KBUILD_MODNAME
,
398 .id_table
= mei_txe_pci_tbl
,
399 .probe
= mei_txe_probe
,
400 .remove
= mei_txe_remove
,
401 .shutdown
= mei_txe_shutdown
,
402 .driver
.pm
= MEI_TXE_PM_OPS
,
405 module_pci_driver(mei_txe_driver
);
407 MODULE_AUTHOR("Intel Corporation");
408 MODULE_DESCRIPTION("Intel(R) Trusted Execution Environment Interface");
409 MODULE_LICENSE("GPL v2");