Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
[pandora-kernel.git] / drivers / bcma / host_pci.c
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 }