1243ac210SCorey Minyard // SPDX-License-Identifier: GPL-2.0+
213d0b35cSCorey Minyard /*
313d0b35cSCorey Minyard * ipmi_si_pci.c
413d0b35cSCorey Minyard *
513d0b35cSCorey Minyard * Handling for IPMI devices on the PCI bus.
613d0b35cSCorey Minyard */
725880f7dSJoe Perches
825880f7dSJoe Perches #define pr_fmt(fmt) "ipmi_pci: " fmt
925880f7dSJoe Perches
1013d0b35cSCorey Minyard #include <linux/module.h>
1113d0b35cSCorey Minyard #include <linux/pci.h>
1213d0b35cSCorey Minyard #include "ipmi_si.h"
1313d0b35cSCorey Minyard
1413d0b35cSCorey Minyard static bool pci_registered;
1513d0b35cSCorey Minyard
1613d0b35cSCorey Minyard static bool si_trypci = true;
1713d0b35cSCorey Minyard
1813d0b35cSCorey Minyard module_param_named(trypci, si_trypci, bool, 0);
19*07cbd87bSAndy Shevchenko MODULE_PARM_DESC(trypci,
20*07cbd87bSAndy Shevchenko "Setting this to zero will disable the default scan of the interfaces identified via pci");
2113d0b35cSCorey Minyard
22ad2575f8SCorey Minyard #define PCI_DEVICE_ID_HP_MMC 0x121A
2313d0b35cSCorey Minyard
ipmi_pci_probe_regspacing(struct si_sm_io * io)2413d0b35cSCorey Minyard static int ipmi_pci_probe_regspacing(struct si_sm_io *io)
2513d0b35cSCorey Minyard {
2613d0b35cSCorey Minyard if (io->si_type == SI_KCS) {
2713d0b35cSCorey Minyard unsigned char status;
2813d0b35cSCorey Minyard int regspacing;
2913d0b35cSCorey Minyard
3013d0b35cSCorey Minyard io->regsize = DEFAULT_REGSIZE;
3113d0b35cSCorey Minyard io->regshift = 0;
3213d0b35cSCorey Minyard
3313d0b35cSCorey Minyard /* detect 1, 4, 16byte spacing */
3413d0b35cSCorey Minyard for (regspacing = DEFAULT_REGSPACING; regspacing <= 16;) {
3513d0b35cSCorey Minyard io->regspacing = regspacing;
3613d0b35cSCorey Minyard if (io->io_setup(io)) {
3725880f7dSJoe Perches dev_err(io->dev, "Could not setup I/O space\n");
3813d0b35cSCorey Minyard return DEFAULT_REGSPACING;
3913d0b35cSCorey Minyard }
4013d0b35cSCorey Minyard /* write invalid cmd */
4113d0b35cSCorey Minyard io->outputb(io, 1, 0x10);
4213d0b35cSCorey Minyard /* read status back */
4313d0b35cSCorey Minyard status = io->inputb(io, 1);
4413d0b35cSCorey Minyard io->io_cleanup(io);
4513d0b35cSCorey Minyard if (status)
4613d0b35cSCorey Minyard return regspacing;
4713d0b35cSCorey Minyard regspacing *= 4;
4813d0b35cSCorey Minyard }
4913d0b35cSCorey Minyard }
5013d0b35cSCorey Minyard return DEFAULT_REGSPACING;
5113d0b35cSCorey Minyard }
5213d0b35cSCorey Minyard
53bc48fa1bSCorey Minyard static struct pci_device_id ipmi_pci_blacklist[] = {
54bc48fa1bSCorey Minyard /*
55bc48fa1bSCorey Minyard * This is a "Virtual IPMI device", whatever that is. It appears
56bc48fa1bSCorey Minyard * as a KCS device by the class, but it is not one.
57bc48fa1bSCorey Minyard */
58bc48fa1bSCorey Minyard { PCI_VDEVICE(REALTEK, 0x816c) },
59bc48fa1bSCorey Minyard { 0, }
60bc48fa1bSCorey Minyard };
61bc48fa1bSCorey Minyard
ipmi_pci_probe(struct pci_dev * pdev,const struct pci_device_id * ent)6213d0b35cSCorey Minyard static int ipmi_pci_probe(struct pci_dev *pdev,
6313d0b35cSCorey Minyard const struct pci_device_id *ent)
6413d0b35cSCorey Minyard {
6513d0b35cSCorey Minyard int rv;
6613d0b35cSCorey Minyard struct si_sm_io io;
6713d0b35cSCorey Minyard
68bc48fa1bSCorey Minyard if (pci_match_id(ipmi_pci_blacklist, pdev))
69bc48fa1bSCorey Minyard return -ENODEV;
70bc48fa1bSCorey Minyard
7113d0b35cSCorey Minyard memset(&io, 0, sizeof(io));
7213d0b35cSCorey Minyard io.addr_source = SI_PCI;
7313d0b35cSCorey Minyard dev_info(&pdev->dev, "probing via PCI");
7413d0b35cSCorey Minyard
75ad2575f8SCorey Minyard switch (pdev->class) {
76ad2575f8SCorey Minyard case PCI_CLASS_SERIAL_IPMI_SMIC:
7713d0b35cSCorey Minyard io.si_type = SI_SMIC;
7813d0b35cSCorey Minyard break;
7913d0b35cSCorey Minyard
80ad2575f8SCorey Minyard case PCI_CLASS_SERIAL_IPMI_KCS:
8113d0b35cSCorey Minyard io.si_type = SI_KCS;
8213d0b35cSCorey Minyard break;
8313d0b35cSCorey Minyard
84ad2575f8SCorey Minyard case PCI_CLASS_SERIAL_IPMI_BT:
8513d0b35cSCorey Minyard io.si_type = SI_BT;
8613d0b35cSCorey Minyard break;
8713d0b35cSCorey Minyard
8813d0b35cSCorey Minyard default:
89ad2575f8SCorey Minyard dev_info(&pdev->dev, "Unknown IPMI class: %x\n", pdev->class);
9013d0b35cSCorey Minyard return -ENOMEM;
9113d0b35cSCorey Minyard }
9213d0b35cSCorey Minyard
932dafddb8SAndy Shevchenko rv = pcim_enable_device(pdev);
9413d0b35cSCorey Minyard if (rv) {
9513d0b35cSCorey Minyard dev_err(&pdev->dev, "couldn't enable PCI device\n");
9613d0b35cSCorey Minyard return rv;
9713d0b35cSCorey Minyard }
9813d0b35cSCorey Minyard
991ac8aa8dSCorey Minyard if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
100f6296bdcSCorey Minyard io.addr_space = IPMI_IO_ADDR_SPACE;
1011ac8aa8dSCorey Minyard io.io_setup = ipmi_si_port_setup;
1021ac8aa8dSCorey Minyard } else {
103f6296bdcSCorey Minyard io.addr_space = IPMI_MEM_ADDR_SPACE;
1041ac8aa8dSCorey Minyard io.io_setup = ipmi_si_mem_setup;
1051ac8aa8dSCorey Minyard }
10613d0b35cSCorey Minyard io.addr_data = pci_resource_start(pdev, 0);
10713d0b35cSCorey Minyard
10801508d9eSMeelis Roos io.dev = &pdev->dev;
10901508d9eSMeelis Roos
11013d0b35cSCorey Minyard io.regspacing = ipmi_pci_probe_regspacing(&io);
11113d0b35cSCorey Minyard io.regsize = DEFAULT_REGSIZE;
11213d0b35cSCorey Minyard io.regshift = 0;
11313d0b35cSCorey Minyard
11413d0b35cSCorey Minyard io.irq = pdev->irq;
11513d0b35cSCorey Minyard if (io.irq)
11613d0b35cSCorey Minyard io.irq_setup = ipmi_std_irq_setup;
11713d0b35cSCorey Minyard
11813d0b35cSCorey Minyard dev_info(&pdev->dev, "%pR regsize %d spacing %d irq %d\n",
11913d0b35cSCorey Minyard &pdev->resource[0], io.regsize, io.regspacing, io.irq);
12013d0b35cSCorey Minyard
1212dafddb8SAndy Shevchenko return ipmi_si_add_smi(&io);
12213d0b35cSCorey Minyard }
12313d0b35cSCorey Minyard
ipmi_pci_remove(struct pci_dev * pdev)12413d0b35cSCorey Minyard static void ipmi_pci_remove(struct pci_dev *pdev)
12513d0b35cSCorey Minyard {
12613d0b35cSCorey Minyard ipmi_si_remove_by_dev(&pdev->dev);
12713d0b35cSCorey Minyard }
12813d0b35cSCorey Minyard
12913d0b35cSCorey Minyard static const struct pci_device_id ipmi_pci_devices[] = {
130ad2575f8SCorey Minyard { PCI_VDEVICE(HP, PCI_DEVICE_ID_HP_MMC) },
131ad2575f8SCorey Minyard { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_IPMI_SMIC, ~0) },
132ad2575f8SCorey Minyard { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_IPMI_KCS, ~0) },
133ad2575f8SCorey Minyard { PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_IPMI_BT, ~0) },
13413d0b35cSCorey Minyard { 0, }
13513d0b35cSCorey Minyard };
13613d0b35cSCorey Minyard MODULE_DEVICE_TABLE(pci, ipmi_pci_devices);
13713d0b35cSCorey Minyard
13813d0b35cSCorey Minyard static struct pci_driver ipmi_pci_driver = {
139104fb25fSCorey Minyard .name = SI_DEVICE_NAME,
14013d0b35cSCorey Minyard .id_table = ipmi_pci_devices,
14113d0b35cSCorey Minyard .probe = ipmi_pci_probe,
14213d0b35cSCorey Minyard .remove = ipmi_pci_remove,
14313d0b35cSCorey Minyard };
14413d0b35cSCorey Minyard
ipmi_si_pci_init(void)14513d0b35cSCorey Minyard void ipmi_si_pci_init(void)
14613d0b35cSCorey Minyard {
14713d0b35cSCorey Minyard if (si_trypci) {
14813d0b35cSCorey Minyard int rv = pci_register_driver(&ipmi_pci_driver);
14913d0b35cSCorey Minyard if (rv)
15025880f7dSJoe Perches pr_err("Unable to register PCI driver: %d\n", rv);
15113d0b35cSCorey Minyard else
15213d0b35cSCorey Minyard pci_registered = true;
15313d0b35cSCorey Minyard }
15413d0b35cSCorey Minyard }
15513d0b35cSCorey Minyard
ipmi_si_pci_shutdown(void)15613d0b35cSCorey Minyard void ipmi_si_pci_shutdown(void)
15713d0b35cSCorey Minyard {
15813d0b35cSCorey Minyard if (pci_registered)
15913d0b35cSCorey Minyard pci_unregister_driver(&ipmi_pci_driver);
16013d0b35cSCorey Minyard }
161