2 * Broadcom specific AMBA
5 * Licensed under the GNU/GPL. See COPYING for details.
8 #include "bcma_private.h"
9 #include <linux/slab.h>
10 #include <linux/bcma/bcma.h>
11 #include <linux/pci.h>
12 #include <linux/module.h>
14 static void bcma_host_pci_switch_core(struct bcma_device
*core
)
16 pci_write_config_dword(core
->bus
->host_pci
, BCMA_PCI_BAR0_WIN
,
18 pci_write_config_dword(core
->bus
->host_pci
, BCMA_PCI_BAR0_WIN2
,
20 core
->bus
->mapped_core
= core
;
21 bcma_debug(core
->bus
, "Switched to core: 0x%X\n", core
->id
.id
);
24 /* Provides access to the requested core. Returns base offset that has to be
25 * used. It makes use of fixed windows when possible. */
26 static u16
bcma_host_pci_provide_access_to_core(struct bcma_device
*core
)
28 switch (core
->id
.id
) {
29 case BCMA_CORE_CHIPCOMMON
:
30 return 3 * BCMA_CORE_SIZE
;
32 return 2 * BCMA_CORE_SIZE
;
35 if (core
->bus
->mapped_core
!= core
)
36 bcma_host_pci_switch_core(core
);
40 static u8
bcma_host_pci_read8(struct bcma_device
*core
, u16 offset
)
42 offset
+= bcma_host_pci_provide_access_to_core(core
);
43 return ioread8(core
->bus
->mmio
+ offset
);
46 static u16
bcma_host_pci_read16(struct bcma_device
*core
, u16 offset
)
48 offset
+= bcma_host_pci_provide_access_to_core(core
);
49 return ioread16(core
->bus
->mmio
+ offset
);
52 static u32
bcma_host_pci_read32(struct bcma_device
*core
, u16 offset
)
54 offset
+= bcma_host_pci_provide_access_to_core(core
);
55 return ioread32(core
->bus
->mmio
+ offset
);
58 static void bcma_host_pci_write8(struct bcma_device
*core
, u16 offset
,
61 offset
+= bcma_host_pci_provide_access_to_core(core
);
62 iowrite8(value
, core
->bus
->mmio
+ offset
);
65 static void bcma_host_pci_write16(struct bcma_device
*core
, u16 offset
,
68 offset
+= bcma_host_pci_provide_access_to_core(core
);
69 iowrite16(value
, core
->bus
->mmio
+ offset
);
72 static void bcma_host_pci_write32(struct bcma_device
*core
, u16 offset
,
75 offset
+= bcma_host_pci_provide_access_to_core(core
);
76 iowrite32(value
, core
->bus
->mmio
+ offset
);
79 #ifdef CONFIG_BCMA_BLOCKIO
80 static void bcma_host_pci_block_read(struct bcma_device
*core
, void *buffer
,
81 size_t count
, u16 offset
, u8 reg_width
)
83 void __iomem
*addr
= core
->bus
->mmio
+ offset
;
84 if (core
->bus
->mapped_core
!= core
)
85 bcma_host_pci_switch_core(core
);
88 ioread8_rep(addr
, buffer
, count
);
92 ioread16_rep(addr
, buffer
, count
>> 1);
96 ioread32_rep(addr
, buffer
, count
>> 2);
103 static void bcma_host_pci_block_write(struct bcma_device
*core
,
104 const void *buffer
, size_t count
,
105 u16 offset
, u8 reg_width
)
107 void __iomem
*addr
= core
->bus
->mmio
+ offset
;
108 if (core
->bus
->mapped_core
!= core
)
109 bcma_host_pci_switch_core(core
);
112 iowrite8_rep(addr
, buffer
, count
);
116 iowrite16_rep(addr
, buffer
, count
>> 1);
120 iowrite32_rep(addr
, buffer
, count
>> 2);
128 static u32
bcma_host_pci_aread32(struct bcma_device
*core
, u16 offset
)
130 if (core
->bus
->mapped_core
!= core
)
131 bcma_host_pci_switch_core(core
);
132 return ioread32(core
->bus
->mmio
+ (1 * BCMA_CORE_SIZE
) + offset
);
135 static void bcma_host_pci_awrite32(struct bcma_device
*core
, u16 offset
,
138 if (core
->bus
->mapped_core
!= core
)
139 bcma_host_pci_switch_core(core
);
140 iowrite32(value
, core
->bus
->mmio
+ (1 * BCMA_CORE_SIZE
) + offset
);
143 static const struct bcma_host_ops bcma_host_pci_ops
= {
144 .read8
= bcma_host_pci_read8
,
145 .read16
= bcma_host_pci_read16
,
146 .read32
= bcma_host_pci_read32
,
147 .write8
= bcma_host_pci_write8
,
148 .write16
= bcma_host_pci_write16
,
149 .write32
= bcma_host_pci_write32
,
150 #ifdef CONFIG_BCMA_BLOCKIO
151 .block_read
= bcma_host_pci_block_read
,
152 .block_write
= bcma_host_pci_block_write
,
154 .aread32
= bcma_host_pci_aread32
,
155 .awrite32
= bcma_host_pci_awrite32
,
158 static int bcma_host_pci_probe(struct pci_dev
*dev
,
159 const struct pci_device_id
*id
)
161 struct bcma_bus
*bus
;
167 bus
= kzalloc(sizeof(*bus
), GFP_KERNEL
);
171 /* Basic PCI configuration */
172 err
= pci_enable_device(dev
);
176 name
= dev_name(&dev
->dev
);
177 if (dev
->driver
&& dev
->driver
->name
)
178 name
= dev
->driver
->name
;
179 err
= pci_request_regions(dev
, name
);
181 goto err_pci_disable
;
184 /* Disable the RETRY_TIMEOUT register (0x41) to keep
185 * PCI Tx retries from interfering with C3 CPU state */
186 pci_read_config_dword(dev
, 0x40, &val
);
187 if ((val
& 0x0000ff00) != 0)
188 pci_write_config_dword(dev
, 0x40, val
& 0xffff00ff);
190 /* SSB needed additional powering up, do we have any AMBA PCI cards? */
191 if (!pci_is_pcie(dev
))
192 bcma_err(bus
, "PCI card detected, report problems.\n");
196 bus
->mmio
= pci_iomap(dev
, 0, ~0UL);
198 goto err_pci_release_regions
;
202 bus
->hosttype
= BCMA_HOSTTYPE_PCI
;
203 bus
->ops
= &bcma_host_pci_ops
;
205 bus
->boardinfo
.vendor
= bus
->host_pci
->subsystem_vendor
;
206 bus
->boardinfo
.type
= bus
->host_pci
->subsystem_device
;
209 err
= bcma_bus_register(bus
);
211 goto err_pci_unmap_mmio
;
213 pci_set_drvdata(dev
, bus
);
219 pci_iounmap(dev
, bus
->mmio
);
220 err_pci_release_regions
:
221 pci_release_regions(dev
);
223 pci_disable_device(dev
);
229 static void bcma_host_pci_remove(struct pci_dev
*dev
)
231 struct bcma_bus
*bus
= pci_get_drvdata(dev
);
233 bcma_bus_unregister(bus
);
234 pci_iounmap(dev
, bus
->mmio
);
235 pci_release_regions(dev
);
236 pci_disable_device(dev
);
238 pci_set_drvdata(dev
, NULL
);
241 #ifdef CONFIG_PM_SLEEP
242 static int bcma_host_pci_suspend(struct device
*dev
)
244 struct pci_dev
*pdev
= to_pci_dev(dev
);
245 struct bcma_bus
*bus
= pci_get_drvdata(pdev
);
247 bus
->mapped_core
= NULL
;
249 return bcma_bus_suspend(bus
);
252 static int bcma_host_pci_resume(struct device
*dev
)
254 struct pci_dev
*pdev
= to_pci_dev(dev
);
255 struct bcma_bus
*bus
= pci_get_drvdata(pdev
);
257 return bcma_bus_resume(bus
);
260 static SIMPLE_DEV_PM_OPS(bcma_pm_ops
, bcma_host_pci_suspend
,
261 bcma_host_pci_resume
);
262 #define BCMA_PM_OPS (&bcma_pm_ops)
264 #else /* CONFIG_PM_SLEEP */
266 #define BCMA_PM_OPS NULL
268 #endif /* CONFIG_PM_SLEEP */
270 static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl
) = {
271 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM
, 0x0576) },
272 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM
, 43224) },
273 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM
, 0x4331) },
274 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM
, 0x4353) },
275 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM
, 0x4357) },
276 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM
, 0x4358) },
277 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM
, 0x4359) },
278 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM
, 0x4365) },
279 { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM
, 0x4727) },
282 MODULE_DEVICE_TABLE(pci
, bcma_pci_bridge_tbl
);
284 static struct pci_driver bcma_pci_bridge_driver
= {
285 .name
= "bcma-pci-bridge",
286 .id_table
= bcma_pci_bridge_tbl
,
287 .probe
= bcma_host_pci_probe
,
288 .remove
= bcma_host_pci_remove
,
289 .driver
.pm
= BCMA_PM_OPS
,
292 int __init
bcma_host_pci_init(void)
294 return pci_register_driver(&bcma_pci_bridge_driver
);
297 void __exit
bcma_host_pci_exit(void)
299 pci_unregister_driver(&bcma_pci_bridge_driver
);