0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/module.h>
0010 #include <linux/pci.h>
0011 #include <linux/mcb.h>
0012
0013 #include "mcb-internal.h"
0014
0015 struct priv {
0016 struct mcb_bus *bus;
0017 phys_addr_t mapbase;
0018 void __iomem *base;
0019 };
0020
0021 static int mcb_pci_get_irq(struct mcb_device *mdev)
0022 {
0023 struct mcb_bus *mbus = mdev->bus;
0024 struct device *dev = mbus->carrier;
0025 struct pci_dev *pdev = to_pci_dev(dev);
0026
0027 return pdev->irq;
0028 }
0029
0030 static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
0031 {
0032 struct resource *res;
0033 struct priv *priv;
0034 int ret;
0035 unsigned long flags;
0036
0037 priv = devm_kzalloc(&pdev->dev, sizeof(struct priv), GFP_KERNEL);
0038 if (!priv)
0039 return -ENOMEM;
0040
0041 ret = pci_enable_device(pdev);
0042 if (ret) {
0043 dev_err(&pdev->dev, "Failed to enable PCI device\n");
0044 return -ENODEV;
0045 }
0046 pci_set_master(pdev);
0047
0048 priv->mapbase = pci_resource_start(pdev, 0);
0049 if (!priv->mapbase) {
0050 dev_err(&pdev->dev, "No PCI resource\n");
0051 ret = -ENODEV;
0052 goto out_disable;
0053 }
0054
0055 res = devm_request_mem_region(&pdev->dev, priv->mapbase,
0056 CHAM_HEADER_SIZE,
0057 KBUILD_MODNAME);
0058 if (!res) {
0059 dev_err(&pdev->dev, "Failed to request PCI memory\n");
0060 ret = -EBUSY;
0061 goto out_disable;
0062 }
0063
0064 priv->base = devm_ioremap(&pdev->dev, priv->mapbase, CHAM_HEADER_SIZE);
0065 if (!priv->base) {
0066 dev_err(&pdev->dev, "Cannot ioremap\n");
0067 ret = -ENOMEM;
0068 goto out_disable;
0069 }
0070
0071 flags = pci_resource_flags(pdev, 0);
0072 if (flags & IORESOURCE_IO) {
0073 ret = -ENOTSUPP;
0074 dev_err(&pdev->dev,
0075 "IO mapped PCI devices are not supported\n");
0076 goto out_disable;
0077 }
0078
0079 pci_set_drvdata(pdev, priv);
0080
0081 priv->bus = mcb_alloc_bus(&pdev->dev);
0082 if (IS_ERR(priv->bus)) {
0083 ret = PTR_ERR(priv->bus);
0084 goto out_disable;
0085 }
0086
0087 priv->bus->get_irq = mcb_pci_get_irq;
0088
0089 ret = chameleon_parse_cells(priv->bus, priv->mapbase, priv->base);
0090 if (ret < 0)
0091 goto out_mcb_bus;
0092
0093 dev_dbg(&pdev->dev, "Found %d cells\n", ret);
0094
0095 mcb_bus_add_devices(priv->bus);
0096
0097 return 0;
0098
0099 out_mcb_bus:
0100 mcb_release_bus(priv->bus);
0101 out_disable:
0102 pci_disable_device(pdev);
0103 return ret;
0104 }
0105
0106 static void mcb_pci_remove(struct pci_dev *pdev)
0107 {
0108 struct priv *priv = pci_get_drvdata(pdev);
0109
0110 mcb_release_bus(priv->bus);
0111
0112 pci_disable_device(pdev);
0113 }
0114
0115 static const struct pci_device_id mcb_pci_tbl[] = {
0116 { PCI_DEVICE(PCI_VENDOR_ID_MEN, PCI_DEVICE_ID_MEN_CHAMELEON) },
0117 { PCI_DEVICE(PCI_VENDOR_ID_ALTERA, PCI_DEVICE_ID_MEN_CHAMELEON) },
0118 { 0 },
0119 };
0120 MODULE_DEVICE_TABLE(pci, mcb_pci_tbl);
0121
0122 static struct pci_driver mcb_pci_driver = {
0123 .name = "mcb-pci",
0124 .id_table = mcb_pci_tbl,
0125 .probe = mcb_pci_probe,
0126 .remove = mcb_pci_remove,
0127 };
0128
0129 module_pci_driver(mcb_pci_driver);
0130
0131 MODULE_AUTHOR("Johannes Thumshirn <johannes.thumshirn@men.de>");
0132 MODULE_LICENSE("GPL");
0133 MODULE_DESCRIPTION("MCB over PCI support");
0134 MODULE_IMPORT_NS(MCB);