Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/bcma/host_pci.c
15109 views
1
/*
2
* Broadcom specific AMBA
3
* PCI Host
4
*
5
* Licensed under the GNU/GPL. See COPYING for details.
6
*/
7
8
#include "bcma_private.h"
9
#include <linux/slab.h>
10
#include <linux/bcma/bcma.h>
11
#include <linux/pci.h>
12
13
static void bcma_host_pci_switch_core(struct bcma_device *core)
14
{
15
pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN,
16
core->addr);
17
pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2,
18
core->wrap);
19
core->bus->mapped_core = core;
20
pr_debug("Switched to core: 0x%X\n", core->id.id);
21
}
22
23
static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset)
24
{
25
if (core->bus->mapped_core != core)
26
bcma_host_pci_switch_core(core);
27
return ioread8(core->bus->mmio + offset);
28
}
29
30
static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset)
31
{
32
if (core->bus->mapped_core != core)
33
bcma_host_pci_switch_core(core);
34
return ioread16(core->bus->mmio + offset);
35
}
36
37
static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset)
38
{
39
if (core->bus->mapped_core != core)
40
bcma_host_pci_switch_core(core);
41
return ioread32(core->bus->mmio + offset);
42
}
43
44
static void bcma_host_pci_write8(struct bcma_device *core, u16 offset,
45
u8 value)
46
{
47
if (core->bus->mapped_core != core)
48
bcma_host_pci_switch_core(core);
49
iowrite8(value, core->bus->mmio + offset);
50
}
51
52
static void bcma_host_pci_write16(struct bcma_device *core, u16 offset,
53
u16 value)
54
{
55
if (core->bus->mapped_core != core)
56
bcma_host_pci_switch_core(core);
57
iowrite16(value, core->bus->mmio + offset);
58
}
59
60
static void bcma_host_pci_write32(struct bcma_device *core, u16 offset,
61
u32 value)
62
{
63
if (core->bus->mapped_core != core)
64
bcma_host_pci_switch_core(core);
65
iowrite32(value, core->bus->mmio + offset);
66
}
67
68
static u32 bcma_host_pci_aread32(struct bcma_device *core, u16 offset)
69
{
70
if (core->bus->mapped_core != core)
71
bcma_host_pci_switch_core(core);
72
return ioread32(core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset);
73
}
74
75
static void bcma_host_pci_awrite32(struct bcma_device *core, u16 offset,
76
u32 value)
77
{
78
if (core->bus->mapped_core != core)
79
bcma_host_pci_switch_core(core);
80
iowrite32(value, core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset);
81
}
82
83
const struct bcma_host_ops bcma_host_pci_ops = {
84
.read8 = bcma_host_pci_read8,
85
.read16 = bcma_host_pci_read16,
86
.read32 = bcma_host_pci_read32,
87
.write8 = bcma_host_pci_write8,
88
.write16 = bcma_host_pci_write16,
89
.write32 = bcma_host_pci_write32,
90
.aread32 = bcma_host_pci_aread32,
91
.awrite32 = bcma_host_pci_awrite32,
92
};
93
94
static int bcma_host_pci_probe(struct pci_dev *dev,
95
const struct pci_device_id *id)
96
{
97
struct bcma_bus *bus;
98
int err = -ENOMEM;
99
const char *name;
100
u32 val;
101
102
/* Alloc */
103
bus = kzalloc(sizeof(*bus), GFP_KERNEL);
104
if (!bus)
105
goto out;
106
107
/* Basic PCI configuration */
108
err = pci_enable_device(dev);
109
if (err)
110
goto err_kfree_bus;
111
112
name = dev_name(&dev->dev);
113
if (dev->driver && dev->driver->name)
114
name = dev->driver->name;
115
err = pci_request_regions(dev, name);
116
if (err)
117
goto err_pci_disable;
118
pci_set_master(dev);
119
120
/* Disable the RETRY_TIMEOUT register (0x41) to keep
121
* PCI Tx retries from interfering with C3 CPU state */
122
pci_read_config_dword(dev, 0x40, &val);
123
if ((val & 0x0000ff00) != 0)
124
pci_write_config_dword(dev, 0x40, val & 0xffff00ff);
125
126
/* SSB needed additional powering up, do we have any AMBA PCI cards? */
127
if (!pci_is_pcie(dev))
128
pr_err("PCI card detected, report problems.\n");
129
130
/* Map MMIO */
131
err = -ENOMEM;
132
bus->mmio = pci_iomap(dev, 0, ~0UL);
133
if (!bus->mmio)
134
goto err_pci_release_regions;
135
136
/* Host specific */
137
bus->host_pci = dev;
138
bus->hosttype = BCMA_HOSTTYPE_PCI;
139
bus->ops = &bcma_host_pci_ops;
140
141
/* Register */
142
err = bcma_bus_register(bus);
143
if (err)
144
goto err_pci_unmap_mmio;
145
146
pci_set_drvdata(dev, bus);
147
148
out:
149
return err;
150
151
err_pci_unmap_mmio:
152
pci_iounmap(dev, bus->mmio);
153
err_pci_release_regions:
154
pci_release_regions(dev);
155
err_pci_disable:
156
pci_disable_device(dev);
157
err_kfree_bus:
158
kfree(bus);
159
return err;
160
}
161
162
static void bcma_host_pci_remove(struct pci_dev *dev)
163
{
164
struct bcma_bus *bus = pci_get_drvdata(dev);
165
166
bcma_bus_unregister(bus);
167
pci_iounmap(dev, bus->mmio);
168
pci_release_regions(dev);
169
pci_disable_device(dev);
170
kfree(bus);
171
pci_set_drvdata(dev, NULL);
172
}
173
174
static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
175
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
176
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
177
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
178
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
179
{ 0, },
180
};
181
MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl);
182
183
static struct pci_driver bcma_pci_bridge_driver = {
184
.name = "bcma-pci-bridge",
185
.id_table = bcma_pci_bridge_tbl,
186
.probe = bcma_host_pci_probe,
187
.remove = bcma_host_pci_remove,
188
};
189
190
int __init bcma_host_pci_init(void)
191
{
192
return pci_register_driver(&bcma_pci_bridge_driver);
193
}
194
195
void __exit bcma_host_pci_exit(void)
196
{
197
pci_unregister_driver(&bcma_pci_bridge_driver);
198
}
199
200