Blame view
drivers/mcb/mcb-pci.c
2.82 KB
b886d83c5
|
1 |
// SPDX-License-Identifier: GPL-2.0-only |
b71bb8639
|
2 3 4 5 6 |
/* * MEN Chameleon Bus. * * Copyright (C) 2014 MEN Mikroelektronik GmbH (www.men.de) * Author: Johannes Thumshirn <johannes.thumshirn@men.de> |
b71bb8639
|
7 8 9 10 11 12 13 14 15 16 |
*/ #include <linux/module.h> #include <linux/pci.h> #include <linux/mcb.h> #include "mcb-internal.h" struct priv { struct mcb_bus *bus; |
7b7c54914
|
17 |
phys_addr_t mapbase; |
b71bb8639
|
18 19 |
void __iomem *base; }; |
4ec65b77c
|
20 21 22 23 24 25 26 27 |
static int mcb_pci_get_irq(struct mcb_device *mdev) { struct mcb_bus *mbus = mdev->bus; struct device *dev = mbus->carrier; struct pci_dev *pdev = to_pci_dev(dev); return pdev->irq; } |
b71bb8639
|
28 29 |
static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { |
7b7c54914
|
30 |
struct resource *res; |
b71bb8639
|
31 |
struct priv *priv; |
b71bb8639
|
32 |
int ret; |
b71bb8639
|
33 34 35 36 37 38 39 40 41 42 43 44 |
unsigned long flags; priv = devm_kzalloc(&pdev->dev, sizeof(struct priv), GFP_KERNEL); if (!priv) return -ENOMEM; ret = pci_enable_device(pdev); if (ret) { dev_err(&pdev->dev, "Failed to enable PCI device "); return -ENODEV; } |
15bb81d33
|
45 |
pci_set_master(pdev); |
b71bb8639
|
46 |
|
7b7c54914
|
47 48 |
priv->mapbase = pci_resource_start(pdev, 0); if (!priv->mapbase) { |
b71bb8639
|
49 50 |
dev_err(&pdev->dev, "No PCI resource "); |
bf25c1997
|
51 |
ret = -ENODEV; |
a48742bce
|
52 |
goto out_disable; |
b71bb8639
|
53 |
} |
d19366f1d
|
54 55 56 |
res = devm_request_mem_region(&pdev->dev, priv->mapbase, CHAM_HEADER_SIZE, KBUILD_MODNAME); |
d86fb45b5
|
57 |
if (!res) { |
7b7c54914
|
58 59 |
dev_err(&pdev->dev, "Failed to request PCI memory "); |
d86fb45b5
|
60 |
ret = -EBUSY; |
a48742bce
|
61 |
goto out_disable; |
b71bb8639
|
62 |
} |
d19366f1d
|
63 |
priv->base = devm_ioremap(&pdev->dev, priv->mapbase, CHAM_HEADER_SIZE); |
b71bb8639
|
64 65 66 67 |
if (!priv->base) { dev_err(&pdev->dev, "Cannot ioremap "); ret = -ENOMEM; |
d19366f1d
|
68 |
goto out_disable; |
b71bb8639
|
69 70 71 72 73 74 75 76 |
} flags = pci_resource_flags(pdev, 0); if (flags & IORESOURCE_IO) { ret = -ENOTSUPP; dev_err(&pdev->dev, "IO mapped PCI devices are not supported "); |
d19366f1d
|
77 |
goto out_disable; |
b71bb8639
|
78 79 80 |
} pci_set_drvdata(pdev, priv); |
4ec65b77c
|
81 82 83 |
priv->bus = mcb_alloc_bus(&pdev->dev); if (IS_ERR(priv->bus)) { ret = PTR_ERR(priv->bus); |
d19366f1d
|
84 |
goto out_disable; |
4ec65b77c
|
85 86 87 |
} priv->bus->get_irq = mcb_pci_get_irq; |
b71bb8639
|
88 |
|
7b7c54914
|
89 |
ret = chameleon_parse_cells(priv->bus, priv->mapbase, priv->base); |
b71bb8639
|
90 |
if (ret < 0) |
41ada9df7
|
91 |
goto out_mcb_bus; |
b71bb8639
|
92 |
|
8cd1f9d01
|
93 94 |
dev_dbg(&pdev->dev, "Found %d cells ", ret); |
b71bb8639
|
95 96 |
mcb_bus_add_devices(priv->bus); |
7b7c54914
|
97 |
return 0; |
41ada9df7
|
98 99 |
out_mcb_bus: mcb_release_bus(priv->bus); |
a48742bce
|
100 |
out_disable: |
b71bb8639
|
101 102 103 104 105 106 107 108 109 |
pci_disable_device(pdev); return ret; } static void mcb_pci_remove(struct pci_dev *pdev) { struct priv *priv = pci_get_drvdata(pdev); mcb_release_bus(priv->bus); |
7b7c54914
|
110 |
|
7b7c54914
|
111 |
pci_disable_device(pdev); |
b71bb8639
|
112 113 114 115 |
} static const struct pci_device_id mcb_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_MEN, PCI_DEVICE_ID_MEN_CHAMELEON) }, |
29ea6be36
|
116 |
{ PCI_DEVICE(PCI_VENDOR_ID_ALTERA, PCI_DEVICE_ID_MEN_CHAMELEON) }, |
b71bb8639
|
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
{ 0 }, }; MODULE_DEVICE_TABLE(pci, mcb_pci_tbl); static struct pci_driver mcb_pci_driver = { .name = "mcb-pci", .id_table = mcb_pci_tbl, .probe = mcb_pci_probe, .remove = mcb_pci_remove, }; module_pci_driver(mcb_pci_driver); MODULE_AUTHOR("Johannes Thumshirn <johannes.thumshirn@men.de>"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("MCB over PCI support"); |