aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/ssb/Kconfig5
-rw-r--r--drivers/ssb/main.c102
-rw-r--r--drivers/ssb/pci.c70
-rw-r--r--drivers/ssb/pcmcia.c119
-rw-r--r--include/linux/ssb/ssb.h19
5 files changed, 315 insertions, 0 deletions
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig
index 0f7cce2560d1..cd845b8acd17 100644
--- a/drivers/ssb/Kconfig
+++ b/drivers/ssb/Kconfig
@@ -24,6 +24,11 @@ config SSB
24config SSB_SPROM 24config SSB_SPROM
25 bool 25 bool
26 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
27config SSB_PCIHOST_POSSIBLE 32config SSB_PCIHOST_POSSIBLE
28 bool 33 bool
29 depends on SSB && (PCI = y || PCI = SSB) 34 depends on SSB && (PCI = y || PCI = SSB)
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index 3e58db7ef608..19ddd2bd1057 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -555,6 +555,55 @@ static u32 ssb_ssb_read32(struct ssb_device *dev, u16 offset)
555 return readl(bus->mmio + offset); 555 return readl(bus->mmio + offset);
556} 556}
557 557
558#ifdef CONFIG_SSB_BLOCKIO
559static void ssb_ssb_block_read(struct ssb_device *dev, void *buffer,
560 size_t count, u16 offset, u8 reg_width)
561{
562 struct ssb_bus *bus = dev->bus;
563 void __iomem *addr;
564
565 offset += dev->core_index * SSB_CORE_SIZE;
566 addr = bus->mmio + offset;
567
568 switch (reg_width) {
569 case sizeof(u8): {
570 u8 *buf = buffer;
571
572 while (count) {
573 *buf = __raw_readb(addr);
574 buf++;
575 count--;
576 }
577 break;
578 }
579 case sizeof(u16): {
580 __le16 *buf = buffer;
581
582 SSB_WARN_ON(count & 1);
583 while (count) {
584 *buf = (__force __le16)__raw_readw(addr);
585 buf++;
586 count -= 2;
587 }
588 break;
589 }
590 case sizeof(u32): {
591 __le32 *buf = buffer;
592
593 SSB_WARN_ON(count & 3);
594 while (count) {
595 *buf = (__force __le32)__raw_readl(addr);
596 buf++;
597 count -= 4;
598 }
599 break;
600 }
601 default:
602 SSB_WARN_ON(1);
603 }
604}
605#endif /* CONFIG_SSB_BLOCKIO */
606
558static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value) 607static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value)
559{ 608{
560 struct ssb_bus *bus = dev->bus; 609 struct ssb_bus *bus = dev->bus;
@@ -579,6 +628,55 @@ static void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value)
579 writel(value, bus->mmio + offset); 628 writel(value, bus->mmio + offset);
580} 629}
581 630
631#ifdef CONFIG_SSB_BLOCKIO
632static void ssb_ssb_block_write(struct ssb_device *dev, const void *buffer,
633 size_t count, u16 offset, u8 reg_width)
634{
635 struct ssb_bus *bus = dev->bus;
636 void __iomem *addr;
637
638 offset += dev->core_index * SSB_CORE_SIZE;
639 addr = bus->mmio + offset;
640
641 switch (reg_width) {
642 case sizeof(u8): {
643 const u8 *buf = buffer;
644
645 while (count) {
646 __raw_writeb(*buf, addr);
647 buf++;
648 count--;
649 }
650 break;
651 }
652 case sizeof(u16): {
653 const __le16 *buf = buffer;
654
655 SSB_WARN_ON(count & 1);
656 while (count) {
657 __raw_writew((__force u16)(*buf), addr);
658 buf++;
659 count -= 2;
660 }
661 break;
662 }
663 case sizeof(u32): {
664 const __le32 *buf = buffer;
665
666 SSB_WARN_ON(count & 3);
667 while (count) {
668 __raw_writel((__force u32)(*buf), addr);
669 buf++;
670 count -= 4;
671 }
672 break;
673 }
674 default:
675 SSB_WARN_ON(1);
676 }
677}
678#endif /* CONFIG_SSB_BLOCKIO */
679
582/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */ 680/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
583static const struct ssb_bus_ops ssb_ssb_ops = { 681static const struct ssb_bus_ops ssb_ssb_ops = {
584 .read8 = ssb_ssb_read8, 682 .read8 = ssb_ssb_read8,
@@ -587,6 +685,10 @@ static const struct ssb_bus_ops ssb_ssb_ops = {
587 .write8 = ssb_ssb_write8, 685 .write8 = ssb_ssb_write8,
588 .write16 = ssb_ssb_write16, 686 .write16 = ssb_ssb_write16,
589 .write32 = ssb_ssb_write32, 687 .write32 = ssb_ssb_write32,
688#ifdef CONFIG_SSB_BLOCKIO
689 .block_read = ssb_ssb_block_read,
690 .block_write = ssb_ssb_block_write,
691#endif
590}; 692};
591 693
592static int ssb_fetch_invariants(struct ssb_bus *bus, 694static int ssb_fetch_invariants(struct ssb_bus *bus,
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index f1514b33cfae..904b1a8d0885 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -613,6 +613,41 @@ static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
613 return ioread32(bus->mmio + offset); 613 return ioread32(bus->mmio + offset);
614} 614}
615 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
616static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value) 651static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
617{ 652{
618 struct ssb_bus *bus = dev->bus; 653 struct ssb_bus *bus = dev->bus;
@@ -652,6 +687,37 @@ static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
652 iowrite32(value, bus->mmio + offset); 687 iowrite32(value, bus->mmio + offset);
653} 688}
654 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
655/* Not "static", as it's used in main.c */ 721/* Not "static", as it's used in main.c */
656const struct ssb_bus_ops ssb_pci_ops = { 722const struct ssb_bus_ops ssb_pci_ops = {
657 .read8 = ssb_pci_read8, 723 .read8 = ssb_pci_read8,
@@ -660,6 +726,10 @@ const struct ssb_bus_ops ssb_pci_ops = {
660 .write8 = ssb_pci_write8, 726 .write8 = ssb_pci_write8,
661 .write16 = ssb_pci_write16, 727 .write16 = ssb_pci_write16,
662 .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
663}; 733};
664 734
665static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev, 735static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
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)
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index a8ca396f810a..9f95afd0e9e3 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -78,6 +78,12 @@ struct ssb_bus_ops {
78 void (*write8)(struct ssb_device *dev, u16 offset, u8 value); 78 void (*write8)(struct ssb_device *dev, u16 offset, u8 value);
79 void (*write16)(struct ssb_device *dev, u16 offset, u16 value); 79 void (*write16)(struct ssb_device *dev, u16 offset, u16 value);
80 void (*write32)(struct ssb_device *dev, u16 offset, u32 value); 80 void (*write32)(struct ssb_device *dev, u16 offset, u32 value);
81#ifdef CONFIG_SSB_BLOCKIO
82 void (*block_read)(struct ssb_device *dev, void *buffer,
83 size_t count, u16 offset, u8 reg_width);
84 void (*block_write)(struct ssb_device *dev, const void *buffer,
85 size_t count, u16 offset, u8 reg_width);
86#endif
81}; 87};
82 88
83 89
@@ -374,6 +380,19 @@ static inline void ssb_write32(struct ssb_device *dev, u16 offset, u32 value)
374{ 380{
375 dev->ops->write32(dev, offset, value); 381 dev->ops->write32(dev, offset, value);
376} 382}
383#ifdef CONFIG_SSB_BLOCKIO
384static inline void ssb_block_read(struct ssb_device *dev, void *buffer,
385 size_t count, u16 offset, u8 reg_width)
386{
387 dev->ops->block_read(dev, buffer, count, offset, reg_width);
388}
389
390static inline void ssb_block_write(struct ssb_device *dev, const void *buffer,
391 size_t count, u16 offset, u8 reg_width)
392{
393 dev->ops->block_write(dev, buffer, count, offset, reg_width);
394}
395#endif /* CONFIG_SSB_BLOCKIO */
377 396
378 397
379/* Translation (routing) bits that need to be ORed to DMA 398/* Translation (routing) bits that need to be ORed to DMA