ssb: Add support for block-I/O
PATCH 1/1 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 <[email protected]>
---
John, please apply to 2.6.26
drivers/ssb/pci.c +70 -0
@@ -610,12 +610,47 @@ static u32 ssb_pci_read32(struct ssb_devif (unlikely (ssb_pci_switch_core (bus, dev)))return 0xFFFFFFFF ; }return ioread32 (bus->mmio + offset); } +#ifdef CONFIG_SSB_BLOCKIO +static void ssb_pci_block_read (struct ssb_device *dev,void *buffer, +size_t count,u16 offset,u8 reg_width) +{ +struct ssb_bus *bus = dev->bus; +void __iomem *addr = bus->mmio + offset; + +if (unlikely (ssb_pci_assert_buspower (bus))) + goto error; +if (unlikely (bus->mapped_device != dev)) { +if (unlikely (ssb_pci_switch_core (bus, dev))) + goto error; + } +switch (reg_width) { +case sizeof (u8): +ioread8_rep (addr, buffer, count); +break ; +case sizeof (u16): +SSB_WARN_ON (count &1 ); +ioread16_rep (addr, buffer, count >>1 ); +break ; +case sizeof (u32): +SSB_WARN_ON (count &3 ); +ioread32_rep (addr, buffer, count >>2 ); +break ; +default : +SSB_WARN_ON (1 ); + } + +return ; +error: +memset (buffer,0xFF , count); +} +#endif /* CONFIG_SSB_BLOCKIO */ +static void ssb_pci_write8 (struct ssb_device *dev,u16 offset,u8 value) {struct ssb_bus *bus = dev->bus;if (unlikely (ssb_pci_assert_buspower (bus)))return ;
@@ -649,20 +684,55 @@ static void ssb_pci_write32(struct ssb_dif (unlikely (ssb_pci_switch_core (bus, dev)))return ; }iowrite32 (value, bus->mmio + offset); } +#ifdef CONFIG_SSB_BLOCKIO +static void ssb_pci_block_write (struct ssb_device *dev,const void *buffer, +size_t count,u16 offset,u8 reg_width) +{ +struct ssb_bus *bus = dev->bus; +void __iomem *addr = bus->mmio + offset; + +if (unlikely (ssb_pci_assert_buspower (bus))) +return ; +if (unlikely (bus->mapped_device != dev)) { +if (unlikely (ssb_pci_switch_core (bus, dev))) +return ; + } +switch (reg_width) { +case sizeof (u8): +iowrite8_rep (addr, buffer, count); +break ; +case sizeof (u16): +SSB_WARN_ON (count &1 ); +iowrite16_rep (addr, buffer, count >>1 ); +break ; +case sizeof (u32): +SSB_WARN_ON (count &3 ); +iowrite32_rep (addr, buffer, count >>2 ); +break ; +default : +SSB_WARN_ON (1 ); + } +} +#endif /* CONFIG_SSB_BLOCKIO */ +/* Not "static", as it's used in main.c */ const struct ssb_bus_ops ssb_pci_ops = { .read8 = ssb_pci_read8, .read16 = ssb_pci_read16, .read32 = ssb_pci_read32, .write8 = ssb_pci_write8, .write16 = ssb_pci_write16, .write32 = ssb_pci_write32, +#ifdef CONFIG_SSB_BLOCKIO + .block_read = ssb_pci_block_read, + .block_write = ssb_pci_block_write, +#endif };static ssize_t ssb_pci_attr_sprom_show (struct device *pcidev,struct device_attribute *attr,char *buf) {
include/linux/ssb/ssb.h +19 -0
@@ -75,12 +75,18 @@ struct ssb_bus_ops {u8 (*read8)(struct ssb_device *dev,u16 offset);u16 (*read16)(struct ssb_device *dev,u16 offset);u32 (*read32)(struct ssb_device *dev,u16 offset);void (*write8)(struct ssb_device *dev,u16 offset,u8 value);void (*write16)(struct ssb_device *dev,u16 offset,u16 value);void (*write32)(struct ssb_device *dev,u16 offset,u32 value); +#ifdef CONFIG_SSB_BLOCKIO +void (*block_read)(struct ssb_device *dev,void *buffer, +size_t count,u16 offset,u8 reg_width); +void (*block_write)(struct ssb_device *dev,const void *buffer, +size_t count,u16 offset,u8 reg_width); +#endif };/* Core-ID values. */ #define SSB_DEV_CHIPCOMMON 0x800#define SSB_DEV_ILINE20 0x801
@@ -371,12 +377,25 @@ static inline void ssb_write16(struct ss dev->ops->write16 (dev, offset, value); }static inline void ssb_write32 (struct ssb_device *dev,u16 offset,u32 value) { dev->ops->write32 (dev, offset, value); } +#ifdef CONFIG_SSB_BLOCKIO +static inline void ssb_block_read (struct ssb_device *dev,void *buffer, +size_t count,u16 offset,u8 reg_width) +{ + dev->ops->block_read (dev, buffer, count, offset, reg_width); +} + +static inline void ssb_block_write (struct ssb_device *dev,const void *buffer, +size_t count,u16 offset,u8 reg_width) +{ + dev->ops->block_write (dev, buffer, count, offset, reg_width); +} +#endif /* CONFIG_SSB_BLOCKIO */ /* Translation (routing) bits that need to be ORed to DMA * addresses before they are given to a device. */ extern u32 ssb_dma_translation (struct ssb_device *dev);#define SSB_DMA_TRANSLATION_MASK 0xC0000000
drivers/ssb/pcmcia.c +119 -0
151 lines not on this page · raw message
drivers/ssb/Kconfig +5 -0
@@ -21,12 +21,17 @@ config SSB If unsure, say N. # Common SPROM support routines config SSB_SPROM bool +# Support for Block-I/O. SELECT this from the driver that needs it. +config SSB_BLOCKIO + bool + depends on SSB + config SSB_PCIHOST_POSSIBLE bool depends on SSB && (PCI = y || PCI = SSB) default y config SSB_PCIHOST
drivers/ssb/main.c +102 -0
134 lines not on this page · raw message