]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/i2c/busses/i2c-amd-pci-mp2.c
x86/speculation/mds: Add mitigation control for MDS
[mirror_ubuntu-bionic-kernel.git] / drivers / i2c / busses / i2c-amd-pci-mp2.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * This file is provided under a dual BSD/GPLv2 license. When using or
4 * redistributing this file, you may do so under either license.
5 *
6 * GPL LICENSE SUMMARY
7 *
8 * Copyright (C) 2018 Advanced Micro Devices, Inc. All Rights Reserved.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * BSD LICENSE
15 *
16 * Copyright (C) 2018 Advanced Micro Devices, Inc. All Rights Reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 *
22 * * Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * * Redistributions in binary form must reproduce the above copy
25 * notice, this list of conditions and the following disclaimer in
26 * the documentation and/or other materials provided with the
27 * distribution.
28 * * Neither the name of AMD Corporation nor the names of its
29 * contributors may be used to endorse or promote products derived
30 * from this software without specific prior written permission.
31 *
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
39 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
40 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
41 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
42 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 *
44 * AMD PCIe MP2 Communication Driver
45 * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
46 */
47
48 #include <linux/debugfs.h>
49 #include <linux/interrupt.h>
50 #include <linux/module.h>
51 #include <linux/pci.h>
52 #include <linux/slab.h>
53
54 #include "i2c-amd-pci-mp2.h"
55
56 #define DRIVER_NAME "pcie_mp2_amd"
57 #define DRIVER_DESC "AMD(R) PCI-E MP2 Communication Driver"
58 #define DRIVER_VER "1.0"
59
60 MODULE_DESCRIPTION(DRIVER_DESC);
61 MODULE_VERSION(DRIVER_VER);
62 MODULE_LICENSE("Dual BSD/GPL");
63 MODULE_AUTHOR("Shyam Sundar S K <Shyam-sundar.S-k@amd.com>");
64
65 static const struct file_operations amd_mp2_debugfs_info;
66 static struct dentry *debugfs_dir;
67
68 int amd_mp2_connect(struct pci_dev *dev,
69 struct i2c_connect_config connect_cfg)
70 {
71 struct amd_mp2_dev *privdata = pci_get_drvdata(dev);
72 union i2c_cmd_base i2c_cmd_base;
73 unsigned long flags;
74
75 raw_spin_lock_irqsave(&privdata->lock, flags);
76 dev_dbg(ndev_dev(privdata), "%s addr: %x id: %d\n", __func__,
77 connect_cfg.dev_addr, connect_cfg.bus_id);
78
79 i2c_cmd_base.ul = 0;
80 i2c_cmd_base.s.i2c_cmd = i2c_enable;
81 i2c_cmd_base.s.bus_id = connect_cfg.bus_id;
82 i2c_cmd_base.s.i2c_speed = connect_cfg.i2c_speed;
83
84 if (i2c_cmd_base.s.bus_id == i2c_bus_1) {
85 writel(i2c_cmd_base.ul, privdata->mmio + AMD_C2P_MSG1);
86 } else if (i2c_cmd_base.s.bus_id == i2c_bus_0) {
87 writel(i2c_cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
88 } else {
89 dev_err(ndev_dev(privdata), "%s Invalid bus id\n", __func__);
90 return -EINVAL;
91 }
92 raw_spin_unlock_irqrestore(&privdata->lock, flags);
93 return 0;
94 }
95 EXPORT_SYMBOL_GPL(amd_mp2_connect);
96
97 int amd_mp2_read(struct pci_dev *dev, struct i2c_read_config read_cfg)
98 {
99 struct amd_mp2_dev *privdata = pci_get_drvdata(dev);
100 union i2c_cmd_base i2c_cmd_base;
101
102 dev_dbg(ndev_dev(privdata), "%s addr: %x id: %d\n", __func__,
103 read_cfg.dev_addr, read_cfg.bus_id);
104
105 privdata->requested = true;
106 i2c_cmd_base.ul = 0;
107 i2c_cmd_base.s.i2c_cmd = i2c_read;
108 i2c_cmd_base.s.dev_addr = read_cfg.dev_addr;
109 i2c_cmd_base.s.length = read_cfg.length;
110 i2c_cmd_base.s.bus_id = read_cfg.bus_id;
111
112 if (read_cfg.length <= 32) {
113 i2c_cmd_base.s.mem_type = use_c2pmsg;
114 privdata->eventval.buf = (u32 *)read_cfg.buf;
115 dev_dbg(ndev_dev(privdata), "%s buf: %llx\n", __func__,
116 (u64)privdata->eventval.buf);
117 } else {
118 i2c_cmd_base.s.mem_type = use_dram;
119 privdata->read_cfg.phy_addr = read_cfg.phy_addr;
120 privdata->read_cfg.buf = read_cfg.buf;
121 write64((u64)privdata->read_cfg.phy_addr,
122 privdata->mmio + AMD_C2P_MSG2);
123 }
124
125 switch (read_cfg.i2c_speed) {
126 case 0:
127 i2c_cmd_base.s.i2c_speed = speed100k;
128 break;
129 case 1:
130 i2c_cmd_base.s.i2c_speed = speed400k;
131 break;
132 case 2:
133 i2c_cmd_base.s.i2c_speed = speed1000k;
134 break;
135 case 3:
136 i2c_cmd_base.s.i2c_speed = speed1400k;
137 break;
138 case 4:
139 i2c_cmd_base.s.i2c_speed = speed3400k;
140 break;
141 default:
142 dev_err(ndev_dev(privdata), "Invalid ConnectionSpeed\n");
143 }
144
145 if (i2c_cmd_base.s.bus_id == i2c_bus_1) {
146 writel(i2c_cmd_base.ul, privdata->mmio + AMD_C2P_MSG1);
147 } else if (i2c_cmd_base.s.bus_id == i2c_bus_0) {
148 writel(i2c_cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
149 } else {
150 dev_err(ndev_dev(privdata), "%s Invalid bus id\n", __func__);
151 return -EINVAL;
152 }
153
154 return 0;
155 }
156 EXPORT_SYMBOL_GPL(amd_mp2_read);
157
158 int amd_mp2_write(struct pci_dev *dev, struct i2c_write_config write_cfg)
159 {
160 struct amd_mp2_dev *privdata = pci_get_drvdata(dev);
161 union i2c_cmd_base i2c_cmd_base;
162 int i;
163 int buf_len;
164
165 privdata->requested = true;
166 dev_dbg(ndev_dev(privdata), "%s addr: %x id: %d\n", __func__,
167 write_cfg.dev_addr, write_cfg.bus_id);
168
169 i2c_cmd_base.ul = 0;
170 i2c_cmd_base.s.i2c_cmd = i2c_write;
171 i2c_cmd_base.s.dev_addr = write_cfg.dev_addr;
172 i2c_cmd_base.s.length = write_cfg.length;
173 i2c_cmd_base.s.bus_id = write_cfg.bus_id;
174
175 switch (write_cfg.i2c_speed) {
176 case 0:
177 i2c_cmd_base.s.i2c_speed = speed100k;
178 break;
179 case 1:
180 i2c_cmd_base.s.i2c_speed = speed400k;
181 break;
182 case 2:
183 i2c_cmd_base.s.i2c_speed = speed1000k;
184 break;
185 case 3:
186 i2c_cmd_base.s.i2c_speed = speed1400k;
187 break;
188 case 4:
189 i2c_cmd_base.s.i2c_speed = speed3400k;
190 break;
191 default:
192 dev_err(ndev_dev(privdata), "Invalid ConnectionSpeed\n");
193 }
194
195 if (write_cfg.length <= 32) {
196 i2c_cmd_base.s.mem_type = use_c2pmsg;
197 buf_len = (write_cfg.length + 3) / 4;
198 for (i = 0; i < buf_len; i++) {
199 writel(write_cfg.buf[i],
200 privdata->mmio + (AMD_C2P_MSG2 + i * 4));
201 }
202 } else {
203 i2c_cmd_base.s.mem_type = use_dram;
204 privdata->write_cfg.phy_addr = write_cfg.phy_addr;
205 write64((u64)privdata->write_cfg.phy_addr,
206 privdata->mmio + AMD_C2P_MSG2);
207 }
208
209 if (i2c_cmd_base.s.bus_id == i2c_bus_1) {
210 writel(i2c_cmd_base.ul, privdata->mmio + AMD_C2P_MSG1);
211 } else if (i2c_cmd_base.s.bus_id == i2c_bus_0) {
212 writel(i2c_cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
213 } else {
214 dev_err(ndev_dev(privdata), "%s Invalid bus id\n", __func__);
215 return -EINVAL;
216 }
217
218 return 0;
219 }
220 EXPORT_SYMBOL_GPL(amd_mp2_write);
221
222 int amd_i2c_register_cb(struct pci_dev *dev, const struct amd_i2c_pci_ops *ops,
223 void *dev_ctx)
224 {
225 struct amd_mp2_dev *privdata = pci_get_drvdata(dev);
226
227 privdata->ops = ops;
228 privdata->i2c_dev_ctx = dev_ctx;
229
230 if (!privdata->ops || !privdata->i2c_dev_ctx)
231 return -EINVAL;
232
233 return 0;
234 }
235 EXPORT_SYMBOL_GPL(amd_i2c_register_cb);
236
237 static void amd_mp2_pci_work(struct work_struct *work)
238 {
239 struct amd_mp2_dev *privdata = mp2_dev(work);
240 u32 readdata = 0;
241 int i;
242 int buf_len;
243 int sts = privdata->eventval.base.r.status;
244 int res = privdata->eventval.base.r.response;
245 int len = privdata->eventval.base.r.length;
246
247 if (res == command_success && sts == i2c_readcomplete_event) {
248 if (privdata->ops->read_complete) {
249 if (len <= 32) {
250 buf_len = (len + 3) / 4;
251 for (i = 0; i < buf_len; i++) {
252 readdata = readl(privdata->mmio +
253 (AMD_C2P_MSG2 + i * 4));
254 privdata->eventval.buf[i] = readdata;
255 }
256 privdata->ops->read_complete(privdata->eventval,
257 privdata->i2c_dev_ctx);
258 } else {
259 privdata->ops->read_complete(privdata->eventval,
260 privdata->i2c_dev_ctx);
261 }
262 }
263 } else if (res == command_success && sts == i2c_writecomplete_event) {
264 if (privdata->ops->write_complete)
265 privdata->ops->write_complete(privdata->eventval,
266 privdata->i2c_dev_ctx);
267 } else if (res == command_success && sts == i2c_busenable_complete) {
268 if (privdata->ops->connect_complete)
269 privdata->ops->connect_complete(privdata->eventval,
270 privdata->i2c_dev_ctx);
271 } else {
272 dev_err(ndev_dev(privdata), "ERROR!!nothing to be handled !\n");
273 }
274 }
275
276 static irqreturn_t amd_mp2_irq_isr(int irq, void *dev)
277 {
278 struct amd_mp2_dev *privdata = dev;
279 u32 val = 0;
280 unsigned long flags;
281
282 raw_spin_lock_irqsave(&privdata->lock, flags);
283 val = readl(privdata->mmio + AMD_P2C_MSG1);
284 if (val != 0) {
285 writel(0, privdata->mmio + AMD_P2C_MSG_INTEN);
286 privdata->eventval.base.ul = val;
287 } else {
288 val = readl(privdata->mmio + AMD_P2C_MSG2);
289 if (val != 0) {
290 writel(0, privdata->mmio + AMD_P2C_MSG_INTEN);
291 privdata->eventval.base.ul = val;
292 }
293 }
294
295 raw_spin_unlock_irqrestore(&privdata->lock, flags);
296 if (!privdata->ops)
297 return IRQ_NONE;
298
299 if (!privdata->requested)
300 return IRQ_HANDLED;
301
302 privdata->requested = false;
303 schedule_delayed_work(&privdata->work, 0);
304
305 return IRQ_HANDLED;
306 }
307
308 static ssize_t amd_mp2_debugfs_read(struct file *filp, char __user *ubuf,
309 size_t count, loff_t *offp)
310 {
311 struct amd_mp2_dev *privdata;
312 void __iomem *mmio;
313 u8 *buf;
314 size_t buf_size;
315 ssize_t ret, off;
316 union {
317 u64 v64;
318 u32 v32;
319 u16 v16;
320 } u;
321
322 privdata = filp->private_data;
323 mmio = privdata->mmio;
324 buf_size = min(count, 0x800ul);
325 buf = kmalloc(buf_size, GFP_KERNEL);
326
327 if (!buf)
328 return -ENOMEM;
329
330 off = 0;
331 off += scnprintf(buf + off, buf_size - off,
332 "Mp2 Device Information:\n");
333
334 off += scnprintf(buf + off, buf_size - off,
335 "========================\n");
336 off += scnprintf(buf + off, buf_size - off,
337 "\tMP2 C2P Message Register Dump:\n\n");
338 u.v32 = readl(privdata->mmio + AMD_C2P_MSG0);
339 off += scnprintf(buf + off, buf_size - off,
340 "AMD_C2P_MSG0 -\t\t\t%#06x\n", u.v32);
341
342 u.v32 = readl(privdata->mmio + AMD_C2P_MSG1);
343 off += scnprintf(buf + off, buf_size - off,
344 "AMD_C2P_MSG1 -\t\t\t%#06x\n", u.v32);
345
346 u.v32 = readl(privdata->mmio + AMD_C2P_MSG2);
347 off += scnprintf(buf + off, buf_size - off,
348 "AMD_C2P_MSG2 -\t\t\t%#06x\n", u.v32);
349
350 u.v32 = readl(privdata->mmio + AMD_C2P_MSG3);
351 off += scnprintf(buf + off, buf_size - off,
352 "AMD_C2P_MSG3 -\t\t\t%#06x\n", u.v32);
353
354 u.v32 = readl(privdata->mmio + AMD_C2P_MSG4);
355 off += scnprintf(buf + off, buf_size - off,
356 "AMD_C2P_MSG4 -\t\t\t%#06x\n", u.v32);
357
358 u.v32 = readl(privdata->mmio + AMD_C2P_MSG5);
359 off += scnprintf(buf + off, buf_size - off,
360 "AMD_C2P_MSG5 -\t\t\t%#06x\n", u.v32);
361
362 u.v32 = readl(privdata->mmio + AMD_C2P_MSG6);
363 off += scnprintf(buf + off, buf_size - off,
364 "AMD_C2P_MSG6 -\t\t\t%#06x\n", u.v32);
365
366 u.v32 = readl(privdata->mmio + AMD_C2P_MSG7);
367 off += scnprintf(buf + off, buf_size - off,
368 "AMD_C2P_MSG7 -\t\t\t%#06x\n", u.v32);
369
370 u.v32 = readl(privdata->mmio + AMD_C2P_MSG8);
371 off += scnprintf(buf + off, buf_size - off,
372 "AMD_C2P_MSG8 -\t\t\t%#06x\n", u.v32);
373
374 u.v32 = readl(privdata->mmio + AMD_C2P_MSG9);
375 off += scnprintf(buf + off, buf_size - off,
376 "AMD_C2P_MSG9 -\t\t\t%#06x\n", u.v32);
377
378 off += scnprintf(buf + off, buf_size - off,
379 "\n\tMP2 P2C Message Register Dump:\n\n");
380
381 u.v32 = readl(privdata->mmio + AMD_P2C_MSG1);
382 off += scnprintf(buf + off, buf_size - off,
383 "AMD_P2C_MSG1 -\t\t\t%#06x\n", u.v32);
384
385 u.v32 = readl(privdata->mmio + AMD_P2C_MSG2);
386 off += scnprintf(buf + off, buf_size - off,
387 "AMD_P2C_MSG2 -\t\t\t%#06x\n", u.v32);
388
389 u.v32 = readl(privdata->mmio + AMD_P2C_MSG_INTEN);
390 off += scnprintf(buf + off, buf_size - off,
391 "AMD_P2C_MSG_INTEN -\t\t%#06x\n", u.v32);
392
393 u.v32 = readl(privdata->mmio + AMD_P2C_MSG_INTSTS);
394 off += scnprintf(buf + off, buf_size - off,
395 "AMD_P2C_MSG_INTSTS -\t\t%#06x\n", u.v32);
396
397 ret = simple_read_from_buffer(ubuf, count, offp, buf, off);
398 kfree(buf);
399 return ret;
400 }
401
402 static void amd_mp2_init_debugfs(struct amd_mp2_dev *privdata)
403 {
404 if (!debugfs_dir) {
405 privdata->debugfs_dir = NULL;
406 privdata->debugfs_info = NULL;
407 } else {
408 privdata->debugfs_dir = debugfs_create_dir(ndev_name(privdata),
409 debugfs_dir);
410 if (!privdata->debugfs_dir) {
411 privdata->debugfs_info = NULL;
412 } else {
413 privdata->debugfs_info = debugfs_create_file(
414 "info", 0400, privdata->debugfs_dir,
415 privdata, &amd_mp2_debugfs_info);
416 }
417 }
418 }
419
420 static void amd_mp2_deinit_debugfs(struct amd_mp2_dev *privdata)
421 {
422 debugfs_remove_recursive(privdata->debugfs_dir);
423 }
424
425 static void amd_mp2_clear_reg(struct amd_mp2_dev *privdata)
426 {
427 int reg = 0;
428
429 for (reg = AMD_C2P_MSG0; reg <= AMD_C2P_MSG9; reg += 4)
430 writel(0, privdata->mmio + reg);
431
432 for (reg = AMD_P2C_MSG0; reg <= AMD_P2C_MSG2; reg += 4)
433 writel(0, privdata->mmio + reg);
434 }
435
436 static int amd_mp2_pci_init(struct amd_mp2_dev *privdata, struct pci_dev *pdev)
437 {
438 int rc;
439 int bar_index = 2;
440 resource_size_t size, base;
441
442 pci_set_drvdata(pdev, privdata);
443
444 rc = pci_enable_device(pdev);
445 if (rc)
446 goto err_pci_enable;
447
448 rc = pci_request_regions(pdev, DRIVER_NAME);
449 if (rc)
450 goto err_pci_regions;
451
452 pci_set_master(pdev);
453
454 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
455 if (rc) {
456 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
457 if (rc)
458 goto err_dma_mask;
459 dev_warn(ndev_dev(privdata), "Cannot DMA highmem\n");
460 }
461
462 rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
463 if (rc) {
464 rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
465 if (rc)
466 goto err_dma_mask;
467 dev_warn(ndev_dev(privdata), "Cannot DMA consistent highmem\n");
468 }
469
470 base = pci_resource_start(pdev, bar_index);
471 size = pci_resource_len(pdev, bar_index);
472 dev_dbg(ndev_dev(privdata), "Base addr:%llx size:%llx\n", base, size);
473
474 privdata->mmio = ioremap(base, size);
475 if (!privdata->mmio) {
476 rc = -EIO;
477 goto err_dma_mask;
478 }
479
480 /* Try to set up intx irq */
481 pci_intx(pdev, 1);
482 privdata->eventval.buf = NULL;
483 privdata->requested = false;
484 raw_spin_lock_init(&privdata->lock);
485 rc = request_irq(pdev->irq, amd_mp2_irq_isr, IRQF_SHARED, "mp2_irq_isr",
486 privdata);
487 if (rc)
488 goto err_intx_request;
489
490 return 0;
491
492 err_intx_request:
493 return rc;
494 err_dma_mask:
495 pci_clear_master(pdev);
496 pci_release_regions(pdev);
497 err_pci_regions:
498 pci_disable_device(pdev);
499 err_pci_enable:
500 pci_set_drvdata(pdev, NULL);
501 return rc;
502 }
503
504 static void amd_mp2_pci_deinit(struct amd_mp2_dev *privdata)
505 {
506 struct pci_dev *pdev = ndev_pdev(privdata);
507
508 pci_iounmap(pdev, privdata->mmio);
509
510 pci_clear_master(pdev);
511 pci_release_regions(pdev);
512 pci_disable_device(pdev);
513 pci_set_drvdata(pdev, NULL);
514 }
515
516 static int amd_mp2_pci_probe(struct pci_dev *pdev,
517 const struct pci_device_id *id)
518 {
519 struct amd_mp2_dev *privdata;
520 int rc;
521
522 dev_info(&pdev->dev, "MP2 device found [%04x:%04x] (rev %x)\n",
523 (int)pdev->vendor, (int)pdev->device, (int)pdev->revision);
524
525 privdata = kzalloc(sizeof(*privdata), GFP_KERNEL);
526 privdata->pdev = pdev;
527
528 if (!privdata) {
529 rc = -ENOMEM;
530 goto err_dev;
531 }
532
533 rc = amd_mp2_pci_init(privdata, pdev);
534 if (rc)
535 goto err_pci_init;
536 dev_dbg(&pdev->dev, "pci init done.\n");
537
538 INIT_DELAYED_WORK(&privdata->work, amd_mp2_pci_work);
539
540 amd_mp2_init_debugfs(privdata);
541 dev_info(&pdev->dev, "MP2 device registered.\n");
542 return 0;
543
544 err_pci_init:
545 kfree(privdata);
546 err_dev:
547 dev_err(&pdev->dev, "Memory Allocation Failed\n");
548 return rc;
549 }
550
551 static void amd_mp2_pci_remove(struct pci_dev *pdev)
552 {
553 struct amd_mp2_dev *privdata = pci_get_drvdata(pdev);
554
555 amd_mp2_deinit_debugfs(privdata);
556 amd_mp2_clear_reg(privdata);
557 cancel_delayed_work_sync(&privdata->work);
558 free_irq(pdev->irq, privdata);
559 pci_intx(pdev, 0);
560 amd_mp2_pci_deinit(privdata);
561 kfree(privdata);
562 }
563
564 static const struct file_operations amd_mp2_debugfs_info = {
565 .owner = THIS_MODULE,
566 .open = simple_open,
567 .read = amd_mp2_debugfs_read,
568 };
569
570 static const struct pci_device_id amd_mp2_pci_tbl[] = {
571 {PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_MP2)},
572 {0}
573 };
574 MODULE_DEVICE_TABLE(pci, amd_mp2_pci_tbl);
575
576 #ifdef CONFIG_PM_SLEEP
577 static int amd_mp2_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
578 {
579 struct amd_mp2_dev *privdata = pci_get_drvdata(pdev);
580
581 if (!privdata)
582 return -EINVAL;
583
584 return 0;
585 }
586
587 static int amd_mp2_pci_device_resume(struct pci_dev *pdev)
588 {
589 struct amd_mp2_dev *privdata = pci_get_drvdata(pdev);
590
591 if (!privdata)
592 return -EINVAL;
593
594 return 0;
595 }
596 #endif
597
598 static struct pci_driver amd_mp2_pci_driver = {
599 .name = DRIVER_NAME,
600 .id_table = amd_mp2_pci_tbl,
601 .probe = amd_mp2_pci_probe,
602 .remove = amd_mp2_pci_remove,
603 #ifdef CONFIG_PM_SLEEP
604 .suspend = amd_mp2_pci_device_suspend,
605 .resume = amd_mp2_pci_device_resume,
606 #endif
607 };
608
609 static int __init amd_mp2_pci_driver_init(void)
610 {
611 pr_info("%s: %s Version: %s\n", DRIVER_NAME, DRIVER_DESC, DRIVER_VER);
612
613 if (debugfs_initialized())
614 debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
615
616 return pci_register_driver(&amd_mp2_pci_driver);
617 }
618 module_init(amd_mp2_pci_driver_init);
619
620 static void __exit amd_mp2_pci_driver_exit(void)
621 {
622 pci_unregister_driver(&amd_mp2_pci_driver);
623 debugfs_remove_recursive(debugfs_dir);
624 }
625 module_exit(amd_mp2_pci_driver_exit);