diff options
author | Michael Buesch <mb@bu3sch.de> | 2008-04-02 13:46:56 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-04-08 16:44:40 -0400 |
commit | d625a29ba649a4df6027520ffc378f23c0e6883e (patch) | |
tree | 07b895d38717e24e655948c963f4287f551df42f /drivers/ssb/main.c | |
parent | 93af2614513103216038afa708718295e7016dbb (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/main.c')
-rw-r--r-- | drivers/ssb/main.c | 102 |
1 files changed, 102 insertions, 0 deletions
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 | ||
559 | static 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 | |||
558 | static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value) | 607 | static 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 | ||
632 | static 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). */ |
583 | static const struct ssb_bus_ops ssb_ssb_ops = { | 681 | static 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 | ||
592 | static int ssb_fetch_invariants(struct ssb_bus *bus, | 694 | static int ssb_fetch_invariants(struct ssb_bus *bus, |