xref: /linux/drivers/misc/mei/pci-txe.c (revision 4ad96db6ccdd8b777cff5fd4aa74ec1e86f1afce)
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[] = {
39*4ad96db6STomas Winkler 	{PCI_VDEVICE(INTEL, 0x0F18)}, /* Baytrail */
40*4ad96db6STomas Winkler 
41795536acSTomas Winkler 	{0, }
42795536acSTomas Winkler };
43795536acSTomas Winkler MODULE_DEVICE_TABLE(pci, mei_txe_pci_tbl);
44795536acSTomas Winkler 
45d2d56faeSAlexander Usyskin #ifdef CONFIG_PM_RUNTIME
46d2d56faeSAlexander Usyskin static inline void mei_txe_set_pm_domain(struct mei_device *dev);
47d2d56faeSAlexander Usyskin static inline void mei_txe_unset_pm_domain(struct mei_device *dev);
48d2d56faeSAlexander Usyskin #else
49d2d56faeSAlexander Usyskin static inline void mei_txe_set_pm_domain(struct mei_device *dev) {}
50d2d56faeSAlexander Usyskin static inline void mei_txe_unset_pm_domain(struct mei_device *dev) {}
51d2d56faeSAlexander Usyskin #endif /* CONFIG_PM_RUNTIME */
52795536acSTomas Winkler 
53795536acSTomas Winkler static void mei_txe_pci_iounmap(struct pci_dev *pdev, struct mei_txe_hw *hw)
54795536acSTomas Winkler {
55795536acSTomas Winkler 	int i;
5692db1555STomas Winkler 
57795536acSTomas Winkler 	for (i = SEC_BAR; i < NUM_OF_MEM_BARS; i++) {
58795536acSTomas Winkler 		if (hw->mem_addr[i]) {
59795536acSTomas Winkler 			pci_iounmap(pdev, hw->mem_addr[i]);
60795536acSTomas Winkler 			hw->mem_addr[i] = NULL;
61795536acSTomas Winkler 		}
62795536acSTomas Winkler 	}
63795536acSTomas Winkler }
64795536acSTomas Winkler /**
65795536acSTomas Winkler  * mei_probe - Device Initialization Routine
66795536acSTomas Winkler  *
67795536acSTomas Winkler  * @pdev: PCI device structure
68795536acSTomas Winkler  * @ent: entry in mei_txe_pci_tbl
69795536acSTomas Winkler  *
70795536acSTomas Winkler  * returns 0 on success, <0 on failure.
71795536acSTomas Winkler  */
72795536acSTomas Winkler static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
73795536acSTomas Winkler {
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 */
104*4ad96db6STomas Winkler 	dev = mei_txe_dev_init(pdev);
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 {
381d08b8fc0STomas 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