xref: /linux/drivers/misc/mei/pci-txe.c (revision f3d8e8788b4efbd13b6e888e85af51385d87d306)
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;
55795536acSTomas Winkler 	for (i = SEC_BAR; i < NUM_OF_MEM_BARS; i++) {
56795536acSTomas Winkler 		if (hw->mem_addr[i]) {
57795536acSTomas Winkler 			pci_iounmap(pdev, hw->mem_addr[i]);
58795536acSTomas Winkler 			hw->mem_addr[i] = NULL;
59795536acSTomas Winkler 		}
60795536acSTomas Winkler 	}
61795536acSTomas Winkler }
62795536acSTomas Winkler /**
63795536acSTomas Winkler  * mei_probe - Device Initialization Routine
64795536acSTomas Winkler  *
65795536acSTomas Winkler  * @pdev: PCI device structure
66795536acSTomas Winkler  * @ent: entry in mei_txe_pci_tbl
67795536acSTomas Winkler  *
68795536acSTomas Winkler  * returns 0 on success, <0 on failure.
69795536acSTomas Winkler  */
70795536acSTomas Winkler static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
71795536acSTomas Winkler {
728d929d48SAlexander Usyskin 	const struct mei_cfg *cfg = (struct mei_cfg *)(ent->driver_data);
73795536acSTomas Winkler 	struct mei_device *dev;
74795536acSTomas Winkler 	struct mei_txe_hw *hw;
75795536acSTomas Winkler 	int err;
76795536acSTomas Winkler 	int i;
77795536acSTomas Winkler 
78795536acSTomas Winkler 	/* enable pci dev */
79795536acSTomas Winkler 	err = pci_enable_device(pdev);
80795536acSTomas Winkler 	if (err) {
81795536acSTomas Winkler 		dev_err(&pdev->dev, "failed to enable pci device.\n");
82795536acSTomas Winkler 		goto end;
83795536acSTomas Winkler 	}
84795536acSTomas Winkler 	/* set PCI host mastering  */
85795536acSTomas Winkler 	pci_set_master(pdev);
86795536acSTomas Winkler 	/* pci request regions for mei driver */
87795536acSTomas Winkler 	err = pci_request_regions(pdev, KBUILD_MODNAME);
88795536acSTomas Winkler 	if (err) {
89795536acSTomas Winkler 		dev_err(&pdev->dev, "failed to get pci regions.\n");
90795536acSTomas Winkler 		goto disable_device;
91795536acSTomas Winkler 	}
92795536acSTomas Winkler 
93795536acSTomas Winkler 	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
94795536acSTomas Winkler 	if (err) {
95795536acSTomas Winkler 		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
96795536acSTomas Winkler 		if (err) {
97795536acSTomas Winkler 			dev_err(&pdev->dev, "No suitable DMA available.\n");
98795536acSTomas Winkler 			goto release_regions;
99795536acSTomas Winkler 		}
100795536acSTomas Winkler 	}
101795536acSTomas Winkler 
102795536acSTomas Winkler 	/* allocates and initializes the mei dev structure */
1038d929d48SAlexander Usyskin 	dev = mei_txe_dev_init(pdev, cfg);
104795536acSTomas Winkler 	if (!dev) {
105795536acSTomas Winkler 		err = -ENOMEM;
106795536acSTomas Winkler 		goto release_regions;
107795536acSTomas Winkler 	}
108795536acSTomas Winkler 	hw = to_txe_hw(dev);
109795536acSTomas Winkler 
110795536acSTomas Winkler 	/* mapping  IO device memory */
111795536acSTomas Winkler 	for (i = SEC_BAR; i < NUM_OF_MEM_BARS; i++) {
112795536acSTomas Winkler 		hw->mem_addr[i] = pci_iomap(pdev, i, 0);
113795536acSTomas Winkler 		if (!hw->mem_addr[i]) {
114795536acSTomas Winkler 			dev_err(&pdev->dev, "mapping I/O device memory failure.\n");
115795536acSTomas Winkler 			err = -ENOMEM;
116795536acSTomas Winkler 			goto free_device;
117795536acSTomas Winkler 		}
118795536acSTomas Winkler 	}
119795536acSTomas Winkler 
120795536acSTomas Winkler 
121795536acSTomas Winkler 	pci_enable_msi(pdev);
122795536acSTomas Winkler 
123795536acSTomas Winkler 	/* clear spurious interrupts */
124795536acSTomas Winkler 	mei_clear_interrupts(dev);
125795536acSTomas Winkler 
126795536acSTomas Winkler 	/* request and enable interrupt  */
127795536acSTomas Winkler 	if (pci_dev_msi_enabled(pdev))
128795536acSTomas Winkler 		err = request_threaded_irq(pdev->irq,
129795536acSTomas Winkler 			NULL,
130795536acSTomas Winkler 			mei_txe_irq_thread_handler,
131795536acSTomas Winkler 			IRQF_ONESHOT, KBUILD_MODNAME, dev);
132795536acSTomas Winkler 	else
133795536acSTomas Winkler 		err = request_threaded_irq(pdev->irq,
134795536acSTomas Winkler 			mei_txe_irq_quick_handler,
135795536acSTomas Winkler 			mei_txe_irq_thread_handler,
136795536acSTomas Winkler 			IRQF_SHARED, KBUILD_MODNAME, dev);
137795536acSTomas Winkler 	if (err) {
138795536acSTomas Winkler 		dev_err(&pdev->dev, "mei: request_threaded_irq failure. irq = %d\n",
139795536acSTomas Winkler 			pdev->irq);
140795536acSTomas Winkler 		goto free_device;
141795536acSTomas Winkler 	}
142795536acSTomas Winkler 
143795536acSTomas Winkler 	if (mei_start(dev)) {
144795536acSTomas Winkler 		dev_err(&pdev->dev, "init hw failure.\n");
145795536acSTomas Winkler 		err = -ENODEV;
146795536acSTomas Winkler 		goto release_irq;
147795536acSTomas Winkler 	}
148795536acSTomas Winkler 
149cfe5ab85SAlexander Usyskin 	pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_TXI_RPM_TIMEOUT);
150cfe5ab85SAlexander Usyskin 	pm_runtime_use_autosuspend(&pdev->dev);
151cfe5ab85SAlexander Usyskin 
152*f3d8e878SAlexander Usyskin 	err = mei_register(dev, &pdev->dev);
153795536acSTomas Winkler 	if (err)
154795536acSTomas Winkler 		goto release_irq;
155795536acSTomas Winkler 
156795536acSTomas Winkler 	pci_set_drvdata(pdev, dev);
157795536acSTomas Winkler 
158d2d56faeSAlexander Usyskin 	/*
159d2d56faeSAlexander Usyskin 	* For not wake-able HW runtime pm framework
160d2d56faeSAlexander Usyskin 	* can't be used on pci device level.
161d2d56faeSAlexander Usyskin 	* Use domain runtime pm callbacks instead.
162d2d56faeSAlexander Usyskin 	*/
163d2d56faeSAlexander Usyskin 	if (!pci_dev_run_wake(pdev))
164d2d56faeSAlexander Usyskin 		mei_txe_set_pm_domain(dev);
165d2d56faeSAlexander Usyskin 
166cfe5ab85SAlexander Usyskin 	pm_runtime_put_noidle(&pdev->dev);
167cfe5ab85SAlexander Usyskin 
168795536acSTomas Winkler 	return 0;
169795536acSTomas Winkler 
170795536acSTomas Winkler release_irq:
171795536acSTomas Winkler 
172795536acSTomas Winkler 	mei_cancel_work(dev);
173795536acSTomas Winkler 
174795536acSTomas Winkler 	/* disable interrupts */
175795536acSTomas Winkler 	mei_disable_interrupts(dev);
176795536acSTomas Winkler 
177795536acSTomas Winkler 	free_irq(pdev->irq, dev);
178795536acSTomas Winkler 	pci_disable_msi(pdev);
179795536acSTomas Winkler 
180795536acSTomas Winkler free_device:
181795536acSTomas Winkler 	mei_txe_pci_iounmap(pdev, hw);
182795536acSTomas Winkler 
183795536acSTomas Winkler 	kfree(dev);
184795536acSTomas Winkler release_regions:
185795536acSTomas Winkler 	pci_release_regions(pdev);
186795536acSTomas Winkler disable_device:
187795536acSTomas Winkler 	pci_disable_device(pdev);
188795536acSTomas Winkler end:
189795536acSTomas Winkler 	dev_err(&pdev->dev, "initialization failed.\n");
190795536acSTomas Winkler 	return err;
191795536acSTomas Winkler }
192795536acSTomas Winkler 
193795536acSTomas Winkler /**
194795536acSTomas Winkler  * mei_remove - Device Removal Routine
195795536acSTomas Winkler  *
196795536acSTomas Winkler  * @pdev: PCI device structure
197795536acSTomas Winkler  *
198795536acSTomas Winkler  * mei_remove is called by the PCI subsystem to alert the driver
199795536acSTomas Winkler  * that it should release a PCI device.
200795536acSTomas Winkler  */
201795536acSTomas Winkler static void mei_txe_remove(struct pci_dev *pdev)
202795536acSTomas Winkler {
203795536acSTomas Winkler 	struct mei_device *dev;
204795536acSTomas Winkler 	struct mei_txe_hw *hw;
205795536acSTomas Winkler 
206795536acSTomas Winkler 	dev = pci_get_drvdata(pdev);
207795536acSTomas Winkler 	if (!dev) {
208795536acSTomas Winkler 		dev_err(&pdev->dev, "mei: dev =NULL\n");
209795536acSTomas Winkler 		return;
210795536acSTomas Winkler 	}
211795536acSTomas Winkler 
212cfe5ab85SAlexander Usyskin 	pm_runtime_get_noresume(&pdev->dev);
213cfe5ab85SAlexander Usyskin 
214795536acSTomas Winkler 	hw = to_txe_hw(dev);
215795536acSTomas Winkler 
216795536acSTomas Winkler 	mei_stop(dev);
217795536acSTomas Winkler 
218d2d56faeSAlexander Usyskin 	if (!pci_dev_run_wake(pdev))
219d2d56faeSAlexander Usyskin 		mei_txe_unset_pm_domain(dev);
220d2d56faeSAlexander Usyskin 
221795536acSTomas Winkler 	/* disable interrupts */
222795536acSTomas Winkler 	mei_disable_interrupts(dev);
223795536acSTomas Winkler 	free_irq(pdev->irq, dev);
224795536acSTomas Winkler 	pci_disable_msi(pdev);
225795536acSTomas Winkler 
226795536acSTomas Winkler 	pci_set_drvdata(pdev, NULL);
227795536acSTomas Winkler 
228795536acSTomas Winkler 	mei_txe_pci_iounmap(pdev, hw);
229795536acSTomas Winkler 
230795536acSTomas Winkler 	mei_deregister(dev);
231795536acSTomas Winkler 
232795536acSTomas Winkler 	kfree(dev);
233795536acSTomas Winkler 
234795536acSTomas Winkler 	pci_release_regions(pdev);
235795536acSTomas Winkler 	pci_disable_device(pdev);
236795536acSTomas Winkler }
237795536acSTomas Winkler 
238795536acSTomas Winkler 
239e0270addSTomas Winkler #ifdef CONFIG_PM_SLEEP
240795536acSTomas Winkler static int mei_txe_pci_suspend(struct device *device)
241795536acSTomas Winkler {
242795536acSTomas Winkler 	struct pci_dev *pdev = to_pci_dev(device);
243795536acSTomas Winkler 	struct mei_device *dev = pci_get_drvdata(pdev);
244795536acSTomas Winkler 
245795536acSTomas Winkler 	if (!dev)
246795536acSTomas Winkler 		return -ENODEV;
247795536acSTomas Winkler 
248795536acSTomas Winkler 	dev_dbg(&pdev->dev, "suspend\n");
249795536acSTomas Winkler 
250795536acSTomas Winkler 	mei_stop(dev);
251795536acSTomas Winkler 
252795536acSTomas Winkler 	mei_disable_interrupts(dev);
253795536acSTomas Winkler 
254795536acSTomas Winkler 	free_irq(pdev->irq, dev);
255795536acSTomas Winkler 	pci_disable_msi(pdev);
256795536acSTomas Winkler 
257795536acSTomas Winkler 	return 0;
258795536acSTomas Winkler }
259795536acSTomas Winkler 
260795536acSTomas Winkler static int mei_txe_pci_resume(struct device *device)
261795536acSTomas Winkler {
262795536acSTomas Winkler 	struct pci_dev *pdev = to_pci_dev(device);
263795536acSTomas Winkler 	struct mei_device *dev;
264795536acSTomas Winkler 	int err;
265795536acSTomas Winkler 
266795536acSTomas Winkler 	dev = pci_get_drvdata(pdev);
267795536acSTomas Winkler 	if (!dev)
268795536acSTomas Winkler 		return -ENODEV;
269795536acSTomas Winkler 
270795536acSTomas Winkler 	pci_enable_msi(pdev);
271795536acSTomas Winkler 
272795536acSTomas Winkler 	mei_clear_interrupts(dev);
273795536acSTomas Winkler 
274795536acSTomas Winkler 	/* request and enable interrupt */
275795536acSTomas Winkler 	if (pci_dev_msi_enabled(pdev))
276795536acSTomas Winkler 		err = request_threaded_irq(pdev->irq,
277795536acSTomas Winkler 			NULL,
278795536acSTomas Winkler 			mei_txe_irq_thread_handler,
279795536acSTomas Winkler 			IRQF_ONESHOT, KBUILD_MODNAME, dev);
280795536acSTomas Winkler 	else
281795536acSTomas Winkler 		err = request_threaded_irq(pdev->irq,
282795536acSTomas Winkler 			mei_txe_irq_quick_handler,
283795536acSTomas Winkler 			mei_txe_irq_thread_handler,
284795536acSTomas Winkler 			IRQF_SHARED, KBUILD_MODNAME, dev);
285795536acSTomas Winkler 	if (err) {
286795536acSTomas Winkler 		dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n",
287795536acSTomas Winkler 				pdev->irq);
288795536acSTomas Winkler 		return err;
289795536acSTomas Winkler 	}
290795536acSTomas Winkler 
291795536acSTomas Winkler 	err = mei_restart(dev);
292795536acSTomas Winkler 
293795536acSTomas Winkler 	return err;
294795536acSTomas Winkler }
295cfe5ab85SAlexander Usyskin #endif /* CONFIG_PM_SLEEP */
296795536acSTomas Winkler 
297cfe5ab85SAlexander Usyskin #ifdef CONFIG_PM_RUNTIME
298cfe5ab85SAlexander Usyskin static int mei_txe_pm_runtime_idle(struct device *device)
299cfe5ab85SAlexander Usyskin {
300cfe5ab85SAlexander Usyskin 	struct pci_dev *pdev = to_pci_dev(device);
301cfe5ab85SAlexander Usyskin 	struct mei_device *dev;
302cfe5ab85SAlexander Usyskin 
303cfe5ab85SAlexander Usyskin 	dev_dbg(&pdev->dev, "rpm: txe: runtime_idle\n");
304cfe5ab85SAlexander Usyskin 
305cfe5ab85SAlexander Usyskin 	dev = pci_get_drvdata(pdev);
306cfe5ab85SAlexander Usyskin 	if (!dev)
307cfe5ab85SAlexander Usyskin 		return -ENODEV;
308cfe5ab85SAlexander Usyskin 	if (mei_write_is_idle(dev))
309cfe5ab85SAlexander Usyskin 		pm_schedule_suspend(device, MEI_TXI_RPM_TIMEOUT * 2);
310cfe5ab85SAlexander Usyskin 
311cfe5ab85SAlexander Usyskin 	return -EBUSY;
312cfe5ab85SAlexander Usyskin }
313cfe5ab85SAlexander Usyskin static int mei_txe_pm_runtime_suspend(struct device *device)
314cfe5ab85SAlexander Usyskin {
315cfe5ab85SAlexander Usyskin 	struct pci_dev *pdev = to_pci_dev(device);
316cfe5ab85SAlexander Usyskin 	struct mei_device *dev;
317cfe5ab85SAlexander Usyskin 	int ret;
318cfe5ab85SAlexander Usyskin 
319cfe5ab85SAlexander Usyskin 	dev_dbg(&pdev->dev, "rpm: txe: runtime suspend\n");
320cfe5ab85SAlexander Usyskin 
321cfe5ab85SAlexander Usyskin 	dev = pci_get_drvdata(pdev);
322cfe5ab85SAlexander Usyskin 	if (!dev)
323cfe5ab85SAlexander Usyskin 		return -ENODEV;
324cfe5ab85SAlexander Usyskin 
325cfe5ab85SAlexander Usyskin 	mutex_lock(&dev->device_lock);
326cfe5ab85SAlexander Usyskin 
327cfe5ab85SAlexander Usyskin 	if (mei_write_is_idle(dev))
328cfe5ab85SAlexander Usyskin 		ret = mei_txe_aliveness_set_sync(dev, 0);
329cfe5ab85SAlexander Usyskin 	else
330cfe5ab85SAlexander Usyskin 		ret = -EAGAIN;
331cfe5ab85SAlexander Usyskin 
332cfe5ab85SAlexander Usyskin 	/*
333cfe5ab85SAlexander Usyskin 	 * If everything is okay we're about to enter PCI low
334cfe5ab85SAlexander Usyskin 	 * power state (D3) therefor we need to disable the
335cfe5ab85SAlexander Usyskin 	 * interrupts towards host.
336cfe5ab85SAlexander Usyskin 	 * However if device is not wakeable we do not enter
337cfe5ab85SAlexander Usyskin 	 * D-low state and we need to keep the interrupt kicking
338cfe5ab85SAlexander Usyskin 	 */
339cfe5ab85SAlexander Usyskin 	 if (!ret && pci_dev_run_wake(pdev))
340cfe5ab85SAlexander Usyskin 		mei_disable_interrupts(dev);
341cfe5ab85SAlexander Usyskin 
342cfe5ab85SAlexander Usyskin 	dev_dbg(&pdev->dev, "rpm: txe: runtime suspend ret=%d\n", ret);
343cfe5ab85SAlexander Usyskin 
344cfe5ab85SAlexander Usyskin 	mutex_unlock(&dev->device_lock);
345cfe5ab85SAlexander Usyskin 	return ret;
346cfe5ab85SAlexander Usyskin }
347cfe5ab85SAlexander Usyskin 
348cfe5ab85SAlexander Usyskin static int mei_txe_pm_runtime_resume(struct device *device)
349cfe5ab85SAlexander Usyskin {
350cfe5ab85SAlexander Usyskin 	struct pci_dev *pdev = to_pci_dev(device);
351cfe5ab85SAlexander Usyskin 	struct mei_device *dev;
352cfe5ab85SAlexander Usyskin 	int ret;
353cfe5ab85SAlexander Usyskin 
354cfe5ab85SAlexander Usyskin 	dev_dbg(&pdev->dev, "rpm: txe: runtime resume\n");
355cfe5ab85SAlexander Usyskin 
356cfe5ab85SAlexander Usyskin 	dev = pci_get_drvdata(pdev);
357cfe5ab85SAlexander Usyskin 	if (!dev)
358cfe5ab85SAlexander Usyskin 		return -ENODEV;
359cfe5ab85SAlexander Usyskin 
360cfe5ab85SAlexander Usyskin 	mutex_lock(&dev->device_lock);
361cfe5ab85SAlexander Usyskin 
362cfe5ab85SAlexander Usyskin 	mei_enable_interrupts(dev);
363cfe5ab85SAlexander Usyskin 
364cfe5ab85SAlexander Usyskin 	ret = mei_txe_aliveness_set_sync(dev, 1);
365cfe5ab85SAlexander Usyskin 
366cfe5ab85SAlexander Usyskin 	mutex_unlock(&dev->device_lock);
367cfe5ab85SAlexander Usyskin 
368cfe5ab85SAlexander Usyskin 	dev_dbg(&pdev->dev, "rpm: txe: runtime resume ret = %d\n", ret);
369cfe5ab85SAlexander Usyskin 
370cfe5ab85SAlexander Usyskin 	return ret;
371cfe5ab85SAlexander Usyskin }
372d2d56faeSAlexander Usyskin 
373d2d56faeSAlexander Usyskin /**
374d2d56faeSAlexander Usyskin  * mei_txe_set_pm_domain - fill and set pm domian stucture for device
375d2d56faeSAlexander Usyskin  *
376d2d56faeSAlexander Usyskin  * @dev: mei_device
377d2d56faeSAlexander Usyskin  */
378d2d56faeSAlexander Usyskin static inline void mei_txe_set_pm_domain(struct mei_device *dev)
379d2d56faeSAlexander Usyskin {
380d2d56faeSAlexander Usyskin 	struct pci_dev *pdev  = dev->pdev;
381d2d56faeSAlexander Usyskin 
382d2d56faeSAlexander Usyskin 	if (pdev->dev.bus && pdev->dev.bus->pm) {
383d2d56faeSAlexander Usyskin 		dev->pg_domain.ops = *pdev->dev.bus->pm;
384d2d56faeSAlexander Usyskin 
385d2d56faeSAlexander Usyskin 		dev->pg_domain.ops.runtime_suspend = mei_txe_pm_runtime_suspend;
386d2d56faeSAlexander Usyskin 		dev->pg_domain.ops.runtime_resume = mei_txe_pm_runtime_resume;
387d2d56faeSAlexander Usyskin 		dev->pg_domain.ops.runtime_idle = mei_txe_pm_runtime_idle;
388d2d56faeSAlexander Usyskin 
389d2d56faeSAlexander Usyskin 		pdev->dev.pm_domain = &dev->pg_domain;
390d2d56faeSAlexander Usyskin 	}
391d2d56faeSAlexander Usyskin }
392d2d56faeSAlexander Usyskin 
393d2d56faeSAlexander Usyskin /**
394d2d56faeSAlexander Usyskin  * mei_txe_unset_pm_domain - clean pm domian stucture for device
395d2d56faeSAlexander Usyskin  *
396d2d56faeSAlexander Usyskin  * @dev: mei_device
397d2d56faeSAlexander Usyskin  */
398d2d56faeSAlexander Usyskin static inline void mei_txe_unset_pm_domain(struct mei_device *dev)
399d2d56faeSAlexander Usyskin {
400d2d56faeSAlexander Usyskin 	/* stop using pm callbacks if any */
401d2d56faeSAlexander Usyskin 	dev->pdev->dev.pm_domain = NULL;
402d2d56faeSAlexander Usyskin }
403cfe5ab85SAlexander Usyskin #endif /* CONFIG_PM_RUNTIME */
404cfe5ab85SAlexander Usyskin 
405cfe5ab85SAlexander Usyskin #ifdef CONFIG_PM
406cfe5ab85SAlexander Usyskin static const struct dev_pm_ops mei_txe_pm_ops = {
407cfe5ab85SAlexander Usyskin 	SET_SYSTEM_SLEEP_PM_OPS(mei_txe_pci_suspend,
408cfe5ab85SAlexander Usyskin 				mei_txe_pci_resume)
409cfe5ab85SAlexander Usyskin 	SET_RUNTIME_PM_OPS(
410cfe5ab85SAlexander Usyskin 		mei_txe_pm_runtime_suspend,
411cfe5ab85SAlexander Usyskin 		mei_txe_pm_runtime_resume,
412cfe5ab85SAlexander Usyskin 		mei_txe_pm_runtime_idle)
413cfe5ab85SAlexander Usyskin };
414795536acSTomas Winkler 
415795536acSTomas Winkler #define MEI_TXE_PM_OPS	(&mei_txe_pm_ops)
416795536acSTomas Winkler #else
417795536acSTomas Winkler #define MEI_TXE_PM_OPS	NULL
418cfe5ab85SAlexander Usyskin #endif /* CONFIG_PM */
419cfe5ab85SAlexander Usyskin 
420795536acSTomas Winkler /*
421795536acSTomas Winkler  *  PCI driver structure
422795536acSTomas Winkler  */
423795536acSTomas Winkler static struct pci_driver mei_txe_driver = {
424795536acSTomas Winkler 	.name = KBUILD_MODNAME,
425795536acSTomas Winkler 	.id_table = mei_txe_pci_tbl,
426795536acSTomas Winkler 	.probe = mei_txe_probe,
427795536acSTomas Winkler 	.remove = mei_txe_remove,
428795536acSTomas Winkler 	.shutdown = mei_txe_remove,
429795536acSTomas Winkler 	.driver.pm = MEI_TXE_PM_OPS,
430795536acSTomas Winkler };
431795536acSTomas Winkler 
432795536acSTomas Winkler module_pci_driver(mei_txe_driver);
433795536acSTomas Winkler 
434795536acSTomas Winkler MODULE_AUTHOR("Intel Corporation");
435795536acSTomas Winkler MODULE_DESCRIPTION("Intel(R) Trusted Execution Environment Interface");
436795536acSTomas Winkler MODULE_LICENSE("GPL v2");
437