aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2008-02-29 05:36:12 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-03-06 17:09:43 -0500
commitaab547ce0d1493d400b6468c521a0137cd8c1edf (patch)
tree84625da40d905669a28a5770de111225667d5f27
parent69d3b6f491545d326135a1def4e290cd577c9a36 (diff)
ssb: Add Gigabit Ethernet driver
This adds the Gigabit Ethernet driver for the SSB Gigabit Ethernet core. This driver actually is a frontend to the Tigon3 driver. So the real work is done by tg3. This device is used in the Linksys WRT350N. Signed-off-by: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/ssb/Kconfig9
-rw-r--r--drivers/ssb/Makefile1
-rw-r--r--drivers/ssb/driver_gige.c294
-rw-r--r--drivers/ssb/driver_mipscore.c1
-rw-r--r--drivers/ssb/driver_pcicore.c160
-rw-r--r--drivers/ssb/embedded.c90
-rw-r--r--drivers/ssb/main.c30
-rw-r--r--drivers/ssb/ssb_private.h2
-rw-r--r--include/linux/ssb/ssb.h7
-rw-r--r--include/linux/ssb/ssb_driver_gige.h174
-rw-r--r--include/linux/ssb/ssb_driver_pci.h19
11 files changed, 715 insertions, 72 deletions
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig
index adea792fb67..f69ef0ba261 100644
--- a/drivers/ssb/Kconfig
+++ b/drivers/ssb/Kconfig
@@ -125,4 +125,13 @@ config SSB_DRIVER_EXTIF
125 125
126 If unsure, say N 126 If unsure, say N
127 127
128config SSB_DRIVER_GIGE
129 bool "SSB Broadcom Gigabit Ethernet driver"
130 depends on SSB_PCIHOST_POSSIBLE && SSB_EMBEDDED && MIPS
131 help
132 Driver for the Sonics Silicon Backplane attached
133 Broadcom Gigabit Ethernet.
134
135 If unsure, say N
136
128endmenu 137endmenu
diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile
index de94c2eb7a3..910f35e32fc 100644
--- a/drivers/ssb/Makefile
+++ b/drivers/ssb/Makefile
@@ -11,6 +11,7 @@ ssb-y += driver_chipcommon.o
11ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o 11ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o
12ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o 12ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o
13ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o 13ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o
14ssb-$(CONFIG_SSB_DRIVER_GIGE) += driver_gige.o
14 15
15# b43 pci-ssb-bridge driver 16# b43 pci-ssb-bridge driver
16# Not strictly a part of SSB, but kept here for convenience 17# Not strictly a part of SSB, but kept here for convenience
diff --git a/drivers/ssb/driver_gige.c b/drivers/ssb/driver_gige.c
new file mode 100644
index 00000000000..172f90407b9
--- /dev/null
+++ b/drivers/ssb/driver_gige.c
@@ -0,0 +1,294 @@
1/*
2 * Sonics Silicon Backplane
3 * Broadcom Gigabit Ethernet core driver
4 *
5 * Copyright 2008, Broadcom Corporation
6 * Copyright 2008, Michael Buesch <mb@bu3sch.de>
7 *
8 * Licensed under the GNU/GPL. See COPYING for details.
9 */
10
11#include <linux/ssb/ssb.h>
12#include <linux/ssb/ssb_driver_gige.h>
13#include <linux/pci.h>
14#include <linux/pci_regs.h>
15
16
17/*
18MODULE_DESCRIPTION("SSB Broadcom Gigabit Ethernet driver");
19MODULE_AUTHOR("Michael Buesch");
20MODULE_LICENSE("GPL");
21*/
22
23static const struct ssb_device_id ssb_gige_tbl[] = {
24 SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_ETHERNET_GBIT, SSB_ANY_REV),
25 SSB_DEVTABLE_END
26};
27/* MODULE_DEVICE_TABLE(ssb, ssb_gige_tbl); */
28
29
30static inline u8 gige_read8(struct ssb_gige *dev, u16 offset)
31{
32 return ssb_read8(dev->dev, offset);
33}
34
35static inline u16 gige_read16(struct ssb_gige *dev, u16 offset)
36{
37 return ssb_read16(dev->dev, offset);
38}
39
40static inline u32 gige_read32(struct ssb_gige *dev, u16 offset)
41{
42 return ssb_read32(dev->dev, offset);
43}
44
45static inline void gige_write8(struct ssb_gige *dev,
46 u16 offset, u8 value)
47{
48 ssb_write8(dev->dev, offset, value);
49}
50
51static inline void gige_write16(struct ssb_gige *dev,
52 u16 offset, u16 value)
53{
54 ssb_write16(dev->dev, offset, value);
55}
56
57static inline void gige_write32(struct ssb_gige *dev,
58 u16 offset, u32 value)
59{
60 ssb_write32(dev->dev, offset, value);
61}
62
63static inline
64u8 gige_pcicfg_read8(struct ssb_gige *dev, unsigned int offset)
65{
66 BUG_ON(offset >= 256);
67 return gige_read8(dev, SSB_GIGE_PCICFG + offset);
68}
69
70static inline
71u16 gige_pcicfg_read16(struct ssb_gige *dev, unsigned int offset)
72{
73 BUG_ON(offset >= 256);
74 return gige_read16(dev, SSB_GIGE_PCICFG + offset);
75}
76
77static inline
78u32 gige_pcicfg_read32(struct ssb_gige *dev, unsigned int offset)
79{
80 BUG_ON(offset >= 256);
81 return gige_read32(dev, SSB_GIGE_PCICFG + offset);
82}
83
84static inline
85void gige_pcicfg_write8(struct ssb_gige *dev,
86 unsigned int offset, u8 value)
87{
88 BUG_ON(offset >= 256);
89 gige_write8(dev, SSB_GIGE_PCICFG + offset, value);
90}
91
92static inline
93void gige_pcicfg_write16(struct ssb_gige *dev,
94 unsigned int offset, u16 value)
95{
96 BUG_ON(offset >= 256);
97 gige_write16(dev, SSB_GIGE_PCICFG + offset, value);
98}
99
100static inline
101void gige_pcicfg_write32(struct ssb_gige *dev,
102 unsigned int offset, u32 value)
103{
104 BUG_ON(offset >= 256);
105 gige_write32(dev, SSB_GIGE_PCICFG + offset, value);
106}
107
108static int ssb_gige_pci_read_config(struct pci_bus *bus, unsigned int devfn,
109 int reg, int size, u32 *val)
110{
111 struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
112 unsigned long flags;
113
114 if ((PCI_SLOT(devfn) > 0) || (PCI_FUNC(devfn) > 0))
115 return PCIBIOS_DEVICE_NOT_FOUND;
116 if (reg >= 256)
117 return PCIBIOS_DEVICE_NOT_FOUND;
118
119 spin_lock_irqsave(&dev->lock, flags);
120 switch (size) {
121 case 1:
122 *val = gige_pcicfg_read8(dev, reg);
123 break;
124 case 2:
125 *val = gige_pcicfg_read16(dev, reg);
126 break;
127 case 4:
128 *val = gige_pcicfg_read32(dev, reg);
129 break;
130 default:
131 WARN_ON(1);
132 }
133 spin_unlock_irqrestore(&dev->lock, flags);
134
135 return PCIBIOS_SUCCESSFUL;
136}
137
138static int ssb_gige_pci_write_config(struct pci_bus *bus, unsigned int devfn,
139 int reg, int size, u32 val)
140{
141 struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
142 unsigned long flags;
143
144 if ((PCI_SLOT(devfn) > 0) || (PCI_FUNC(devfn) > 0))
145 return PCIBIOS_DEVICE_NOT_FOUND;
146 if (reg >= 256)
147 return PCIBIOS_DEVICE_NOT_FOUND;
148
149 spin_lock_irqsave(&dev->lock, flags);
150 switch (size) {
151 case 1:
152 gige_pcicfg_write8(dev, reg, val);
153 break;
154 case 2:
155 gige_pcicfg_write16(dev, reg, val);
156 break;
157 case 4:
158 gige_pcicfg_write32(dev, reg, val);
159 break;
160 default:
161 WARN_ON(1);
162 }
163 spin_unlock_irqrestore(&dev->lock, flags);
164
165 return PCIBIOS_SUCCESSFUL;
166}
167
168static int ssb_gige_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
169{
170 struct ssb_gige *dev;
171 u32 base, tmslow, tmshigh;
172
173 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
174 if (!dev)
175 return -ENOMEM;
176 dev->dev = sdev;
177
178 spin_lock_init(&dev->lock);
179 dev->pci_controller.pci_ops = &dev->pci_ops;
180 dev->pci_controller.io_resource = &dev->io_resource;
181 dev->pci_controller.mem_resource = &dev->mem_resource;
182 dev->pci_controller.io_map_base = 0x800;
183 dev->pci_ops.read = ssb_gige_pci_read_config;
184 dev->pci_ops.write = ssb_gige_pci_write_config;
185
186 dev->io_resource.name = SSB_GIGE_IO_RES_NAME;
187 dev->io_resource.start = 0x800;
188 dev->io_resource.end = 0x8FF;
189 dev->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED;
190
191 if (!ssb_device_is_enabled(sdev))
192 ssb_device_enable(sdev, 0);
193
194 /* Setup BAR0. This is a 64k MMIO region. */
195 base = ssb_admatch_base(ssb_read32(sdev, SSB_ADMATCH1));
196 gige_pcicfg_write32(dev, PCI_BASE_ADDRESS_0, base);
197 gige_pcicfg_write32(dev, PCI_BASE_ADDRESS_1, 0);
198
199 dev->mem_resource.name = SSB_GIGE_MEM_RES_NAME;
200 dev->mem_resource.start = base;
201 dev->mem_resource.end = base + 0x10000 - 1;
202 dev->mem_resource.flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED;
203
204 /* Enable the memory region. */
205 gige_pcicfg_write16(dev, PCI_COMMAND,
206 gige_pcicfg_read16(dev, PCI_COMMAND)
207 | PCI_COMMAND_MEMORY);
208
209 /* Write flushing is controlled by the Flush Status Control register.
210 * We want to flush every register write with a timeout and we want
211 * to disable the IRQ mask while flushing to avoid concurrency.
212 * Note that automatic write flushing does _not_ work from
213 * an IRQ handler. The driver must flush manually by reading a register.
214 */
215 gige_write32(dev, SSB_GIGE_SHIM_FLUSHSTAT, 0x00000068);
216
217 /* Check if we have an RGMII or GMII PHY-bus.
218 * On RGMII do not bypass the DLLs */
219 tmslow = ssb_read32(sdev, SSB_TMSLOW);
220 tmshigh = ssb_read32(sdev, SSB_TMSHIGH);
221 if (tmshigh & SSB_GIGE_TMSHIGH_RGMII) {
222 tmslow &= ~SSB_GIGE_TMSLOW_TXBYPASS;
223 tmslow &= ~SSB_GIGE_TMSLOW_RXBYPASS;
224 dev->has_rgmii = 1;
225 } else {
226 tmslow |= SSB_GIGE_TMSLOW_TXBYPASS;
227 tmslow |= SSB_GIGE_TMSLOW_RXBYPASS;
228 dev->has_rgmii = 0;
229 }
230 tmslow |= SSB_GIGE_TMSLOW_DLLEN;
231 ssb_write32(sdev, SSB_TMSLOW, tmslow);
232
233 ssb_set_drvdata(sdev, dev);
234 register_pci_controller(&dev->pci_controller);
235
236 return 0;
237}
238
239bool pdev_is_ssb_gige_core(struct pci_dev *pdev)
240{
241 if (!pdev->resource[0].name)
242 return 0;
243 return (strcmp(pdev->resource[0].name, SSB_GIGE_MEM_RES_NAME) == 0);
244}
245EXPORT_SYMBOL(pdev_is_ssb_gige_core);
246
247int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
248 struct pci_dev *pdev)
249{
250 struct ssb_gige *dev = ssb_get_drvdata(sdev);
251 struct resource *res;
252
253 if (pdev->bus->ops != &dev->pci_ops) {
254 /* The PCI device is not on this SSB GigE bridge device. */
255 return -ENODEV;
256 }
257
258 /* Fixup the PCI resources. */
259 res = &(pdev->resource[0]);
260 res->flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED;
261 res->name = dev->mem_resource.name;
262 res->start = dev->mem_resource.start;
263 res->end = dev->mem_resource.end;
264
265 /* Fixup interrupt lines. */
266 pdev->irq = ssb_mips_irq(sdev) + 2;
267 pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, pdev->irq);
268
269 return 0;
270}
271
272int ssb_gige_map_irq(struct ssb_device *sdev,
273 const struct pci_dev *pdev)
274{
275 struct ssb_gige *dev = ssb_get_drvdata(sdev);
276
277 if (pdev->bus->ops != &dev->pci_ops) {
278 /* The PCI device is not on this SSB GigE bridge device. */
279 return -ENODEV;
280 }
281
282 return ssb_mips_irq(sdev) + 2;
283}
284
285static struct ssb_driver ssb_gige_driver = {
286 .name = "BCM-GigE",
287 .id_table = ssb_gige_tbl,
288 .probe = ssb_gige_probe,
289};
290
291int ssb_gige_init(void)
292{
293 return ssb_driver_register(&ssb_gige_driver);
294}
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c
index 3d3dd32bf3a..e3fad3123ec 100644
--- a/drivers/ssb/driver_mipscore.c
+++ b/drivers/ssb/driver_mipscore.c
@@ -209,6 +209,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
209 /* fallthrough */ 209 /* fallthrough */
210 case SSB_DEV_PCI: 210 case SSB_DEV_PCI:
211 case SSB_DEV_ETHERNET: 211 case SSB_DEV_ETHERNET:
212 case SSB_DEV_ETHERNET_GBIT:
212 case SSB_DEV_80211: 213 case SSB_DEV_80211:
213 case SSB_DEV_USB20_HOST: 214 case SSB_DEV_USB20_HOST:
214 /* These devices get their own IRQ line if available, the rest goes on IRQ0 */ 215 /* These devices get their own IRQ line if available, the rest goes on IRQ0 */
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c
index 74b9a8aea52..33a7d562047 100644
--- a/drivers/ssb/driver_pcicore.c
+++ b/drivers/ssb/driver_pcicore.c
@@ -60,77 +60,6 @@ static DEFINE_SPINLOCK(cfgspace_lock);
60/* Core to access the external PCI config space. Can only have one. */ 60/* Core to access the external PCI config space. Can only have one. */
61static struct ssb_pcicore *extpci_core; 61static struct ssb_pcicore *extpci_core;
62 62
63static u32 ssb_pcicore_pcibus_iobase = 0x100;
64static u32 ssb_pcicore_pcibus_membase = SSB_PCI_DMA;
65
66int pcibios_plat_dev_init(struct pci_dev *d)
67{
68 struct resource *res;
69 int pos, size;
70 u32 *base;
71
72 ssb_printk(KERN_INFO "PCI: Fixing up device %s\n",
73 pci_name(d));
74
75 /* Fix up resource bases */
76 for (pos = 0; pos < 6; pos++) {
77 res = &d->resource[pos];
78 if (res->flags & IORESOURCE_IO)
79 base = &ssb_pcicore_pcibus_iobase;
80 else
81 base = &ssb_pcicore_pcibus_membase;
82 res->flags |= IORESOURCE_PCI_FIXED;
83 if (res->end) {
84 size = res->end - res->start + 1;
85 if (*base & (size - 1))
86 *base = (*base + size) & ~(size - 1);
87 res->start = *base;
88 res->end = res->start + size - 1;
89 *base += size;
90 pci_write_config_dword(d, PCI_BASE_ADDRESS_0 + (pos << 2), res->start);
91 }
92 /* Fix up PCI bridge BAR0 only */
93 if (d->bus->number == 0 && PCI_SLOT(d->devfn) == 0)
94 break;
95 }
96 /* Fix up interrupt lines */
97 d->irq = ssb_mips_irq(extpci_core->dev) + 2;
98 pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq);
99
100 return 0;
101}
102
103static void __init ssb_fixup_pcibridge(struct pci_dev *dev)
104{
105 u8 lat;
106
107 if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0)
108 return;
109
110 ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev));
111
112 /* Enable PCI bridge bus mastering and memory space */
113 pci_set_master(dev);
114 if (pcibios_enable_device(dev, ~0) < 0) {
115 ssb_printk(KERN_ERR "PCI: SSB bridge enable failed\n");
116 return;
117 }
118
119 /* Enable PCI bridge BAR1 prefetch and burst */
120 pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3);
121
122 /* Make sure our latency is high enough to handle the devices behind us */
123 lat = 168;
124 ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n",
125 pci_name(dev), lat);
126 pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
127}
128DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_fixup_pcibridge);
129
130int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
131{
132 return ssb_mips_irq(extpci_core->dev) + 2;
133}
134 63
135static u32 get_cfgspace_addr(struct ssb_pcicore *pc, 64static u32 get_cfgspace_addr(struct ssb_pcicore *pc,
136 unsigned int bus, unsigned int dev, 65 unsigned int bus, unsigned int dev,
@@ -320,6 +249,95 @@ static struct pci_controller ssb_pcicore_controller = {
320 .mem_offset = 0x24000000, 249 .mem_offset = 0x24000000,
321}; 250};
322 251
252static u32 ssb_pcicore_pcibus_iobase = 0x100;
253static u32 ssb_pcicore_pcibus_membase = SSB_PCI_DMA;
254
255/* This function is called when doing a pci_enable_device().
256 * We must first check if the device is a device on the PCI-core bridge. */
257int ssb_pcicore_plat_dev_init(struct pci_dev *d)
258{
259 struct resource *res;
260 int pos, size;
261 u32 *base;
262
263 if (d->bus->ops != &ssb_pcicore_pciops) {
264 /* This is not a device on the PCI-core bridge. */
265 return -ENODEV;
266 }
267
268 ssb_printk(KERN_INFO "PCI: Fixing up device %s\n",
269 pci_name(d));
270
271 /* Fix up resource bases */
272 for (pos = 0; pos < 6; pos++) {
273 res = &d->resource[pos];
274 if (res->flags & IORESOURCE_IO)
275 base = &ssb_pcicore_pcibus_iobase;
276 else
277 base = &ssb_pcicore_pcibus_membase;
278 res->flags |= IORESOURCE_PCI_FIXED;
279 if (res->end) {
280 size = res->end - res->start + 1;
281 if (*base & (size - 1))
282 *base = (*base + size) & ~(size - 1);
283 res->start = *base;
284 res->end = res->start + size - 1;
285 *base += size;
286 pci_write_config_dword(d, PCI_BASE_ADDRESS_0 + (pos << 2), res->start);
287 }
288 /* Fix up PCI bridge BAR0 only */
289 if (d->bus->number == 0 && PCI_SLOT(d->devfn) == 0)
290 break;
291 }
292 /* Fix up interrupt lines */
293 d->irq = ssb_mips_irq(extpci_core->dev) + 2;
294 pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq);
295
296 return 0;
297}
298
299/* Early PCI fixup for a device on the PCI-core bridge. */
300static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev)
301{
302 u8 lat;
303
304 if (dev->bus->ops != &ssb_pcicore_pciops) {
305 /* This is not a device on the PCI-core bridge. */
306 return;
307 }
308 if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0)
309 return;
310
311 ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev));
312
313 /* Enable PCI bridge bus mastering and memory space */
314 pci_set_master(dev);
315 if (pcibios_enable_device(dev, ~0) < 0) {
316 ssb_printk(KERN_ERR "PCI: SSB bridge enable failed\n");
317 return;
318 }
319
320 /* Enable PCI bridge BAR1 prefetch and burst */
321 pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3);
322
323 /* Make sure our latency is high enough to handle the devices behind us */
324 lat = 168;
325 ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n",
326 pci_name(dev), lat);
327 pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
328}
329DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_pcicore_fixup_pcibridge);
330
331/* PCI device IRQ mapping. */
332int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
333{
334 if (dev->bus->ops != &ssb_pcicore_pciops) {
335 /* This is not a device on the PCI-core bridge. */
336 return -ENODEV;
337 }
338 return ssb_mips_irq(extpci_core->dev) + 2;
339}
340
323static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) 341static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
324{ 342{
325 u32 val; 343 u32 val;
diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c
index d3ade821555..7dc3a6b4139 100644
--- a/drivers/ssb/embedded.c
+++ b/drivers/ssb/embedded.c
@@ -10,6 +10,9 @@
10 10
11#include <linux/ssb/ssb.h> 11#include <linux/ssb/ssb.h>
12#include <linux/ssb/ssb_embedded.h> 12#include <linux/ssb/ssb_embedded.h>
13#include <linux/ssb/ssb_driver_pci.h>
14#include <linux/ssb/ssb_driver_gige.h>
15#include <linux/pci.h>
13 16
14#include "ssb_private.h" 17#include "ssb_private.h"
15 18
@@ -130,3 +133,90 @@ u32 ssb_gpio_polarity(struct ssb_bus *bus, u32 mask, u32 value)
130 return res; 133 return res;
131} 134}
132EXPORT_SYMBOL(ssb_gpio_polarity); 135EXPORT_SYMBOL(ssb_gpio_polarity);
136
137#ifdef CONFIG_SSB_DRIVER_GIGE
138static int gige_pci_init_callback(struct ssb_bus *bus, unsigned long data)
139{
140 struct pci_dev *pdev = (struct pci_dev *)data;
141 struct ssb_device *dev;
142 unsigned int i;
143 int res;
144
145 for (i = 0; i < bus->nr_devices; i++) {
146 dev = &(bus->devices[i]);
147 if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
148 continue;
149 if (!dev->dev ||
150 !dev->dev->driver ||
151 !device_is_registered(dev->dev))
152 continue;
153 res = ssb_gige_pcibios_plat_dev_init(dev, pdev);
154 if (res >= 0)
155 return res;
156 }
157
158 return -ENODEV;
159}
160#endif /* CONFIG_SSB_DRIVER_GIGE */
161
162int ssb_pcibios_plat_dev_init(struct pci_dev *dev)
163{
164 int err;
165
166 err = ssb_pcicore_plat_dev_init(dev);
167 if (!err)
168 return 0;
169#ifdef CONFIG_SSB_DRIVER_GIGE
170 err = ssb_for_each_bus_call((unsigned long)dev, gige_pci_init_callback);
171 if (err >= 0)
172 return err;
173#endif
174 /* This is not a PCI device on any SSB device. */
175
176 return -ENODEV;
177}
178
179#ifdef CONFIG_SSB_DRIVER_GIGE
180static int gige_map_irq_callback(struct ssb_bus *bus, unsigned long data)
181{
182 const struct pci_dev *pdev = (const struct pci_dev *)data;
183 struct ssb_device *dev;
184 unsigned int i;
185 int res;
186
187 for (i = 0; i < bus->nr_devices; i++) {
188 dev = &(bus->devices[i]);
189 if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
190 continue;
191 if (!dev->dev ||
192 !dev->dev->driver ||
193 !device_is_registered(dev->dev))
194 continue;
195 res = ssb_gige_map_irq(dev, pdev);
196 if (res >= 0)
197 return res;
198 }
199
200 return -ENODEV;
201}
202#endif /* CONFIG_SSB_DRIVER_GIGE */
203
204int ssb_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
205{
206 int res;
207
208 /* Check if this PCI device is a device on a SSB bus or device
209 * and return the IRQ number for it. */
210
211 res = ssb_pcicore_pcibios_map_irq(dev, slot, pin);
212 if (res >= 0)
213 return res;
214#ifdef CONFIG_SSB_DRIVER_GIGE
215 res = ssb_for_each_bus_call((unsigned long)dev, gige_map_irq_callback);
216 if (res >= 0)
217 return res;
218#endif
219 /* This is not a PCI device on any SSB device. */
220
221 return -ENODEV;
222}
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index 8db40c4b86e..49d7bbb9bea 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -14,6 +14,7 @@
14#include <linux/io.h> 14#include <linux/io.h>
15#include <linux/ssb/ssb.h> 15#include <linux/ssb/ssb.h>
16#include <linux/ssb/ssb_regs.h> 16#include <linux/ssb/ssb_regs.h>
17#include <linux/ssb/ssb_driver_gige.h>
17#include <linux/dma-mapping.h> 18#include <linux/dma-mapping.h>
18#include <linux/pci.h> 19#include <linux/pci.h>
19 20
@@ -68,6 +69,25 @@ found:
68} 69}
69#endif /* CONFIG_SSB_PCIHOST */ 70#endif /* CONFIG_SSB_PCIHOST */
70 71
72int ssb_for_each_bus_call(unsigned long data,
73 int (*func)(struct ssb_bus *bus, unsigned long data))
74{
75 struct ssb_bus *bus;
76 int res;
77
78 ssb_buses_lock();
79 list_for_each_entry(bus, &buses, list) {
80 res = func(bus, data);
81 if (res >= 0) {
82 ssb_buses_unlock();
83 return res;
84 }
85 }
86 ssb_buses_unlock();
87
88 return -ENODEV;
89}
90
71static struct ssb_device *ssb_device_get(struct ssb_device *dev) 91static struct ssb_device *ssb_device_get(struct ssb_device *dev)
72{ 92{
73 if (dev) 93 if (dev)
@@ -1171,7 +1191,14 @@ static int __init ssb_modinit(void)
1171 err = b43_pci_ssb_bridge_init(); 1191 err = b43_pci_ssb_bridge_init();
1172 if (err) { 1192 if (err) {
1173 ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge " 1193 ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge "
1174 "initialization failed"); 1194 "initialization failed\n");
1195 /* don't fail SSB init because of this */
1196 err = 0;
1197 }
1198 err = ssb_gige_init();
1199 if (err) {
1200 ssb_printk(KERN_ERR "SSB Broadcom Gigabit Ethernet "
1201 "driver initialization failed\n");
1175 /* don't fail SSB init because of this */ 1202 /* don't fail SSB init because of this */
1176 err = 0; 1203 err = 0;
1177 } 1204 }
@@ -1185,6 +1212,7 @@ fs_initcall(ssb_modinit);
1185 1212
1186static void __exit ssb_modexit(void) 1213static void __exit ssb_modexit(void)
1187{ 1214{
1215 ssb_gige_exit();
1188 b43_pci_ssb_bridge_exit(); 1216 b43_pci_ssb_bridge_exit();
1189 bus_unregister(&ssb_bustype); 1217 bus_unregister(&ssb_bustype);
1190} 1218}
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h
index 21eca2b5118..d03b20983b1 100644
--- a/drivers/ssb/ssb_private.h
+++ b/drivers/ssb/ssb_private.h
@@ -118,6 +118,8 @@ extern u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m);
118extern int ssb_devices_freeze(struct ssb_bus *bus); 118extern int ssb_devices_freeze(struct ssb_bus *bus);
119extern int ssb_devices_thaw(struct ssb_bus *bus); 119extern int ssb_devices_thaw(struct ssb_bus *bus);
120extern struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev); 120extern struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev);
121int ssb_for_each_bus_call(unsigned long data,
122 int (*func)(struct ssb_bus *bus, unsigned long data));
121 123
122/* b43_pci_bridge.c */ 124/* b43_pci_bridge.c */
123#ifdef CONFIG_SSB_B43_PCI_BRIDGE 125#ifdef CONFIG_SSB_B43_PCI_BRIDGE
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index 860d28c6d14..b7c388972fc 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -422,5 +422,12 @@ extern int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl);
422extern u32 ssb_admatch_base(u32 adm); 422extern u32 ssb_admatch_base(u32 adm);
423extern u32 ssb_admatch_size(u32 adm); 423extern u32 ssb_admatch_size(u32 adm);
424 424
425/* PCI device mapping and fixup routines.
426 * Called from the architecture pcibios init code.
427 * These are only available on SSB_EMBEDDED configurations. */
428#ifdef CONFIG_SSB_EMBEDDED
429int ssb_pcibios_plat_dev_init(struct pci_dev *dev);
430int ssb_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
431#endif /* CONFIG_SSB_EMBEDDED */
425 432
426#endif /* LINUX_SSB_H_ */ 433#endif /* LINUX_SSB_H_ */
diff --git a/include/linux/ssb/ssb_driver_gige.h b/include/linux/ssb/ssb_driver_gige.h
new file mode 100644
index 00000000000..01fbdf5fef2
--- /dev/null
+++ b/include/linux/ssb/ssb_driver_gige.h
@@ -0,0 +1,174 @@
1#ifndef LINUX_SSB_DRIVER_GIGE_H_
2#define LINUX_SSB_DRIVER_GIGE_H_
3
4#include <linux/ssb/ssb.h>
5#include <linux/pci.h>
6#include <linux/spinlock.h>
7
8
9#ifdef CONFIG_SSB_DRIVER_GIGE
10
11
12#define SSB_GIGE_PCIIO 0x0000 /* PCI I/O Registers (1024 bytes) */
13#define SSB_GIGE_RESERVED 0x0400 /* Reserved (1024 bytes) */
14#define SSB_GIGE_PCICFG 0x0800 /* PCI config space (256 bytes) */
15#define SSB_GIGE_SHIM_FLUSHSTAT 0x0C00 /* PCI to OCP: Flush status control (32bit) */
16#define SSB_GIGE_SHIM_FLUSHRDA 0x0C04 /* PCI to OCP: Flush read address (32bit) */
17#define SSB_GIGE_SHIM_FLUSHTO 0x0C08 /* PCI to OCP: Flush timeout counter (32bit) */
18#define SSB_GIGE_SHIM_BARRIER 0x0C0C /* PCI to OCP: Barrier register (32bit) */
19#define SSB_GIGE_SHIM_MAOCPSI 0x0C10 /* PCI to OCP: MaocpSI Control (32bit) */
20#define SSB_GIGE_SHIM_SIOCPMA 0x0C14 /* PCI to OCP: SiocpMa Control (32bit) */
21
22/* TM Status High flags */
23#define SSB_GIGE_TMSHIGH_RGMII 0x00010000 /* Have an RGMII PHY-bus */
24/* TM Status Low flags */
25#define SSB_GIGE_TMSLOW_TXBYPASS 0x00080000 /* TX bypass (no delay) */
26#define SSB_GIGE_TMSLOW_RXBYPASS 0x00100000 /* RX bypass (no delay) */
27#define SSB_GIGE_TMSLOW_DLLEN 0x01000000 /* Enable DLL controls */
28
29/* Boardflags (low) */
30#define SSB_GIGE_BFL_ROBOSWITCH 0x0010
31
32
33#define SSB_GIGE_MEM_RES_NAME "SSB Broadcom 47xx GigE memory"
34#define SSB_GIGE_IO_RES_NAME "SSB Broadcom 47xx GigE I/O"
35
36struct ssb_gige {
37 struct ssb_device *dev;
38
39 spinlock_t lock;
40
41 /* True, if the device has an RGMII bus.
42 * False, if the device has a GMII bus. */
43 bool has_rgmii;
44
45 /* The PCI controller device. */
46 struct pci_controller pci_controller;
47 struct pci_ops pci_ops;
48 struct resource mem_resource;
49 struct resource io_resource;
50};
51
52/* Check whether a PCI device is a SSB Gigabit Ethernet core. */
53extern bool pdev_is_ssb_gige_core(struct pci_dev *pdev);
54
55/* Convert a pci_dev pointer to a ssb_gige pointer. */
56static inline struct ssb_gige * pdev_to_ssb_gige(struct pci_dev *pdev)
57{
58 if (!pdev_is_ssb_gige_core(pdev))
59 return NULL;
60 return container_of(pdev->bus->ops, struct ssb_gige, pci_ops);
61}
62
63/* Returns whether the PHY is connected by an RGMII bus. */
64static inline bool ssb_gige_is_rgmii(struct pci_dev *pdev)
65{
66 struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
67 return (dev ? dev->has_rgmii : 0);
68}
69
70/* Returns whether we have a Roboswitch. */
71static inline bool ssb_gige_have_roboswitch(struct pci_dev *pdev)
72{
73 struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
74 if (dev)
75 return !!(dev->dev->bus->sprom.boardflags_lo &
76 SSB_GIGE_BFL_ROBOSWITCH);
77 return 0;
78}
79
80/* Returns whether we can only do one DMA at once. */
81static inline bool ssb_gige_one_dma_at_once(struct pci_dev *pdev)
82{
83 struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
84 if (dev)
85 return ((dev->dev->bus->chip_id == 0x4785) &&
86 (dev->dev->bus->chip_rev < 2));
87 return 0;
88}
89
90/* Returns whether we must flush posted writes. */
91static inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev)
92{
93 struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
94 if (dev)
95 return (dev->dev->bus->chip_id == 0x4785);
96 return 0;
97}
98
99extern char * nvram_get(const char *name);
100/* Get the device MAC address */
101static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
102{
103#ifdef CONFIG_BCM947XX
104 char *res = nvram_get("et0macaddr");
105 if (res)
106 memcpy(macaddr, res, 6);
107#endif
108}
109
110extern int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
111 struct pci_dev *pdev);
112extern int ssb_gige_map_irq(struct ssb_device *sdev,
113 const struct pci_dev *pdev);
114
115/* The GigE driver is not a standalone module, because we don't have support
116 * for unregistering the driver. So we could not unload the module anyway. */
117extern int ssb_gige_init(void);
118static inline void ssb_gige_exit(void)
119{
120 /* Currently we can not unregister the GigE driver,
121 * because we can not unregister the PCI bridge. */
122 BUG();
123}
124
125
126#else /* CONFIG_SSB_DRIVER_GIGE */
127/* Gigabit Ethernet driver disabled */
128
129
130static inline int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
131 struct pci_dev *pdev)
132{
133 return -ENOSYS;
134}
135static inline int ssb_gige_map_irq(struct ssb_device *sdev,
136 const struct pci_dev *pdev)
137{
138 return -ENOSYS;
139}
140static inline int ssb_gige_init(void)
141{
142 return 0;
143}
144static inline void ssb_gige_exit(void)
145{
146}
147
148static inline bool pdev_is_ssb_gige_core(struct pci_dev *pdev)
149{
150 return 0;
151}
152static inline struct ssb_gige * pdev_to_ssb_gige(struct pci_dev *pdev)
153{
154 return NULL;
155}
156static inline bool ssb_gige_is_rgmii(struct pci_dev *pdev)
157{
158 return 0;
159}
160static inline bool ssb_gige_have_roboswitch(struct pci_dev *pdev)
161{
162 return 0;
163}
164static inline bool ssb_gige_one_dma_at_once(struct pci_dev *pdev)
165{
166 return 0;
167}
168static inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev)
169{
170 return 0;
171}
172
173#endif /* CONFIG_SSB_DRIVER_GIGE */
174#endif /* LINUX_SSB_DRIVER_GIGE_H_ */
diff --git a/include/linux/ssb/ssb_driver_pci.h b/include/linux/ssb/ssb_driver_pci.h
index 5e25bac4ed3..41e330e51c2 100644
--- a/include/linux/ssb/ssb_driver_pci.h
+++ b/include/linux/ssb/ssb_driver_pci.h
@@ -1,6 +1,11 @@
1#ifndef LINUX_SSB_PCICORE_H_ 1#ifndef LINUX_SSB_PCICORE_H_
2#define LINUX_SSB_PCICORE_H_ 2#define LINUX_SSB_PCICORE_H_
3 3
4#include <linux/types.h>
5
6struct pci_dev;
7
8
4#ifdef CONFIG_SSB_DRIVER_PCICORE 9#ifdef CONFIG_SSB_DRIVER_PCICORE
5 10
6/* PCI core registers. */ 11/* PCI core registers. */
@@ -88,6 +93,9 @@ extern void ssb_pcicore_init(struct ssb_pcicore *pc);
88extern int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, 93extern int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
89 struct ssb_device *dev); 94 struct ssb_device *dev);
90 95
96int ssb_pcicore_plat_dev_init(struct pci_dev *d);
97int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
98
91 99
92#else /* CONFIG_SSB_DRIVER_PCICORE */ 100#else /* CONFIG_SSB_DRIVER_PCICORE */
93 101
@@ -107,5 +115,16 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
107 return 0; 115 return 0;
108} 116}
109 117
118static inline
119int ssb_pcicore_plat_dev_init(struct pci_dev *d)
120{
121 return -ENODEV;
122}
123static inline
124int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
125{
126 return -ENODEV;
127}
128
110#endif /* CONFIG_SSB_DRIVER_PCICORE */ 129#endif /* CONFIG_SSB_DRIVER_PCICORE */
111#endif /* LINUX_SSB_PCICORE_H_ */ 130#endif /* LINUX_SSB_PCICORE_H_ */