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/pci.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/pci.c')
-rw-r--r-- | drivers/ssb/pci.c | 70 |
1 files changed, 70 insertions, 0 deletions
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 | ||
617 | static 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; | ||
646 | error: | ||
647 | memset(buffer, 0xFF, count); | ||
648 | } | ||
649 | #endif /* CONFIG_SSB_BLOCKIO */ | ||
650 | |||
616 | static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value) | 651 | static 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 | ||
691 | static 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 */ |
656 | const struct ssb_bus_ops ssb_pci_ops = { | 722 | const 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 | ||
665 | static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev, | 735 | static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev, |