aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ssb/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ssb/main.c')
-rw-r--r--drivers/ssb/main.c102
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
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,