aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ssb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ssb')
-rw-r--r--drivers/ssb/Kconfig20
-rw-r--r--drivers/ssb/Makefile2
-rw-r--r--drivers/ssb/driver_chipcommon.c12
-rw-r--r--drivers/ssb/driver_gige.c294
-rw-r--r--drivers/ssb/driver_mipscore.c1
-rw-r--r--drivers/ssb/driver_pcicore.c172
-rw-r--r--drivers/ssb/embedded.c90
-rw-r--r--drivers/ssb/main.c260
-rw-r--r--drivers/ssb/pci.c211
-rw-r--r--drivers/ssb/pcihost_wrapper.c10
-rw-r--r--drivers/ssb/pcmcia.c699
-rw-r--r--drivers/ssb/sprom.c133
-rw-r--r--drivers/ssb/ssb_private.h24
13 files changed, 1627 insertions, 301 deletions
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig
index adea792fb675..cd845b8acd17 100644
--- a/drivers/ssb/Kconfig
+++ b/drivers/ssb/Kconfig
@@ -20,6 +20,15 @@ config SSB
20 20
21 If unsure, say N. 21 If unsure, say N.
22 22
23# Common SPROM support routines
24config SSB_SPROM
25 bool
26
27# Support for Block-I/O. SELECT this from the driver that needs it.
28config SSB_BLOCKIO
29 bool
30 depends on SSB
31
23config SSB_PCIHOST_POSSIBLE 32config SSB_PCIHOST_POSSIBLE
24 bool 33 bool
25 depends on SSB && (PCI = y || PCI = SSB) 34 depends on SSB && (PCI = y || PCI = SSB)
@@ -28,6 +37,7 @@ config SSB_PCIHOST_POSSIBLE
28config SSB_PCIHOST 37config SSB_PCIHOST
29 bool "Support for SSB on PCI-bus host" 38 bool "Support for SSB on PCI-bus host"
30 depends on SSB_PCIHOST_POSSIBLE 39 depends on SSB_PCIHOST_POSSIBLE
40 select SSB_SPROM
31 default y 41 default y
32 help 42 help
33 Support for a Sonics Silicon Backplane on top 43 Support for a Sonics Silicon Backplane on top
@@ -48,6 +58,7 @@ config SSB_PCMCIAHOST_POSSIBLE
48config SSB_PCMCIAHOST 58config SSB_PCMCIAHOST
49 bool "Support for SSB on PCMCIA-bus host (EXPERIMENTAL)" 59 bool "Support for SSB on PCMCIA-bus host (EXPERIMENTAL)"
50 depends on SSB_PCMCIAHOST_POSSIBLE 60 depends on SSB_PCMCIAHOST_POSSIBLE
61 select SSB_SPROM
51 help 62 help
52 Support for a Sonics Silicon Backplane on top 63 Support for a Sonics Silicon Backplane on top
53 of a PCMCIA device. 64 of a PCMCIA device.
@@ -125,4 +136,13 @@ config SSB_DRIVER_EXTIF
125 136
126 If unsure, say N 137 If unsure, say N
127 138
139config SSB_DRIVER_GIGE
140 bool "SSB Broadcom Gigabit Ethernet driver"
141 depends on SSB_PCIHOST_POSSIBLE && SSB_EMBEDDED && MIPS
142 help
143 Driver for the Sonics Silicon Backplane attached
144 Broadcom Gigabit Ethernet.
145
146 If unsure, say N
147
128endmenu 148endmenu
diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile
index de94c2eb7a37..6f255e9c5af9 100644
--- a/drivers/ssb/Makefile
+++ b/drivers/ssb/Makefile
@@ -1,6 +1,7 @@
1# core 1# core
2ssb-y += main.o scan.o 2ssb-y += main.o scan.o
3ssb-$(CONFIG_SSB_EMBEDDED) += embedded.o 3ssb-$(CONFIG_SSB_EMBEDDED) += embedded.o
4ssb-$(CONFIG_SSB_SPROM) += sprom.o
4 5
5# host support 6# host support
6ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o 7ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o
@@ -11,6 +12,7 @@ ssb-y += driver_chipcommon.o
11ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o 12ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o
12ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o 13ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o
13ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o 14ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o
15ssb-$(CONFIG_SSB_DRIVER_GIGE) += driver_gige.o
14 16
15# b43 pci-ssb-bridge driver 17# b43 pci-ssb-bridge driver
16# Not strictly a part of SSB, but kept here for convenience 18# Not strictly a part of SSB, but kept here for convenience
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c
index e586321a473a..571f4fd55236 100644
--- a/drivers/ssb/driver_chipcommon.c
+++ b/drivers/ssb/driver_chipcommon.c
@@ -251,7 +251,7 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc)
251 calc_fast_powerup_delay(cc); 251 calc_fast_powerup_delay(cc);
252} 252}
253 253
254void ssb_chipco_suspend(struct ssb_chipcommon *cc, pm_message_t state) 254void ssb_chipco_suspend(struct ssb_chipcommon *cc)
255{ 255{
256 if (!cc->dev) 256 if (!cc->dev)
257 return; 257 return;
@@ -353,6 +353,16 @@ void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks)
353 chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks); 353 chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks);
354} 354}
355 355
356void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value)
357{
358 chipco_write32_masked(cc, SSB_CHIPCO_IRQMASK, mask, value);
359}
360
361u32 ssb_chipco_irq_status(struct ssb_chipcommon *cc, u32 mask)
362{
363 return chipco_read32(cc, SSB_CHIPCO_IRQSTAT) & mask;
364}
365
356u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask) 366u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask)
357{ 367{
358 return chipco_read32(cc, SSB_CHIPCO_GPIOIN) & mask; 368 return chipco_read32(cc, SSB_CHIPCO_GPIOIN) & mask;
diff --git a/drivers/ssb/driver_gige.c b/drivers/ssb/driver_gige.c
new file mode 100644
index 000000000000..172f90407b93
--- /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 a9e7eb45b2e7..3fd3e3b412b6 100644
--- a/drivers/ssb/driver_mipscore.c
+++ b/drivers/ssb/driver_mipscore.c
@@ -210,6 +210,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
210 /* fallthrough */ 210 /* fallthrough */
211 case SSB_DEV_PCI: 211 case SSB_DEV_PCI:
212 case SSB_DEV_ETHERNET: 212 case SSB_DEV_ETHERNET:
213 case SSB_DEV_ETHERNET_GBIT:
213 case SSB_DEV_80211: 214 case SSB_DEV_80211:
214 case SSB_DEV_USB20_HOST: 215 case SSB_DEV_USB20_HOST:
215 /* These devices get their own IRQ line if available, the rest goes on IRQ0 */ 216 /* 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 5d777f211699..75def13e797d 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;
@@ -544,15 +562,9 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
544 u32 intvec; 562 u32 intvec;
545 563
546 intvec = ssb_read32(pdev, SSB_INTVEC); 564 intvec = ssb_read32(pdev, SSB_INTVEC);
547 if ((bus->chip_id & 0xFF00) == 0x4400) { 565 tmp = ssb_read32(dev, SSB_TPSFLAG);
548 /* Workaround: On the BCM44XX the BPFLAG routing 566 tmp &= SSB_TPSFLAG_BPFLAG;
549 * bit is wrong. Use a hardcoded constant. */ 567 intvec |= (1 << tmp);
550 intvec |= 0x00000002;
551 } else {
552 tmp = ssb_read32(dev, SSB_TPSFLAG);
553 tmp &= SSB_TPSFLAG_BPFLAG;
554 intvec |= (1 << tmp);
555 }
556 ssb_write32(pdev, SSB_INTVEC, intvec); 568 ssb_write32(pdev, SSB_INTVEC, intvec);
557 } 569 }
558 570
diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c
index d3ade821555c..7dc3a6b41397 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 8003a9e55ac4..7cf8851286b5 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,44 @@ found:
68} 69}
69#endif /* CONFIG_SSB_PCIHOST */ 70#endif /* CONFIG_SSB_PCIHOST */
70 71
72#ifdef CONFIG_SSB_PCMCIAHOST
73struct ssb_bus *ssb_pcmcia_dev_to_bus(struct pcmcia_device *pdev)
74{
75 struct ssb_bus *bus;
76
77 ssb_buses_lock();
78 list_for_each_entry(bus, &buses, list) {
79 if (bus->bustype == SSB_BUSTYPE_PCMCIA &&
80 bus->host_pcmcia == pdev)
81 goto found;
82 }
83 bus = NULL;
84found:
85 ssb_buses_unlock();
86
87 return bus;
88}
89#endif /* CONFIG_SSB_PCMCIAHOST */
90
91int ssb_for_each_bus_call(unsigned long data,
92 int (*func)(struct ssb_bus *bus, unsigned long data))
93{
94 struct ssb_bus *bus;
95 int res;
96
97 ssb_buses_lock();
98 list_for_each_entry(bus, &buses, list) {
99 res = func(bus, data);
100 if (res >= 0) {
101 ssb_buses_unlock();
102 return res;
103 }
104 }
105 ssb_buses_unlock();
106
107 return -ENODEV;
108}
109
71static struct ssb_device *ssb_device_get(struct ssb_device *dev) 110static struct ssb_device *ssb_device_get(struct ssb_device *dev)
72{ 111{
73 if (dev) 112 if (dev)
@@ -81,35 +120,12 @@ static void ssb_device_put(struct ssb_device *dev)
81 put_device(dev->dev); 120 put_device(dev->dev);
82} 121}
83 122
84static int ssb_bus_resume(struct ssb_bus *bus)
85{
86 int err;
87
88 ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1);
89 err = ssb_pcmcia_init(bus);
90 if (err) {
91 /* No need to disable XTAL, as we don't have one on PCMCIA. */
92 return err;
93 }
94 ssb_chipco_resume(&bus->chipco);
95
96 return 0;
97}
98
99static int ssb_device_resume(struct device *dev) 123static int ssb_device_resume(struct device *dev)
100{ 124{
101 struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); 125 struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
102 struct ssb_driver *ssb_drv; 126 struct ssb_driver *ssb_drv;
103 struct ssb_bus *bus;
104 int err = 0; 127 int err = 0;
105 128
106 bus = ssb_dev->bus;
107 if (bus->suspend_cnt == bus->nr_devices) {
108 err = ssb_bus_resume(bus);
109 if (err)
110 return err;
111 }
112 bus->suspend_cnt--;
113 if (dev->driver) { 129 if (dev->driver) {
114 ssb_drv = drv_to_ssb_drv(dev->driver); 130 ssb_drv = drv_to_ssb_drv(dev->driver);
115 if (ssb_drv && ssb_drv->resume) 131 if (ssb_drv && ssb_drv->resume)
@@ -121,27 +137,10 @@ out:
121 return err; 137 return err;
122} 138}
123 139
124static void ssb_bus_suspend(struct ssb_bus *bus, pm_message_t state)
125{
126 ssb_chipco_suspend(&bus->chipco, state);
127 ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0);
128
129 /* Reset HW state information in memory, so that HW is
130 * completely reinitialized on resume. */
131 bus->mapped_device = NULL;
132#ifdef CONFIG_SSB_DRIVER_PCICORE
133 bus->pcicore.setup_done = 0;
134#endif
135#ifdef CONFIG_SSB_DEBUG
136 bus->powered_up = 0;
137#endif
138}
139
140static int ssb_device_suspend(struct device *dev, pm_message_t state) 140static int ssb_device_suspend(struct device *dev, pm_message_t state)
141{ 141{
142 struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); 142 struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
143 struct ssb_driver *ssb_drv; 143 struct ssb_driver *ssb_drv;
144 struct ssb_bus *bus;
145 int err = 0; 144 int err = 0;
146 145
147 if (dev->driver) { 146 if (dev->driver) {
@@ -151,19 +150,46 @@ static int ssb_device_suspend(struct device *dev, pm_message_t state)
151 if (err) 150 if (err)
152 goto out; 151 goto out;
153 } 152 }
153out:
154 return err;
155}
156
157int ssb_bus_resume(struct ssb_bus *bus)
158{
159 int err;
160
161 /* Reset HW state information in memory, so that HW is
162 * completely reinitialized. */
163 bus->mapped_device = NULL;
164#ifdef CONFIG_SSB_DRIVER_PCICORE
165 bus->pcicore.setup_done = 0;
166#endif
154 167
155 bus = ssb_dev->bus; 168 err = ssb_bus_powerup(bus, 0);
156 bus->suspend_cnt++; 169 if (err)
157 if (bus->suspend_cnt == bus->nr_devices) { 170 return err;
158 /* All devices suspended. Shutdown the bus. */ 171 err = ssb_pcmcia_hardware_setup(bus);
159 ssb_bus_suspend(bus, state); 172 if (err) {
173 ssb_bus_may_powerdown(bus);
174 return err;
160 } 175 }
176 ssb_chipco_resume(&bus->chipco);
177 ssb_bus_may_powerdown(bus);
161 178
162out: 179 return 0;
163 return err;
164} 180}
181EXPORT_SYMBOL(ssb_bus_resume);
165 182
166#ifdef CONFIG_SSB_PCIHOST 183int ssb_bus_suspend(struct ssb_bus *bus)
184{
185 ssb_chipco_suspend(&bus->chipco);
186 ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0);
187
188 return 0;
189}
190EXPORT_SYMBOL(ssb_bus_suspend);
191
192#ifdef CONFIG_SSB_SPROM
167int ssb_devices_freeze(struct ssb_bus *bus) 193int ssb_devices_freeze(struct ssb_bus *bus)
168{ 194{
169 struct ssb_device *dev; 195 struct ssb_device *dev;
@@ -249,7 +275,7 @@ int ssb_devices_thaw(struct ssb_bus *bus)
249 275
250 return 0; 276 return 0;
251} 277}
252#endif /* CONFIG_SSB_PCIHOST */ 278#endif /* CONFIG_SSB_SPROM */
253 279
254static void ssb_device_shutdown(struct device *dev) 280static void ssb_device_shutdown(struct device *dev)
255{ 281{
@@ -378,7 +404,7 @@ void ssb_bus_unregister(struct ssb_bus *bus)
378 list_del(&bus->list); 404 list_del(&bus->list);
379 ssb_buses_unlock(); 405 ssb_buses_unlock();
380 406
381 /* ssb_pcmcia_exit(bus); */ 407 ssb_pcmcia_exit(bus);
382 ssb_pci_exit(bus); 408 ssb_pci_exit(bus);
383 ssb_iounmap(bus); 409 ssb_iounmap(bus);
384} 410}
@@ -508,6 +534,14 @@ error:
508 return err; 534 return err;
509} 535}
510 536
537static u8 ssb_ssb_read8(struct ssb_device *dev, u16 offset)
538{
539 struct ssb_bus *bus = dev->bus;
540
541 offset += dev->core_index * SSB_CORE_SIZE;
542 return readb(bus->mmio + offset);
543}
544
511static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset) 545static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset)
512{ 546{
513 struct ssb_bus *bus = dev->bus; 547 struct ssb_bus *bus = dev->bus;
@@ -524,6 +558,63 @@ static u32 ssb_ssb_read32(struct ssb_device *dev, u16 offset)
524 return readl(bus->mmio + offset); 558 return readl(bus->mmio + offset);
525} 559}
526 560
561#ifdef CONFIG_SSB_BLOCKIO
562static void ssb_ssb_block_read(struct ssb_device *dev, void *buffer,
563 size_t count, u16 offset, u8 reg_width)
564{
565 struct ssb_bus *bus = dev->bus;
566 void __iomem *addr;
567
568 offset += dev->core_index * SSB_CORE_SIZE;
569 addr = bus->mmio + offset;
570
571 switch (reg_width) {
572 case sizeof(u8): {
573 u8 *buf = buffer;
574
575 while (count) {
576 *buf = __raw_readb(addr);
577 buf++;
578 count--;
579 }
580 break;
581 }
582 case sizeof(u16): {
583 __le16 *buf = buffer;
584
585 SSB_WARN_ON(count & 1);
586 while (count) {
587 *buf = (__force __le16)__raw_readw(addr);
588 buf++;
589 count -= 2;
590 }
591 break;
592 }
593 case sizeof(u32): {
594 __le32 *buf = buffer;
595
596 SSB_WARN_ON(count & 3);
597 while (count) {
598 *buf = (__force __le32)__raw_readl(addr);
599 buf++;
600 count -= 4;
601 }
602 break;
603 }
604 default:
605 SSB_WARN_ON(1);
606 }
607}
608#endif /* CONFIG_SSB_BLOCKIO */
609
610static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value)
611{
612 struct ssb_bus *bus = dev->bus;
613
614 offset += dev->core_index * SSB_CORE_SIZE;
615 writeb(value, bus->mmio + offset);
616}
617
527static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value) 618static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value)
528{ 619{
529 struct ssb_bus *bus = dev->bus; 620 struct ssb_bus *bus = dev->bus;
@@ -540,12 +631,67 @@ static void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value)
540 writel(value, bus->mmio + offset); 631 writel(value, bus->mmio + offset);
541} 632}
542 633
634#ifdef CONFIG_SSB_BLOCKIO
635static void ssb_ssb_block_write(struct ssb_device *dev, const void *buffer,
636 size_t count, u16 offset, u8 reg_width)
637{
638 struct ssb_bus *bus = dev->bus;
639 void __iomem *addr;
640
641 offset += dev->core_index * SSB_CORE_SIZE;
642 addr = bus->mmio + offset;
643
644 switch (reg_width) {
645 case sizeof(u8): {
646 const u8 *buf = buffer;
647
648 while (count) {
649 __raw_writeb(*buf, addr);
650 buf++;
651 count--;
652 }
653 break;
654 }
655 case sizeof(u16): {
656 const __le16 *buf = buffer;
657
658 SSB_WARN_ON(count & 1);
659 while (count) {
660 __raw_writew((__force u16)(*buf), addr);
661 buf++;
662 count -= 2;
663 }
664 break;
665 }
666 case sizeof(u32): {
667 const __le32 *buf = buffer;
668
669 SSB_WARN_ON(count & 3);
670 while (count) {
671 __raw_writel((__force u32)(*buf), addr);
672 buf++;
673 count -= 4;
674 }
675 break;
676 }
677 default:
678 SSB_WARN_ON(1);
679 }
680}
681#endif /* CONFIG_SSB_BLOCKIO */
682
543/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */ 683/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
544static const struct ssb_bus_ops ssb_ssb_ops = { 684static const struct ssb_bus_ops ssb_ssb_ops = {
685 .read8 = ssb_ssb_read8,
545 .read16 = ssb_ssb_read16, 686 .read16 = ssb_ssb_read16,
546 .read32 = ssb_ssb_read32, 687 .read32 = ssb_ssb_read32,
688 .write8 = ssb_ssb_write8,
547 .write16 = ssb_ssb_write16, 689 .write16 = ssb_ssb_write16,
548 .write32 = ssb_ssb_write32, 690 .write32 = ssb_ssb_write32,
691#ifdef CONFIG_SSB_BLOCKIO
692 .block_read = ssb_ssb_block_read,
693 .block_write = ssb_ssb_block_write,
694#endif
549}; 695};
550 696
551static int ssb_fetch_invariants(struct ssb_bus *bus, 697static int ssb_fetch_invariants(struct ssb_bus *bus,
@@ -628,7 +774,7 @@ out:
628err_dequeue: 774err_dequeue:
629 list_del(&bus->list); 775 list_del(&bus->list);
630err_pcmcia_exit: 776err_pcmcia_exit:
631/* ssb_pcmcia_exit(bus); */ 777 ssb_pcmcia_exit(bus);
632err_pci_exit: 778err_pci_exit:
633 ssb_pci_exit(bus); 779 ssb_pci_exit(bus);
634err_unmap: 780err_unmap:
@@ -1010,9 +1156,9 @@ u32 ssb_dma_translation(struct ssb_device *dev)
1010{ 1156{
1011 switch (dev->bus->bustype) { 1157 switch (dev->bus->bustype) {
1012 case SSB_BUSTYPE_SSB: 1158 case SSB_BUSTYPE_SSB:
1159 case SSB_BUSTYPE_PCMCIA:
1013 return 0; 1160 return 0;
1014 case SSB_BUSTYPE_PCI: 1161 case SSB_BUSTYPE_PCI:
1015 case SSB_BUSTYPE_PCMCIA:
1016 return SSB_PCI_DMA; 1162 return SSB_PCI_DMA;
1017 } 1163 }
1018 return 0; 1164 return 0;
@@ -1161,7 +1307,14 @@ static int __init ssb_modinit(void)
1161 err = b43_pci_ssb_bridge_init(); 1307 err = b43_pci_ssb_bridge_init();
1162 if (err) { 1308 if (err) {
1163 ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge " 1309 ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge "
1164 "initialization failed"); 1310 "initialization failed\n");
1311 /* don't fail SSB init because of this */
1312 err = 0;
1313 }
1314 err = ssb_gige_init();
1315 if (err) {
1316 ssb_printk(KERN_ERR "SSB Broadcom Gigabit Ethernet "
1317 "driver initialization failed\n");
1165 /* don't fail SSB init because of this */ 1318 /* don't fail SSB init because of this */
1166 err = 0; 1319 err = 0;
1167 } 1320 }
@@ -1175,6 +1328,7 @@ fs_initcall(ssb_modinit);
1175 1328
1176static void __exit ssb_modexit(void) 1329static void __exit ssb_modexit(void)
1177{ 1330{
1331 ssb_gige_exit();
1178 b43_pci_ssb_bridge_exit(); 1332 b43_pci_ssb_bridge_exit();
1179 bus_unregister(&ssb_bustype); 1333 bus_unregister(&ssb_bustype);
1180} 1334}
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index b434df75047f..904b1a8d0885 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -227,7 +227,7 @@ static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
227 return crc; 227 return crc;
228} 228}
229 229
230static int sprom_check_crc(const u16 *sprom, u16 size) 230static int sprom_check_crc(const u16 *sprom, size_t size)
231{ 231{
232 u8 crc; 232 u8 crc;
233 u8 expected_crc; 233 u8 expected_crc;
@@ -242,12 +242,14 @@ static int sprom_check_crc(const u16 *sprom, u16 size)
242 return 0; 242 return 0;
243} 243}
244 244
245static void sprom_do_read(struct ssb_bus *bus, u16 *sprom) 245static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
246{ 246{
247 int i; 247 int i;
248 248
249 for (i = 0; i < bus->sprom_size; i++) 249 for (i = 0; i < bus->sprom_size; i++)
250 sprom[i] = ioread16(bus->mmio + SSB_SPROM_BASE + (i * 2)); 250 sprom[i] = ioread16(bus->mmio + SSB_SPROM_BASE + (i * 2));
251
252 return 0;
251} 253}
252 254
253static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom) 255static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
@@ -572,6 +574,19 @@ static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
572} 574}
573#endif /* DEBUG */ 575#endif /* DEBUG */
574 576
577static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
578{
579 struct ssb_bus *bus = dev->bus;
580
581 if (unlikely(ssb_pci_assert_buspower(bus)))
582 return 0xFF;
583 if (unlikely(bus->mapped_device != dev)) {
584 if (unlikely(ssb_pci_switch_core(bus, dev)))
585 return 0xFF;
586 }
587 return ioread8(bus->mmio + offset);
588}
589
575static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset) 590static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
576{ 591{
577 struct ssb_bus *bus = dev->bus; 592 struct ssb_bus *bus = dev->bus;
@@ -598,6 +613,54 @@ static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
598 return ioread32(bus->mmio + offset); 613 return ioread32(bus->mmio + offset);
599} 614}
600 615
616#ifdef CONFIG_SSB_BLOCKIO
617static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
618 size_t count, u16 offset, u8 reg_width)
619{
620 struct ssb_bus *bus = dev->bus;
621 void __iomem *addr = bus->mmio + offset;
622
623 if (unlikely(ssb_pci_assert_buspower(bus)))
624 goto error;
625 if (unlikely(bus->mapped_device != dev)) {
626 if (unlikely(ssb_pci_switch_core(bus, dev)))
627 goto error;
628 }
629 switch (reg_width) {
630 case sizeof(u8):
631 ioread8_rep(addr, buffer, count);
632 break;
633 case sizeof(u16):
634 SSB_WARN_ON(count & 1);
635 ioread16_rep(addr, buffer, count >> 1);
636 break;
637 case sizeof(u32):
638 SSB_WARN_ON(count & 3);
639 ioread32_rep(addr, buffer, count >> 2);
640 break;
641 default:
642 SSB_WARN_ON(1);
643 }
644
645 return;
646error:
647 memset(buffer, 0xFF, count);
648}
649#endif /* CONFIG_SSB_BLOCKIO */
650
651static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
652{
653 struct ssb_bus *bus = dev->bus;
654
655 if (unlikely(ssb_pci_assert_buspower(bus)))
656 return;
657 if (unlikely(bus->mapped_device != dev)) {
658 if (unlikely(ssb_pci_switch_core(bus, dev)))
659 return;
660 }
661 iowrite8(value, bus->mmio + offset);
662}
663
601static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value) 664static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
602{ 665{
603 struct ssb_bus *bus = dev->bus; 666 struct ssb_bus *bus = dev->bus;
@@ -624,79 +687,63 @@ static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
624 iowrite32(value, bus->mmio + offset); 687 iowrite32(value, bus->mmio + offset);
625} 688}
626 689
690#ifdef CONFIG_SSB_BLOCKIO
691static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
692 size_t count, u16 offset, u8 reg_width)
693{
694 struct ssb_bus *bus = dev->bus;
695 void __iomem *addr = bus->mmio + offset;
696
697 if (unlikely(ssb_pci_assert_buspower(bus)))
698 return;
699 if (unlikely(bus->mapped_device != dev)) {
700 if (unlikely(ssb_pci_switch_core(bus, dev)))
701 return;
702 }
703 switch (reg_width) {
704 case sizeof(u8):
705 iowrite8_rep(addr, buffer, count);
706 break;
707 case sizeof(u16):
708 SSB_WARN_ON(count & 1);
709 iowrite16_rep(addr, buffer, count >> 1);
710 break;
711 case sizeof(u32):
712 SSB_WARN_ON(count & 3);
713 iowrite32_rep(addr, buffer, count >> 2);
714 break;
715 default:
716 SSB_WARN_ON(1);
717 }
718}
719#endif /* CONFIG_SSB_BLOCKIO */
720
627/* Not "static", as it's used in main.c */ 721/* Not "static", as it's used in main.c */
628const struct ssb_bus_ops ssb_pci_ops = { 722const struct ssb_bus_ops ssb_pci_ops = {
723 .read8 = ssb_pci_read8,
629 .read16 = ssb_pci_read16, 724 .read16 = ssb_pci_read16,
630 .read32 = ssb_pci_read32, 725 .read32 = ssb_pci_read32,
726 .write8 = ssb_pci_write8,
631 .write16 = ssb_pci_write16, 727 .write16 = ssb_pci_write16,
632 .write32 = ssb_pci_write32, 728 .write32 = ssb_pci_write32,
729#ifdef CONFIG_SSB_BLOCKIO
730 .block_read = ssb_pci_block_read,
731 .block_write = ssb_pci_block_write,
732#endif
633}; 733};
634 734
635static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, u16 size)
636{
637 int i, pos = 0;
638
639 for (i = 0; i < size; i++)
640 pos += snprintf(buf + pos, buf_len - pos - 1,
641 "%04X", swab16(sprom[i]) & 0xFFFF);
642 pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
643
644 return pos + 1;
645}
646
647static int hex2sprom(u16 *sprom, const char *dump, size_t len, u16 size)
648{
649 char tmp[5] = { 0 };
650 int cnt = 0;
651 unsigned long parsed;
652
653 if (len < size * 2)
654 return -EINVAL;
655
656 while (cnt < size) {
657 memcpy(tmp, dump, 4);
658 dump += 4;
659 parsed = simple_strtoul(tmp, NULL, 16);
660 sprom[cnt++] = swab16((u16)parsed);
661 }
662
663 return 0;
664}
665
666static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev, 735static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
667 struct device_attribute *attr, 736 struct device_attribute *attr,
668 char *buf) 737 char *buf)
669{ 738{
670 struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev); 739 struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
671 struct ssb_bus *bus; 740 struct ssb_bus *bus;
672 u16 *sprom;
673 int err = -ENODEV;
674 ssize_t count = 0;
675 741
676 bus = ssb_pci_dev_to_bus(pdev); 742 bus = ssb_pci_dev_to_bus(pdev);
677 if (!bus) 743 if (!bus)
678 goto out; 744 return -ENODEV;
679 err = -ENOMEM;
680 sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
681 if (!sprom)
682 goto out;
683
684 /* Use interruptible locking, as the SPROM write might
685 * be holding the lock for several seconds. So allow userspace
686 * to cancel operation. */
687 err = -ERESTARTSYS;
688 if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
689 goto out_kfree;
690 sprom_do_read(bus, sprom);
691 mutex_unlock(&bus->pci_sprom_mutex);
692 745
693 count = sprom2hex(sprom, buf, PAGE_SIZE, bus->sprom_size); 746 return ssb_attr_sprom_show(bus, buf, sprom_do_read);
694 err = 0;
695
696out_kfree:
697 kfree(sprom);
698out:
699 return err ? err : count;
700} 747}
701 748
702static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev, 749static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
@@ -705,55 +752,13 @@ static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
705{ 752{
706 struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev); 753 struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
707 struct ssb_bus *bus; 754 struct ssb_bus *bus;
708 u16 *sprom;
709 int res = 0, err = -ENODEV;
710 755
711 bus = ssb_pci_dev_to_bus(pdev); 756 bus = ssb_pci_dev_to_bus(pdev);
712 if (!bus) 757 if (!bus)
713 goto out; 758 return -ENODEV;
714 err = -ENOMEM;
715 sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
716 if (!sprom)
717 goto out;
718 err = hex2sprom(sprom, buf, count, bus->sprom_size);
719 if (err) {
720 err = -EINVAL;
721 goto out_kfree;
722 }
723 err = sprom_check_crc(sprom, bus->sprom_size);
724 if (err) {
725 err = -EINVAL;
726 goto out_kfree;
727 }
728 759
729 /* Use interruptible locking, as the SPROM write might 760 return ssb_attr_sprom_store(bus, buf, count,
730 * be holding the lock for several seconds. So allow userspace 761 sprom_check_crc, sprom_do_write);
731 * to cancel operation. */
732 err = -ERESTARTSYS;
733 if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
734 goto out_kfree;
735 err = ssb_devices_freeze(bus);
736 if (err == -EOPNOTSUPP) {
737 ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze devices. "
738 "No suspend support. Is CONFIG_PM enabled?\n");
739 goto out_unlock;
740 }
741 if (err) {
742 ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
743 goto out_unlock;
744 }
745 res = sprom_do_write(bus, sprom);
746 err = ssb_devices_thaw(bus);
747 if (err)
748 ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
749out_unlock:
750 mutex_unlock(&bus->pci_sprom_mutex);
751out_kfree:
752 kfree(sprom);
753out:
754 if (res)
755 return res;
756 return err ? err : count;
757} 762}
758 763
759static DEVICE_ATTR(ssb_sprom, 0600, 764static DEVICE_ATTR(ssb_sprom, 0600,
@@ -780,7 +785,7 @@ int ssb_pci_init(struct ssb_bus *bus)
780 return 0; 785 return 0;
781 786
782 pdev = bus->host_pci; 787 pdev = bus->host_pci;
783 mutex_init(&bus->pci_sprom_mutex); 788 mutex_init(&bus->sprom_mutex);
784 err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom); 789 err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
785 if (err) 790 if (err)
786 goto out; 791 goto out;
diff --git a/drivers/ssb/pcihost_wrapper.c b/drivers/ssb/pcihost_wrapper.c
index 82a10abef640..e82db4aaa050 100644
--- a/drivers/ssb/pcihost_wrapper.c
+++ b/drivers/ssb/pcihost_wrapper.c
@@ -18,6 +18,12 @@
18#ifdef CONFIG_PM 18#ifdef CONFIG_PM
19static int ssb_pcihost_suspend(struct pci_dev *dev, pm_message_t state) 19static int ssb_pcihost_suspend(struct pci_dev *dev, pm_message_t state)
20{ 20{
21 struct ssb_bus *ssb = pci_get_drvdata(dev);
22 int err;
23
24 err = ssb_bus_suspend(ssb);
25 if (err)
26 return err;
21 pci_save_state(dev); 27 pci_save_state(dev);
22 pci_disable_device(dev); 28 pci_disable_device(dev);
23 pci_set_power_state(dev, pci_choose_state(dev, state)); 29 pci_set_power_state(dev, pci_choose_state(dev, state));
@@ -27,6 +33,7 @@ static int ssb_pcihost_suspend(struct pci_dev *dev, pm_message_t state)
27 33
28static int ssb_pcihost_resume(struct pci_dev *dev) 34static int ssb_pcihost_resume(struct pci_dev *dev)
29{ 35{
36 struct ssb_bus *ssb = pci_get_drvdata(dev);
30 int err; 37 int err;
31 38
32 pci_set_power_state(dev, 0); 39 pci_set_power_state(dev, 0);
@@ -34,6 +41,9 @@ static int ssb_pcihost_resume(struct pci_dev *dev)
34 if (err) 41 if (err)
35 return err; 42 return err;
36 pci_restore_state(dev); 43 pci_restore_state(dev);
44 err = ssb_bus_resume(ssb);
45 if (err)
46 return err;
37 47
38 return 0; 48 return 0;
39} 49}
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
index 46816cda8b98..24c2a46c1476 100644
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -3,7 +3,7 @@
3 * PCMCIA-Hostbus related functions 3 * PCMCIA-Hostbus related functions
4 * 4 *
5 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> 5 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
6 * Copyright 2007 Michael Buesch <mb@bu3sch.de> 6 * Copyright 2007-2008 Michael Buesch <mb@bu3sch.de>
7 * 7 *
8 * Licensed under the GNU/GPL. See COPYING for details. 8 * Licensed under the GNU/GPL. See COPYING for details.
9 */ 9 */
@@ -11,6 +11,7 @@
11#include <linux/ssb/ssb.h> 11#include <linux/ssb/ssb.h>
12#include <linux/delay.h> 12#include <linux/delay.h>
13#include <linux/io.h> 13#include <linux/io.h>
14#include <linux/etherdevice.h>
14 15
15#include <pcmcia/cs_types.h> 16#include <pcmcia/cs_types.h>
16#include <pcmcia/cs.h> 17#include <pcmcia/cs.h>
@@ -26,59 +27,127 @@
26#define SSB_VERBOSE_PCMCIACORESWITCH_DEBUG 0 27#define SSB_VERBOSE_PCMCIACORESWITCH_DEBUG 0
27 28
28 29
30/* PCMCIA configuration registers */
31#define SSB_PCMCIA_ADDRESS0 0x2E
32#define SSB_PCMCIA_ADDRESS1 0x30
33#define SSB_PCMCIA_ADDRESS2 0x32
34#define SSB_PCMCIA_MEMSEG 0x34
35#define SSB_PCMCIA_SPROMCTL 0x36
36#define SSB_PCMCIA_SPROMCTL_IDLE 0
37#define SSB_PCMCIA_SPROMCTL_WRITE 1
38#define SSB_PCMCIA_SPROMCTL_READ 2
39#define SSB_PCMCIA_SPROMCTL_WRITEEN 4
40#define SSB_PCMCIA_SPROMCTL_WRITEDIS 7
41#define SSB_PCMCIA_SPROMCTL_DONE 8
42#define SSB_PCMCIA_SPROM_DATALO 0x38
43#define SSB_PCMCIA_SPROM_DATAHI 0x3A
44#define SSB_PCMCIA_SPROM_ADDRLO 0x3C
45#define SSB_PCMCIA_SPROM_ADDRHI 0x3E
46
47/* Hardware invariants CIS tuples */
48#define SSB_PCMCIA_CIS 0x80
49#define SSB_PCMCIA_CIS_ID 0x01
50#define SSB_PCMCIA_CIS_BOARDREV 0x02
51#define SSB_PCMCIA_CIS_PA 0x03
52#define SSB_PCMCIA_CIS_PA_PA0B0_LO 0
53#define SSB_PCMCIA_CIS_PA_PA0B0_HI 1
54#define SSB_PCMCIA_CIS_PA_PA0B1_LO 2
55#define SSB_PCMCIA_CIS_PA_PA0B1_HI 3
56#define SSB_PCMCIA_CIS_PA_PA0B2_LO 4
57#define SSB_PCMCIA_CIS_PA_PA0B2_HI 5
58#define SSB_PCMCIA_CIS_PA_ITSSI 6
59#define SSB_PCMCIA_CIS_PA_MAXPOW 7
60#define SSB_PCMCIA_CIS_OEMNAME 0x04
61#define SSB_PCMCIA_CIS_CCODE 0x05
62#define SSB_PCMCIA_CIS_ANTENNA 0x06
63#define SSB_PCMCIA_CIS_ANTGAIN 0x07
64#define SSB_PCMCIA_CIS_BFLAGS 0x08
65#define SSB_PCMCIA_CIS_LEDS 0x09
66
67/* PCMCIA SPROM size. */
68#define SSB_PCMCIA_SPROM_SIZE 256
69#define SSB_PCMCIA_SPROM_SIZE_BYTES (SSB_PCMCIA_SPROM_SIZE * sizeof(u16))
70
71
72/* Write to a PCMCIA configuration register. */
73static int ssb_pcmcia_cfg_write(struct ssb_bus *bus, u8 offset, u8 value)
74{
75 conf_reg_t reg;
76 int res;
77
78 memset(&reg, 0, sizeof(reg));
79 reg.Offset = offset;
80 reg.Action = CS_WRITE;
81 reg.Value = value;
82 res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
83 if (unlikely(res != CS_SUCCESS))
84 return -EBUSY;
85
86 return 0;
87}
88
89/* Read from a PCMCIA configuration register. */
90static int ssb_pcmcia_cfg_read(struct ssb_bus *bus, u8 offset, u8 *value)
91{
92 conf_reg_t reg;
93 int res;
94
95 memset(&reg, 0, sizeof(reg));
96 reg.Offset = offset;
97 reg.Action = CS_READ;
98 res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
99 if (unlikely(res != CS_SUCCESS))
100 return -EBUSY;
101 *value = reg.Value;
102
103 return 0;
104}
105
29int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus, 106int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
30 u8 coreidx) 107 u8 coreidx)
31{ 108{
32 struct pcmcia_device *pdev = bus->host_pcmcia;
33 int err; 109 int err;
34 int attempts = 0; 110 int attempts = 0;
35 u32 cur_core; 111 u32 cur_core;
36 conf_reg_t reg;
37 u32 addr; 112 u32 addr;
38 u32 read_addr; 113 u32 read_addr;
114 u8 val;
39 115
40 addr = (coreidx * SSB_CORE_SIZE) + SSB_ENUM_BASE; 116 addr = (coreidx * SSB_CORE_SIZE) + SSB_ENUM_BASE;
41 while (1) { 117 while (1) {
42 reg.Action = CS_WRITE; 118 err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS0,
43 reg.Offset = 0x2E; 119 (addr & 0x0000F000) >> 12);
44 reg.Value = (addr & 0x0000F000) >> 12; 120 if (err)
45 err = pcmcia_access_configuration_register(pdev, &reg);
46 if (err != CS_SUCCESS)
47 goto error; 121 goto error;
48 reg.Offset = 0x30; 122 err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS1,
49 reg.Value = (addr & 0x00FF0000) >> 16; 123 (addr & 0x00FF0000) >> 16);
50 err = pcmcia_access_configuration_register(pdev, &reg); 124 if (err)
51 if (err != CS_SUCCESS)
52 goto error; 125 goto error;
53 reg.Offset = 0x32; 126 err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS2,
54 reg.Value = (addr & 0xFF000000) >> 24; 127 (addr & 0xFF000000) >> 24);
55 err = pcmcia_access_configuration_register(pdev, &reg); 128 if (err)
56 if (err != CS_SUCCESS)
57 goto error; 129 goto error;
58 130
59 read_addr = 0; 131 read_addr = 0;
60 132
61 reg.Action = CS_READ; 133 err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS0, &val);
62 reg.Offset = 0x2E; 134 if (err)
63 err = pcmcia_access_configuration_register(pdev, &reg);
64 if (err != CS_SUCCESS)
65 goto error; 135 goto error;
66 read_addr |= ((u32)(reg.Value & 0x0F)) << 12; 136 read_addr |= ((u32)(val & 0x0F)) << 12;
67 reg.Offset = 0x30; 137 err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS1, &val);
68 err = pcmcia_access_configuration_register(pdev, &reg); 138 if (err)
69 if (err != CS_SUCCESS)
70 goto error; 139 goto error;
71 read_addr |= ((u32)reg.Value) << 16; 140 read_addr |= ((u32)val) << 16;
72 reg.Offset = 0x32; 141 err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS2, &val);
73 err = pcmcia_access_configuration_register(pdev, &reg); 142 if (err)
74 if (err != CS_SUCCESS)
75 goto error; 143 goto error;
76 read_addr |= ((u32)reg.Value) << 24; 144 read_addr |= ((u32)val) << 24;
77 145
78 cur_core = (read_addr - SSB_ENUM_BASE) / SSB_CORE_SIZE; 146 cur_core = (read_addr - SSB_ENUM_BASE) / SSB_CORE_SIZE;
79 if (cur_core == coreidx) 147 if (cur_core == coreidx)
80 break; 148 break;
81 149
150 err = -ETIMEDOUT;
82 if (attempts++ > SSB_BAR0_MAX_RETRIES) 151 if (attempts++ > SSB_BAR0_MAX_RETRIES)
83 goto error; 152 goto error;
84 udelay(10); 153 udelay(10);
@@ -87,7 +156,7 @@ int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
87 return 0; 156 return 0;
88error: 157error:
89 ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx); 158 ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
90 return -ENODEV; 159 return err;
91} 160}
92 161
93int ssb_pcmcia_switch_core(struct ssb_bus *bus, 162int ssb_pcmcia_switch_core(struct ssb_bus *bus,
@@ -112,27 +181,21 @@ int ssb_pcmcia_switch_core(struct ssb_bus *bus,
112int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg) 181int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg)
113{ 182{
114 int attempts = 0; 183 int attempts = 0;
115 conf_reg_t reg; 184 int err;
116 int res; 185 u8 val;
117 186
118 SSB_WARN_ON((seg != 0) && (seg != 1)); 187 SSB_WARN_ON((seg != 0) && (seg != 1));
119 reg.Offset = 0x34;
120 reg.Function = 0;
121 while (1) { 188 while (1) {
122 reg.Action = CS_WRITE; 189 err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_MEMSEG, seg);
123 reg.Value = seg; 190 if (err)
124 res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
125 if (unlikely(res != CS_SUCCESS))
126 goto error; 191 goto error;
127 reg.Value = 0xFF; 192 err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_MEMSEG, &val);
128 reg.Action = CS_READ; 193 if (err)
129 res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
130 if (unlikely(res != CS_SUCCESS))
131 goto error; 194 goto error;
132 195 if (val == seg)
133 if (reg.Value == seg)
134 break; 196 break;
135 197
198 err = -ETIMEDOUT;
136 if (unlikely(attempts++ > SSB_BAR0_MAX_RETRIES)) 199 if (unlikely(attempts++ > SSB_BAR0_MAX_RETRIES))
137 goto error; 200 goto error;
138 udelay(10); 201 udelay(10);
@@ -142,7 +205,7 @@ int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg)
142 return 0; 205 return 0;
143error: 206error:
144 ssb_printk(KERN_ERR PFX "Failed to switch pcmcia segment\n"); 207 ssb_printk(KERN_ERR PFX "Failed to switch pcmcia segment\n");
145 return -ENODEV; 208 return err;
146} 209}
147 210
148static int select_core_and_segment(struct ssb_device *dev, 211static int select_core_and_segment(struct ssb_device *dev,
@@ -172,6 +235,22 @@ static int select_core_and_segment(struct ssb_device *dev,
172 return 0; 235 return 0;
173} 236}
174 237
238static u8 ssb_pcmcia_read8(struct ssb_device *dev, u16 offset)
239{
240 struct ssb_bus *bus = dev->bus;
241 unsigned long flags;
242 int err;
243 u8 value = 0xFF;
244
245 spin_lock_irqsave(&bus->bar_lock, flags);
246 err = select_core_and_segment(dev, &offset);
247 if (likely(!err))
248 value = readb(bus->mmio + offset);
249 spin_unlock_irqrestore(&bus->bar_lock, flags);
250
251 return value;
252}
253
175static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset) 254static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset)
176{ 255{
177 struct ssb_bus *bus = dev->bus; 256 struct ssb_bus *bus = dev->bus;
@@ -206,6 +285,78 @@ static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset)
206 return (lo | (hi << 16)); 285 return (lo | (hi << 16));
207} 286}
208 287
288#ifdef CONFIG_SSB_BLOCKIO
289static void ssb_pcmcia_block_read(struct ssb_device *dev, void *buffer,
290 size_t count, u16 offset, u8 reg_width)
291{
292 struct ssb_bus *bus = dev->bus;
293 unsigned long flags;
294 void __iomem *addr = bus->mmio + offset;
295 int err;
296
297 spin_lock_irqsave(&bus->bar_lock, flags);
298 err = select_core_and_segment(dev, &offset);
299 if (unlikely(err)) {
300 memset(buffer, 0xFF, count);
301 goto unlock;
302 }
303 switch (reg_width) {
304 case sizeof(u8): {
305 u8 *buf = buffer;
306
307 while (count) {
308 *buf = __raw_readb(addr);
309 buf++;
310 count--;
311 }
312 break;
313 }
314 case sizeof(u16): {
315 __le16 *buf = buffer;
316
317 SSB_WARN_ON(count & 1);
318 while (count) {
319 *buf = (__force __le16)__raw_readw(addr);
320 buf++;
321 count -= 2;
322 }
323 break;
324 }
325 case sizeof(u32): {
326 __le16 *buf = buffer;
327
328 SSB_WARN_ON(count & 3);
329 while (count) {
330 *buf = (__force __le16)__raw_readw(addr);
331 buf++;
332 *buf = (__force __le16)__raw_readw(addr + 2);
333 buf++;
334 count -= 4;
335 }
336 break;
337 }
338 default:
339 SSB_WARN_ON(1);
340 }
341unlock:
342 spin_unlock_irqrestore(&bus->bar_lock, flags);
343}
344#endif /* CONFIG_SSB_BLOCKIO */
345
346static void ssb_pcmcia_write8(struct ssb_device *dev, u16 offset, u8 value)
347{
348 struct ssb_bus *bus = dev->bus;
349 unsigned long flags;
350 int err;
351
352 spin_lock_irqsave(&bus->bar_lock, flags);
353 err = select_core_and_segment(dev, &offset);
354 if (likely(!err))
355 writeb(value, bus->mmio + offset);
356 mmiowb();
357 spin_unlock_irqrestore(&bus->bar_lock, flags);
358}
359
209static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value) 360static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value)
210{ 361{
211 struct ssb_bus *bus = dev->bus; 362 struct ssb_bus *bus = dev->bus;
@@ -236,26 +387,425 @@ static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value)
236 spin_unlock_irqrestore(&bus->bar_lock, flags); 387 spin_unlock_irqrestore(&bus->bar_lock, flags);
237} 388}
238 389
390#ifdef CONFIG_SSB_BLOCKIO
391static void ssb_pcmcia_block_write(struct ssb_device *dev, const void *buffer,
392 size_t count, u16 offset, u8 reg_width)
393{
394 struct ssb_bus *bus = dev->bus;
395 unsigned long flags;
396 void __iomem *addr = bus->mmio + offset;
397 int err;
398
399 spin_lock_irqsave(&bus->bar_lock, flags);
400 err = select_core_and_segment(dev, &offset);
401 if (unlikely(err))
402 goto unlock;
403 switch (reg_width) {
404 case sizeof(u8): {
405 const u8 *buf = buffer;
406
407 while (count) {
408 __raw_writeb(*buf, addr);
409 buf++;
410 count--;
411 }
412 break;
413 }
414 case sizeof(u16): {
415 const __le16 *buf = buffer;
416
417 SSB_WARN_ON(count & 1);
418 while (count) {
419 __raw_writew((__force u16)(*buf), addr);
420 buf++;
421 count -= 2;
422 }
423 break;
424 }
425 case sizeof(u32): {
426 const __le16 *buf = buffer;
427
428 SSB_WARN_ON(count & 3);
429 while (count) {
430 __raw_writew((__force u16)(*buf), addr);
431 buf++;
432 __raw_writew((__force u16)(*buf), addr + 2);
433 buf++;
434 count -= 4;
435 }
436 break;
437 }
438 default:
439 SSB_WARN_ON(1);
440 }
441unlock:
442 mmiowb();
443 spin_unlock_irqrestore(&bus->bar_lock, flags);
444}
445#endif /* CONFIG_SSB_BLOCKIO */
446
239/* Not "static", as it's used in main.c */ 447/* Not "static", as it's used in main.c */
240const struct ssb_bus_ops ssb_pcmcia_ops = { 448const struct ssb_bus_ops ssb_pcmcia_ops = {
449 .read8 = ssb_pcmcia_read8,
241 .read16 = ssb_pcmcia_read16, 450 .read16 = ssb_pcmcia_read16,
242 .read32 = ssb_pcmcia_read32, 451 .read32 = ssb_pcmcia_read32,
452 .write8 = ssb_pcmcia_write8,
243 .write16 = ssb_pcmcia_write16, 453 .write16 = ssb_pcmcia_write16,
244 .write32 = ssb_pcmcia_write32, 454 .write32 = ssb_pcmcia_write32,
455#ifdef CONFIG_SSB_BLOCKIO
456 .block_read = ssb_pcmcia_block_read,
457 .block_write = ssb_pcmcia_block_write,
458#endif
245}; 459};
246 460
247#include <linux/etherdevice.h> 461static int ssb_pcmcia_sprom_command(struct ssb_bus *bus, u8 command)
462{
463 unsigned int i;
464 int err;
465 u8 value;
466
467 err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROMCTL, command);
468 if (err)
469 return err;
470 for (i = 0; i < 1000; i++) {
471 err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROMCTL, &value);
472 if (err)
473 return err;
474 if (value & SSB_PCMCIA_SPROMCTL_DONE)
475 return 0;
476 udelay(10);
477 }
478
479 return -ETIMEDOUT;
480}
481
482/* offset is the 16bit word offset */
483static int ssb_pcmcia_sprom_read(struct ssb_bus *bus, u16 offset, u16 *value)
484{
485 int err;
486 u8 lo, hi;
487
488 offset *= 2; /* Make byte offset */
489
490 err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,
491 (offset & 0x00FF));
492 if (err)
493 return err;
494 err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,
495 (offset & 0xFF00) >> 8);
496 if (err)
497 return err;
498 err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_READ);
499 if (err)
500 return err;
501 err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATALO, &lo);
502 if (err)
503 return err;
504 err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATAHI, &hi);
505 if (err)
506 return err;
507 *value = (lo | (((u16)hi) << 8));
508
509 return 0;
510}
511
512/* offset is the 16bit word offset */
513static int ssb_pcmcia_sprom_write(struct ssb_bus *bus, u16 offset, u16 value)
514{
515 int err;
516
517 offset *= 2; /* Make byte offset */
518
519 err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,
520 (offset & 0x00FF));
521 if (err)
522 return err;
523 err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,
524 (offset & 0xFF00) >> 8);
525 if (err)
526 return err;
527 err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATALO,
528 (value & 0x00FF));
529 if (err)
530 return err;
531 err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATAHI,
532 (value & 0xFF00) >> 8);
533 if (err)
534 return err;
535 err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITE);
536 if (err)
537 return err;
538 msleep(20);
539
540 return 0;
541}
542
543/* Read the SPROM image. bufsize is in 16bit words. */
544static int ssb_pcmcia_sprom_read_all(struct ssb_bus *bus, u16 *sprom)
545{
546 int err, i;
547
548 for (i = 0; i < SSB_PCMCIA_SPROM_SIZE; i++) {
549 err = ssb_pcmcia_sprom_read(bus, i, &sprom[i]);
550 if (err)
551 return err;
552 }
553
554 return 0;
555}
556
557/* Write the SPROM image. size is in 16bit words. */
558static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom)
559{
560 int i, err;
561 bool failed = 0;
562 size_t size = SSB_PCMCIA_SPROM_SIZE;
563
564 ssb_printk(KERN_NOTICE PFX
565 "Writing SPROM. Do NOT turn off the power! "
566 "Please stand by...\n");
567 err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN);
568 if (err) {
569 ssb_printk(KERN_NOTICE PFX
570 "Could not enable SPROM write access.\n");
571 return -EBUSY;
572 }
573 ssb_printk(KERN_NOTICE PFX "[ 0%%");
574 msleep(500);
575 for (i = 0; i < size; i++) {
576 if (i == size / 4)
577 ssb_printk("25%%");
578 else if (i == size / 2)
579 ssb_printk("50%%");
580 else if (i == (size * 3) / 4)
581 ssb_printk("75%%");
582 else if (i % 2)
583 ssb_printk(".");
584 err = ssb_pcmcia_sprom_write(bus, i, sprom[i]);
585 if (err) {
586 ssb_printk("\n" KERN_NOTICE PFX
587 "Failed to write to SPROM.\n");
588 failed = 1;
589 break;
590 }
591 }
592 err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS);
593 if (err) {
594 ssb_printk("\n" KERN_NOTICE PFX
595 "Could not disable SPROM write access.\n");
596 failed = 1;
597 }
598 msleep(500);
599 if (!failed) {
600 ssb_printk("100%% ]\n");
601 ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
602 }
603
604 return failed ? -EBUSY : 0;
605}
606
607static int ssb_pcmcia_sprom_check_crc(const u16 *sprom, size_t size)
608{
609 //TODO
610 return 0;
611}
612
613#define GOTO_ERROR_ON(condition, description) do { \
614 if (unlikely(condition)) { \
615 error_description = description; \
616 goto error; \
617 } \
618 } while (0)
619
248int ssb_pcmcia_get_invariants(struct ssb_bus *bus, 620int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
249 struct ssb_init_invariants *iv) 621 struct ssb_init_invariants *iv)
250{ 622{
251 //TODO 623 tuple_t tuple;
252 random_ether_addr(iv->sprom.il0mac); 624 int res;
625 unsigned char buf[32];
626 struct ssb_sprom *sprom = &iv->sprom;
627 struct ssb_boardinfo *bi = &iv->boardinfo;
628 const char *error_description;
629
630 memset(sprom, 0xFF, sizeof(*sprom));
631 sprom->revision = 1;
632 sprom->boardflags_lo = 0;
633 sprom->boardflags_hi = 0;
634
635 /* First fetch the MAC address. */
636 memset(&tuple, 0, sizeof(tuple));
637 tuple.DesiredTuple = CISTPL_FUNCE;
638 tuple.TupleData = buf;
639 tuple.TupleDataMax = sizeof(buf);
640 res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple);
641 GOTO_ERROR_ON(res != CS_SUCCESS, "MAC first tpl");
642 res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
643 GOTO_ERROR_ON(res != CS_SUCCESS, "MAC first tpl data");
644 while (1) {
645 GOTO_ERROR_ON(tuple.TupleDataLen < 1, "MAC tpl < 1");
646 if (tuple.TupleData[0] == CISTPL_FUNCE_LAN_NODE_ID)
647 break;
648 res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple);
649 GOTO_ERROR_ON(res != CS_SUCCESS, "MAC next tpl");
650 res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
651 GOTO_ERROR_ON(res != CS_SUCCESS, "MAC next tpl data");
652 }
653 GOTO_ERROR_ON(tuple.TupleDataLen != ETH_ALEN + 2, "MAC tpl size");
654 memcpy(sprom->il0mac, &tuple.TupleData[2], ETH_ALEN);
655
656 /* Fetch the vendor specific tuples. */
657 memset(&tuple, 0, sizeof(tuple));
658 tuple.DesiredTuple = SSB_PCMCIA_CIS;
659 tuple.TupleData = buf;
660 tuple.TupleDataMax = sizeof(buf);
661 res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple);
662 GOTO_ERROR_ON(res != CS_SUCCESS, "VEN first tpl");
663 res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
664 GOTO_ERROR_ON(res != CS_SUCCESS, "VEN first tpl data");
665 while (1) {
666 GOTO_ERROR_ON(tuple.TupleDataLen < 1, "VEN tpl < 1");
667 switch (tuple.TupleData[0]) {
668 case SSB_PCMCIA_CIS_ID:
669 GOTO_ERROR_ON((tuple.TupleDataLen != 5) &&
670 (tuple.TupleDataLen != 7),
671 "id tpl size");
672 bi->vendor = tuple.TupleData[1] |
673 ((u16)tuple.TupleData[2] << 8);
674 break;
675 case SSB_PCMCIA_CIS_BOARDREV:
676 GOTO_ERROR_ON(tuple.TupleDataLen != 2,
677 "boardrev tpl size");
678 sprom->board_rev = tuple.TupleData[1];
679 break;
680 case SSB_PCMCIA_CIS_PA:
681 GOTO_ERROR_ON(tuple.TupleDataLen != 9,
682 "pa tpl size");
683 sprom->pa0b0 = tuple.TupleData[1] |
684 ((u16)tuple.TupleData[2] << 8);
685 sprom->pa0b1 = tuple.TupleData[3] |
686 ((u16)tuple.TupleData[4] << 8);
687 sprom->pa0b2 = tuple.TupleData[5] |
688 ((u16)tuple.TupleData[6] << 8);
689 sprom->itssi_a = tuple.TupleData[7];
690 sprom->itssi_bg = tuple.TupleData[7];
691 sprom->maxpwr_a = tuple.TupleData[8];
692 sprom->maxpwr_bg = tuple.TupleData[8];
693 break;
694 case SSB_PCMCIA_CIS_OEMNAME:
695 /* We ignore this. */
696 break;
697 case SSB_PCMCIA_CIS_CCODE:
698 GOTO_ERROR_ON(tuple.TupleDataLen != 2,
699 "ccode tpl size");
700 sprom->country_code = tuple.TupleData[1];
701 break;
702 case SSB_PCMCIA_CIS_ANTENNA:
703 GOTO_ERROR_ON(tuple.TupleDataLen != 2,
704 "ant tpl size");
705 sprom->ant_available_a = tuple.TupleData[1];
706 sprom->ant_available_bg = tuple.TupleData[1];
707 break;
708 case SSB_PCMCIA_CIS_ANTGAIN:
709 GOTO_ERROR_ON(tuple.TupleDataLen != 2,
710 "antg tpl size");
711 sprom->antenna_gain.ghz24.a0 = tuple.TupleData[1];
712 sprom->antenna_gain.ghz24.a1 = tuple.TupleData[1];
713 sprom->antenna_gain.ghz24.a2 = tuple.TupleData[1];
714 sprom->antenna_gain.ghz24.a3 = tuple.TupleData[1];
715 sprom->antenna_gain.ghz5.a0 = tuple.TupleData[1];
716 sprom->antenna_gain.ghz5.a1 = tuple.TupleData[1];
717 sprom->antenna_gain.ghz5.a2 = tuple.TupleData[1];
718 sprom->antenna_gain.ghz5.a3 = tuple.TupleData[1];
719 break;
720 case SSB_PCMCIA_CIS_BFLAGS:
721 GOTO_ERROR_ON(tuple.TupleDataLen != 3,
722 "bfl tpl size");
723 sprom->boardflags_lo = tuple.TupleData[1] |
724 ((u16)tuple.TupleData[2] << 8);
725 break;
726 case SSB_PCMCIA_CIS_LEDS:
727 GOTO_ERROR_ON(tuple.TupleDataLen != 5,
728 "leds tpl size");
729 sprom->gpio0 = tuple.TupleData[1];
730 sprom->gpio1 = tuple.TupleData[2];
731 sprom->gpio2 = tuple.TupleData[3];
732 sprom->gpio3 = tuple.TupleData[4];
733 break;
734 }
735 res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple);
736 if (res == CS_NO_MORE_ITEMS)
737 break;
738 GOTO_ERROR_ON(res != CS_SUCCESS, "VEN next tpl");
739 res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
740 GOTO_ERROR_ON(res != CS_SUCCESS, "VEN next tpl data");
741 }
742
253 return 0; 743 return 0;
744error:
745 ssb_printk(KERN_ERR PFX
746 "PCMCIA: Failed to fetch device invariants: %s\n",
747 error_description);
748 return -ENODEV;
254} 749}
255 750
256int ssb_pcmcia_init(struct ssb_bus *bus) 751static ssize_t ssb_pcmcia_attr_sprom_show(struct device *pcmciadev,
752 struct device_attribute *attr,
753 char *buf)
754{
755 struct pcmcia_device *pdev =
756 container_of(pcmciadev, struct pcmcia_device, dev);
757 struct ssb_bus *bus;
758
759 bus = ssb_pcmcia_dev_to_bus(pdev);
760 if (!bus)
761 return -ENODEV;
762
763 return ssb_attr_sprom_show(bus, buf,
764 ssb_pcmcia_sprom_read_all);
765}
766
767static ssize_t ssb_pcmcia_attr_sprom_store(struct device *pcmciadev,
768 struct device_attribute *attr,
769 const char *buf, size_t count)
770{
771 struct pcmcia_device *pdev =
772 container_of(pcmciadev, struct pcmcia_device, dev);
773 struct ssb_bus *bus;
774
775 bus = ssb_pcmcia_dev_to_bus(pdev);
776 if (!bus)
777 return -ENODEV;
778
779 return ssb_attr_sprom_store(bus, buf, count,
780 ssb_pcmcia_sprom_check_crc,
781 ssb_pcmcia_sprom_write_all);
782}
783
784static DEVICE_ATTR(ssb_sprom, 0600,
785 ssb_pcmcia_attr_sprom_show,
786 ssb_pcmcia_attr_sprom_store);
787
788static int ssb_pcmcia_cor_setup(struct ssb_bus *bus, u8 cor)
789{
790 u8 val;
791 int err;
792
793 err = ssb_pcmcia_cfg_read(bus, cor, &val);
794 if (err)
795 return err;
796 val &= ~COR_SOFT_RESET;
797 val |= COR_FUNC_ENA | COR_IREQ_ENA | COR_LEVEL_REQ;
798 err = ssb_pcmcia_cfg_write(bus, cor, val);
799 if (err)
800 return err;
801 msleep(40);
802
803 return 0;
804}
805
806/* Initialize the PCMCIA hardware. This is called on Init and Resume. */
807int ssb_pcmcia_hardware_setup(struct ssb_bus *bus)
257{ 808{
258 conf_reg_t reg;
259 int err; 809 int err;
260 810
261 if (bus->bustype != SSB_BUSTYPE_PCMCIA) 811 if (bus->bustype != SSB_BUSTYPE_PCMCIA)
@@ -264,24 +814,45 @@ int ssb_pcmcia_init(struct ssb_bus *bus)
264 /* Switch segment to a known state and sync 814 /* Switch segment to a known state and sync
265 * bus->mapped_pcmcia_seg with hardware state. */ 815 * bus->mapped_pcmcia_seg with hardware state. */
266 ssb_pcmcia_switch_segment(bus, 0); 816 ssb_pcmcia_switch_segment(bus, 0);
817 /* Init the COR register. */
818 err = ssb_pcmcia_cor_setup(bus, CISREG_COR);
819 if (err)
820 return err;
821 /* Some cards also need this register to get poked. */
822 err = ssb_pcmcia_cor_setup(bus, CISREG_COR + 0x80);
823 if (err)
824 return err;
267 825
268 /* Init IRQ routing */ 826 return 0;
269 reg.Action = CS_READ; 827}
270 reg.Function = 0; 828
271 if (bus->chip_id == 0x4306) 829void ssb_pcmcia_exit(struct ssb_bus *bus)
272 reg.Offset = 0x00; 830{
273 else 831 if (bus->bustype != SSB_BUSTYPE_PCMCIA)
274 reg.Offset = 0x80; 832 return;
275 err = pcmcia_access_configuration_register(bus->host_pcmcia, &reg); 833
276 if (err != CS_SUCCESS) 834 device_remove_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);
835}
836
837int ssb_pcmcia_init(struct ssb_bus *bus)
838{
839 int err;
840
841 if (bus->bustype != SSB_BUSTYPE_PCMCIA)
842 return 0;
843
844 err = ssb_pcmcia_hardware_setup(bus);
845 if (err)
277 goto error; 846 goto error;
278 reg.Action = CS_WRITE; 847
279 reg.Value |= 0x04 | 0x01; 848 bus->sprom_size = SSB_PCMCIA_SPROM_SIZE;
280 err = pcmcia_access_configuration_register(bus->host_pcmcia, &reg); 849 mutex_init(&bus->sprom_mutex);
281 if (err != CS_SUCCESS) 850 err = device_create_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);
851 if (err)
282 goto error; 852 goto error;
283 853
284 return 0; 854 return 0;
285error: 855error:
286 return -ENODEV; 856 ssb_printk(KERN_ERR PFX "Failed to initialize PCMCIA host device\n");
857 return err;
287} 858}
diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c
new file mode 100644
index 000000000000..3668edb39315
--- /dev/null
+++ b/drivers/ssb/sprom.c
@@ -0,0 +1,133 @@
1/*
2 * Sonics Silicon Backplane
3 * Common SPROM support routines
4 *
5 * Copyright (C) 2005-2008 Michael Buesch <mb@bu3sch.de>
6 * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
7 * Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
8 * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
9 * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
10 *
11 * Licensed under the GNU/GPL. See COPYING for details.
12 */
13
14#include "ssb_private.h"
15
16
17static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len,
18 size_t sprom_size_words)
19{
20 int i, pos = 0;
21
22 for (i = 0; i < sprom_size_words; i++)
23 pos += snprintf(buf + pos, buf_len - pos - 1,
24 "%04X", swab16(sprom[i]) & 0xFFFF);
25 pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
26
27 return pos + 1;
28}
29
30static int hex2sprom(u16 *sprom, const char *dump, size_t len,
31 size_t sprom_size_words)
32{
33 char tmp[5] = { 0 };
34 int cnt = 0;
35 unsigned long parsed;
36
37 if (len < sprom_size_words * 2)
38 return -EINVAL;
39
40 while (cnt < sprom_size_words) {
41 memcpy(tmp, dump, 4);
42 dump += 4;
43 parsed = simple_strtoul(tmp, NULL, 16);
44 sprom[cnt++] = swab16((u16)parsed);
45 }
46
47 return 0;
48}
49
50/* Common sprom device-attribute show-handler */
51ssize_t ssb_attr_sprom_show(struct ssb_bus *bus, char *buf,
52 int (*sprom_read)(struct ssb_bus *bus, u16 *sprom))
53{
54 u16 *sprom;
55 int err = -ENOMEM;
56 ssize_t count = 0;
57 size_t sprom_size_words = bus->sprom_size;
58
59 sprom = kcalloc(sprom_size_words, sizeof(u16), GFP_KERNEL);
60 if (!sprom)
61 goto out;
62
63 /* Use interruptible locking, as the SPROM write might
64 * be holding the lock for several seconds. So allow userspace
65 * to cancel operation. */
66 err = -ERESTARTSYS;
67 if (mutex_lock_interruptible(&bus->sprom_mutex))
68 goto out_kfree;
69 err = sprom_read(bus, sprom);
70 mutex_unlock(&bus->sprom_mutex);
71
72 if (!err)
73 count = sprom2hex(sprom, buf, PAGE_SIZE, sprom_size_words);
74
75out_kfree:
76 kfree(sprom);
77out:
78 return err ? err : count;
79}
80
81/* Common sprom device-attribute store-handler */
82ssize_t ssb_attr_sprom_store(struct ssb_bus *bus,
83 const char *buf, size_t count,
84 int (*sprom_check_crc)(const u16 *sprom, size_t size),
85 int (*sprom_write)(struct ssb_bus *bus, const u16 *sprom))
86{
87 u16 *sprom;
88 int res = 0, err = -ENOMEM;
89 size_t sprom_size_words = bus->sprom_size;
90
91 sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
92 if (!sprom)
93 goto out;
94 err = hex2sprom(sprom, buf, count, sprom_size_words);
95 if (err) {
96 err = -EINVAL;
97 goto out_kfree;
98 }
99 err = sprom_check_crc(sprom, sprom_size_words);
100 if (err) {
101 err = -EINVAL;
102 goto out_kfree;
103 }
104
105 /* Use interruptible locking, as the SPROM write might
106 * be holding the lock for several seconds. So allow userspace
107 * to cancel operation. */
108 err = -ERESTARTSYS;
109 if (mutex_lock_interruptible(&bus->sprom_mutex))
110 goto out_kfree;
111 err = ssb_devices_freeze(bus);
112 if (err == -EOPNOTSUPP) {
113 ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze devices. "
114 "No suspend support. Is CONFIG_PM enabled?\n");
115 goto out_unlock;
116 }
117 if (err) {
118 ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
119 goto out_unlock;
120 }
121 res = sprom_write(bus, sprom);
122 err = ssb_devices_thaw(bus);
123 if (err)
124 ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
125out_unlock:
126 mutex_unlock(&bus->sprom_mutex);
127out_kfree:
128 kfree(sprom);
129out:
130 if (res)
131 return res;
132 return err ? err : count;
133}
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h
index 21eca2b5118b..ebc32d8fe15f 100644
--- a/drivers/ssb/ssb_private.h
+++ b/drivers/ssb/ssb_private.h
@@ -81,6 +81,8 @@ extern int ssb_pcmcia_switch_segment(struct ssb_bus *bus,
81 u8 seg); 81 u8 seg);
82extern int ssb_pcmcia_get_invariants(struct ssb_bus *bus, 82extern int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
83 struct ssb_init_invariants *iv); 83 struct ssb_init_invariants *iv);
84extern int ssb_pcmcia_hardware_setup(struct ssb_bus *bus);
85extern void ssb_pcmcia_exit(struct ssb_bus *bus);
84extern int ssb_pcmcia_init(struct ssb_bus *bus); 86extern int ssb_pcmcia_init(struct ssb_bus *bus);
85extern const struct ssb_bus_ops ssb_pcmcia_ops; 87extern const struct ssb_bus_ops ssb_pcmcia_ops;
86#else /* CONFIG_SSB_PCMCIAHOST */ 88#else /* CONFIG_SSB_PCMCIAHOST */
@@ -99,6 +101,13 @@ static inline int ssb_pcmcia_switch_segment(struct ssb_bus *bus,
99{ 101{
100 return 0; 102 return 0;
101} 103}
104static inline int ssb_pcmcia_hardware_setup(struct ssb_bus *bus)
105{
106 return 0;
107}
108static inline void ssb_pcmcia_exit(struct ssb_bus *bus)
109{
110}
102static inline int ssb_pcmcia_init(struct ssb_bus *bus) 111static inline int ssb_pcmcia_init(struct ssb_bus *bus)
103{ 112{
104 return 0; 113 return 0;
@@ -113,11 +122,26 @@ extern int ssb_bus_scan(struct ssb_bus *bus,
113extern void ssb_iounmap(struct ssb_bus *ssb); 122extern void ssb_iounmap(struct ssb_bus *ssb);
114 123
115 124
125/* sprom.c */
126extern
127ssize_t ssb_attr_sprom_show(struct ssb_bus *bus, char *buf,
128 int (*sprom_read)(struct ssb_bus *bus, u16 *sprom));
129extern
130ssize_t ssb_attr_sprom_store(struct ssb_bus *bus,
131 const char *buf, size_t count,
132 int (*sprom_check_crc)(const u16 *sprom, size_t size),
133 int (*sprom_write)(struct ssb_bus *bus, const u16 *sprom));
134
135
116/* core.c */ 136/* core.c */
117extern u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m); 137extern u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m);
118extern int ssb_devices_freeze(struct ssb_bus *bus); 138extern int ssb_devices_freeze(struct ssb_bus *bus);
119extern int ssb_devices_thaw(struct ssb_bus *bus); 139extern int ssb_devices_thaw(struct ssb_bus *bus);
120extern struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev); 140extern struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev);
141int ssb_for_each_bus_call(unsigned long data,
142 int (*func)(struct ssb_bus *bus, unsigned long data));
143extern struct ssb_bus *ssb_pcmcia_dev_to_bus(struct pcmcia_device *pdev);
144
121 145
122/* b43_pci_bridge.c */ 146/* b43_pci_bridge.c */
123#ifdef CONFIG_SSB_B43_PCI_BRIDGE 147#ifdef CONFIG_SSB_B43_PCI_BRIDGE