aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ssb/pcmcia.c
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2008-04-02 13:46:56 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-04-08 16:44:40 -0400
commitd625a29ba649a4df6027520ffc378f23c0e6883e (patch)
tree07b895d38717e24e655948c963f4287f551df42f /drivers/ssb/pcmcia.c
parent93af2614513103216038afa708718295e7016dbb (diff)
ssb: Add support for block-I/O
This adds support for block based I/O to SSB. This is needed in order to efficiently support PIO data transfers to the card. The block-I/O support is only compiled, if it's selected by the weird driver that needs it. So there's no overhead for sane devices. Signed-off-by: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/ssb/pcmcia.c')
-rw-r--r--drivers/ssb/pcmcia.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
index dcaf2412bea7..24c2a46c1476 100644
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -285,6 +285,64 @@ static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset)
285 return (lo | (hi << 16)); 285 return (lo | (hi << 16));
286} 286}
287 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
288static void ssb_pcmcia_write8(struct ssb_device *dev, u16 offset, u8 value) 346static void ssb_pcmcia_write8(struct ssb_device *dev, u16 offset, u8 value)
289{ 347{
290 struct ssb_bus *bus = dev->bus; 348 struct ssb_bus *bus = dev->bus;
@@ -329,6 +387,63 @@ static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value)
329 spin_unlock_irqrestore(&bus->bar_lock, flags); 387 spin_unlock_irqrestore(&bus->bar_lock, flags);
330} 388}
331 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
332/* Not "static", as it's used in main.c */ 447/* Not "static", as it's used in main.c */
333const struct ssb_bus_ops ssb_pcmcia_ops = { 448const struct ssb_bus_ops ssb_pcmcia_ops = {
334 .read8 = ssb_pcmcia_read8, 449 .read8 = ssb_pcmcia_read8,
@@ -337,6 +452,10 @@ const struct ssb_bus_ops ssb_pcmcia_ops = {
337 .write8 = ssb_pcmcia_write8, 452 .write8 = ssb_pcmcia_write8,
338 .write16 = ssb_pcmcia_write16, 453 .write16 = ssb_pcmcia_write16,
339 .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
340}; 459};
341 460
342static int ssb_pcmcia_sprom_command(struct ssb_bus *bus, u8 command) 461static int ssb_pcmcia_sprom_command(struct ssb_bus *bus, u8 command)