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